diff --git a/Cargo.lock b/Cargo.lock index d079bea7e..d035b9b0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -215,9 +215,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "block-buffer" @@ -1216,7 +1216,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27d12c0aed7f1e24276a241aadc4cb8ea9f83000f34bc062b7cc2d51e3b0fabd" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.0", "debugid", "fxhash", "serde", @@ -1629,8 +1629,7 @@ checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libcgroups" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f6fef16f505466473eeeee906244e03a437beaf41ccd85c39355b4077890c9" +source = "git+https://github.com/containers/youki?rev=09e67372a892f22a89eeef62ff429c3cbcac6d41#09e67372a892f22a89eeef62ff429c3cbcac6d41" dependencies = [ "dbus", "errno", @@ -1649,13 +1648,11 @@ dependencies = [ [[package]] name = "libcontainer" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac48a05819bd5bd31390bd1874f5a94f711c248677fc908801de4789bdd1fbad" +source = "git+https://github.com/containers/youki?rev=09e67372a892f22a89eeef62ff429c3cbcac6d41#09e67372a892f22a89eeef62ff429c3cbcac6d41" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.0", "caps", "chrono", - "clone3", "fastrand", "futures", "libc", @@ -1882,7 +1879,7 @@ version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abbbc55ad7b13aac85f9401c796dcda1b864e07fcad40ad47792eaa8932ea502" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.0", "cfg-if 1.0.0", "libc", "memoffset 0.7.1", @@ -2127,7 +2124,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "059a34f111a9dee2ce1ac2826a68b24601c4298cfeb1a587c3cb493d5ab46f52" dependencies = [ "libc", - "nix 0.22.3", + "nix 0.26.3", ] [[package]] @@ -2448,9 +2445,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.3" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" +checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" dependencies = [ "aho-corasick", "memchr", @@ -2460,9 +2457,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" +checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" dependencies = [ "aho-corasick", "memchr", @@ -2471,9 +2468,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "reqwest" @@ -2598,7 +2595,7 @@ version = "0.38.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "172891ebdceb05aa0005f533a6cbfca599ddd7d966f6f5d4d9b2e70478e70399" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.0", "errno", "libc", "linux-raw-sys 0.4.5", @@ -2982,7 +2979,7 @@ version = "0.25.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10081a99cbecbc363d381b9503563785f0b02735fccbb0d4c1a2cb3d39f7e7fe" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.0", "cap-fs-ext", "cap-std", "fd-lock", @@ -4263,7 +4260,7 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4857cedf8371f690bb6782a3e2b065c54d1b6661be068aaf3eac8b45e813fdf8" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.0", "windows-sys 0.48.0", ] diff --git a/Cargo.toml b/Cargo.toml index 4fb618b38..bf9adea04 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,8 @@ thiserror = "1.0" libc = "0.2.147" oci-spec = { version = "0.6.1", features = ["runtime"] } sha256 = "1.4.0" -libcontainer = { version = "0.1", default-features = false } +# TODO: once lincontainer releases 0.2, switch to released version. The current commit is the tip of the tree from `youki` and a release candidate. +libcontainer = { git = "https://github.com/containers/youki", rev = "09e67372a892f22a89eeef62ff429c3cbcac6d41", default-features = false } windows-sys = { version = "0.48" } [profile.release] diff --git a/crates/containerd-shim-wasm/src/libcontainer_instance/container_executor.rs b/crates/containerd-shim-wasm/src/libcontainer_instance/container_executor.rs index 47afd5e7d..81c999aff 100644 --- a/crates/containerd-shim-wasm/src/libcontainer_instance/container_executor.rs +++ b/crates/containerd-shim-wasm/src/libcontainer_instance/container_executor.rs @@ -3,12 +3,12 @@ use std::io::Read; use std::path::PathBuf; use libcontainer::workload::default::DefaultExecutor; -use libcontainer::workload::{Executor, ExecutorError}; +use libcontainer::workload::{Executor, ExecutorError, ExecutorValidationError}; use oci_spec::runtime::Spec; use crate::sandbox::{oci, Stdio}; -#[derive(Default)] +#[derive(Clone)] pub struct LinuxContainerExecutor { stdio: Stdio, default_executor: DefaultExecutor, @@ -18,7 +18,7 @@ impl LinuxContainerExecutor { pub fn new(stdio: Stdio) -> Self { Self { stdio, - ..Default::default() + default_executor: DefaultExecutor {}, } } } @@ -32,82 +32,86 @@ impl Executor for LinuxContainerExecutor { self.default_executor.exec(spec) } - fn can_handle(&self, spec: &Spec) -> bool { - let args = oci::get_args(spec); + fn validate(&self, spec: &Spec) -> Result<(), ExecutorValidationError> { + self.default_executor.validate(spec)?; - if args.is_empty() { - return false; - } + can_handle(spec) + .then_some(()) + .ok_or(ExecutorValidationError::InvalidArg) + } +} - let executable = args[0].as_str(); +fn can_handle(spec: &Spec) -> bool { + let args = oci::get_args(spec); - // mostly follows youki's verify_binary implementation - // https://github.com/containers/youki/blob/2d6fd7650bb0f22a78fb5fa982b5628f61fe25af/crates/libcontainer/src/process/container_init_process.rs#L106 - let path = if executable.contains('/') { - PathBuf::from(executable) - } else { - let path = std::env::var("PATH").unwrap_or_default(); - // check each path in $PATH - let mut found = false; - let mut found_path = PathBuf::default(); - for p in path.split(':') { - let path = PathBuf::from(p).join(executable); - if path.exists() { - found = true; - found_path = path; - break; - } - } - if !found { - return false; - } - found_path - }; + if args.is_empty() { + return false; + } - // check execute permission - use std::os::unix::fs::PermissionsExt; - let metadata = path.metadata(); - if metadata.is_err() { - log::info!("failed to get metadata of {:?}", path); - return false; + let executable = args[0].as_str(); + + // mostly follows youki's verify_binary implementation + // https://github.com/containers/youki/blob/2d6fd7650bb0f22a78fb5fa982b5628f61fe25af/crates/libcontainer/src/process/container_init_process.rs#L106 + let path = if executable.contains('/') { + PathBuf::from(executable) + } else { + let path = std::env::var("PATH").unwrap_or_default(); + // check each path in $PATH + let mut found = false; + let mut found_path = PathBuf::default(); + for p in path.split(':') { + let path = PathBuf::from(p).join(executable); + if path.exists() { + found = true; + found_path = path; + break; + } } - let metadata = metadata.unwrap(); - let permissions = metadata.permissions(); - if !metadata.is_file() || permissions.mode() & 0o001 == 0 { - log::info!("{} is not a file or has no execute permission", executable); + if !found { return false; } + found_path + }; - // check the shebang and ELF magic number - // https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header - let mut buffer = [0; 4]; + // check execute permission + use std::os::unix::fs::PermissionsExt; + let metadata = path.metadata(); + if metadata.is_err() { + log::info!("failed to get metadata of {:?}", path); + return false; + } + let metadata = metadata.unwrap(); + let permissions = metadata.permissions(); + if !metadata.is_file() || permissions.mode() & 0o001 == 0 { + log::info!("{} is not a file or has no execute permission", executable); + return false; + } + + // check the shebang and ELF magic number + // https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header + let mut buffer = [0; 4]; - let file = OpenOptions::new().read(true).open(path); - if file.is_err() { - log::info!("failed to open {}", executable); + let file = OpenOptions::new().read(true).open(path); + if file.is_err() { + log::info!("failed to open {}", executable); + return false; + } + let mut file = file.unwrap(); + match file.read_exact(&mut buffer) { + Ok(_) => {} + Err(err) => { + log::info!("failed to read shebang of {}: {}", executable, err); return false; } - let mut file = file.unwrap(); - match file.read_exact(&mut buffer) { - Ok(_) => {} - Err(err) => { - log::info!("failed to read shebang of {}: {}", executable, err); - return false; - } - } - match buffer { - // ELF magic number - [0x7f, 0x45, 0x4c, 0x46] => true, - // shebang - [0x23, 0x21, ..] => true, - _ => { - log::info!("{} is not a valid script or elf file", executable); - false - } - } } - - fn name(&self) -> &'static str { - self.default_executor.name() + match buffer { + // ELF magic number + [0x7f, 0x45, 0x4c, 0x46] => true, + // shebang + [0x23, 0x21, ..] => true, + _ => { + log::info!("{} is not a valid script or elf file", executable); + false + } } } diff --git a/crates/containerd-shim-wasmedge/src/executor.rs b/crates/containerd-shim-wasmedge/src/executor.rs index 983bf12e4..25636d190 100644 --- a/crates/containerd-shim-wasmedge/src/executor.rs +++ b/crates/containerd-shim-wasmedge/src/executor.rs @@ -1,8 +1,9 @@ use std::path::PathBuf; use anyhow::Result; +use containerd_shim_wasm::libcontainer_instance::LinuxContainerExecutor; use containerd_shim_wasm::sandbox::{oci, Stdio}; -use libcontainer::workload::{Executor, ExecutorError}; +use libcontainer::workload::{Executor, ExecutorError, ExecutorValidationError}; use log::debug; use oci_spec::runtime::Spec; use wasmedge_sdk::config::{CommonConfigOptions, ConfigBuilder, HostRegistrationConfigOptions}; @@ -10,6 +11,7 @@ use wasmedge_sdk::{params, VmBuilder}; const EXECUTOR_NAME: &str = "wasmedge"; +#[derive(Clone)] pub struct WasmEdgeExecutor { stdio: Stdio, } @@ -22,45 +24,45 @@ impl WasmEdgeExecutor { impl Executor for WasmEdgeExecutor { fn exec(&self, spec: &Spec) -> Result<(), ExecutorError> { - // parse wasi parameters - let args = oci::get_args(spec); - if args.is_empty() { - return Err(ExecutorError::InvalidArg); - } + match can_handle(spec) { + Ok(()) => { + // parse wasi parameters + let args = oci::get_args(spec); + if args.is_empty() { + return Err(ExecutorError::InvalidArg); + } - let vm = self - .prepare(args, spec) - .map_err(|err| ExecutorError::Other(format!("failed to prepare function: {}", err)))?; - - // TODO: How to get exit code? - // This was relatively straight forward in go, but wasi and wasmtime are totally separate things in rust - let (module_name, method) = oci::get_module(spec); - debug!("running {:?} with method {}", module_name, method); - match vm.run_func(Some("main"), method, params!()) { - Ok(_) => std::process::exit(0), - Err(_) => std::process::exit(137), - }; - } + let vm = self.prepare(args, spec).map_err(|err| { + ExecutorError::Other(format!("failed to prepare function: {}", err)) + })?; - fn can_handle(&self, spec: &Spec) -> bool { - // check if the entrypoint of the spec is a wasm binary. - let (module_name, _method) = oci::get_module(spec); - let module_name = match module_name { - Some(m) => m, - None => { - log::info!("WasmEdge cannot handle this workload, no arguments provided"); - return false; + // TODO: How to get exit code? + // This was relatively straight forward in go, but wasi and wasmtime are totally separate things in rust + let (module_name, method) = oci::get_module(spec); + debug!("running {:?} with method {}", module_name, method); + match vm.run_func(Some("main"), method, params!()) { + Ok(_) => std::process::exit(0), + Err(_) => std::process::exit(137), + }; } - }; - let path = PathBuf::from(module_name); - - path.extension() - .map(|ext| ext.to_ascii_lowercase()) - .is_some_and(|ext| ext == "wasm" || ext == "wat") + Err(ExecutorValidationError::CantHandle(_)) => { + LinuxContainerExecutor::new(self.stdio.clone()).exec(spec)?; + Ok(()) + } + Err(_) => Err(ExecutorError::InvalidArg), + } } - fn name(&self) -> &'static str { - EXECUTOR_NAME + fn validate(&self, spec: &Spec) -> std::result::Result<(), ExecutorValidationError> { + match can_handle(spec) { + Ok(()) => Ok(()), + Err(ExecutorValidationError::CantHandle(_)) => { + LinuxContainerExecutor::new(self.stdio.clone()).validate(spec)?; + + Ok(()) + } + Err(err) => Err(err), + } } } @@ -111,3 +113,24 @@ fn env_to_wasi(spec: &Spec) -> Vec { .unwrap_or(&default); env.to_vec() } + +fn can_handle(spec: &Spec) -> Result<(), ExecutorValidationError> { + // check if the entrypoint of the spec is a wasm binary. + let (module_name, _method) = oci::get_module(spec); + let module_name = match module_name { + Some(m) => m, + None => { + log::info!("WasmEdge cannot handle this workload, no arguments provided"); + return Err(ExecutorValidationError::CantHandle(EXECUTOR_NAME)); + } + }; + let path = PathBuf::from(module_name); + + path.extension() + .map(|ext| ext.to_ascii_lowercase()) + .is_some_and(|ext| ext == "wasm" || ext == "wat") + .then_some(()) + .ok_or(ExecutorValidationError::CantHandle(EXECUTOR_NAME))?; + + Ok(()) +} diff --git a/crates/containerd-shim-wasmedge/src/instance/instance_linux.rs b/crates/containerd-shim-wasmedge/src/instance/instance_linux.rs index af7a726aa..60c928e78 100644 --- a/crates/containerd-shim-wasmedge/src/instance/instance_linux.rs +++ b/crates/containerd-shim-wasmedge/src/instance/instance_linux.rs @@ -2,14 +2,14 @@ use std::fs; use std::path::PathBuf; use std::sync::{Arc, Condvar, Mutex}; -use containerd_shim_wasm::libcontainer_instance::{LibcontainerInstance, LinuxContainerExecutor}; +use containerd_shim_wasm::libcontainer_instance::LibcontainerInstance; use containerd_shim_wasm::sandbox::error::Error; use containerd_shim_wasm::sandbox::instance::ExitCode; use containerd_shim_wasm::sandbox::instance_utils::determine_rootdir; use containerd_shim_wasm::sandbox::{InstanceConfig, Stdio}; use libcontainer::container::builder::ContainerBuilder; use libcontainer::container::Container; -use libcontainer::syscall::syscall::create_syscall; +use libcontainer::syscall::syscall::SyscallType; use crate::executor::WasmEdgeExecutor; @@ -63,14 +63,9 @@ impl LibcontainerInstance for Wasi { fn build_container(&self) -> std::result::Result { fs::create_dir_all(&self.rootdir)?; - let syscall = create_syscall(); let err_others = |err| Error::Others(format!("failed to create container: {}", err)); - let default_executor = Box::new(LinuxContainerExecutor::new(self.stdio.clone())); - let wasmedge_executor = Box::new(WasmEdgeExecutor::new(self.stdio.clone())); - - let container = ContainerBuilder::new(self.id.clone(), syscall.as_ref()) - .with_executor(vec![default_executor, wasmedge_executor]) - .map_err(err_others)? + let container = ContainerBuilder::new(self.id.clone(), SyscallType::Linux) + .with_executor(WasmEdgeExecutor::new(self.stdio.clone())) .with_root_path(self.rootdir.clone()) .map_err(err_others)? .as_init(&self.bundle) diff --git a/crates/containerd-shim-wasmtime/src/executor.rs b/crates/containerd-shim-wasmtime/src/executor.rs index f5652a9e6..4fe71b351 100644 --- a/crates/containerd-shim-wasmtime/src/executor.rs +++ b/crates/containerd-shim-wasmtime/src/executor.rs @@ -2,8 +2,9 @@ use std::fs::OpenOptions; use std::path::PathBuf; use anyhow::{anyhow, Result}; +use containerd_shim_wasm::libcontainer_instance::LinuxContainerExecutor; use containerd_shim_wasm::sandbox::{oci, Stdio}; -use libcontainer::workload::{Executor, ExecutorError}; +use libcontainer::workload::{Executor, ExecutorError, ExecutorValidationError}; use oci_spec::runtime::Spec; use wasmtime::{Engine, Linker, Module, Store}; use wasmtime_wasi::WasiCtxBuilder; @@ -12,6 +13,7 @@ use crate::oci_wasmtime::{self, wasi_dir}; const EXECUTOR_NAME: &str = "wasmtime"; +#[derive(Clone)] pub struct WasmtimeExecutor { stdio: Stdio, engine: Engine, @@ -25,47 +27,42 @@ impl WasmtimeExecutor { impl Executor for WasmtimeExecutor { fn exec(&self, spec: &Spec) -> Result<(), ExecutorError> { - let args = oci::get_args(spec); - if args.is_empty() { - return Err(ExecutorError::InvalidArg); - } - - let (mut store, f) = self - .prepare(spec, args) - .map_err(|err| ExecutorError::Other(format!("failed to prepare function: {}", err)))?; - - log::info!("calling start function"); - match f.call(&mut store, &[], &mut []) { - Ok(_) => std::process::exit(0), - Err(_) => std::process::exit(137), - }; - } - - fn can_handle(&self, spec: &Spec) -> bool { - // check if the entrypoint of the spec is a wasm binary. - let (module_name, _method) = oci::get_module(spec); - let module_name = match module_name { - Some(m) => m, - None => { - log::info!("Wasmtime cannot handle this workload, no arguments provided"); - return false; + match can_handle(spec) { + Ok(()) => { + let args = oci::get_args(spec); + if args.is_empty() { + return Err(ExecutorError::InvalidArg); + } + + let (mut store, f) = self.prepare(spec, args).map_err(|err| { + ExecutorError::Other(format!("failed to prepare function: {}", err)) + })?; + + log::info!("calling start function"); + match f.call(&mut store, &[], &mut []) { + Ok(_) => std::process::exit(0), + Err(_) => std::process::exit(137), + }; } - }; - let path = PathBuf::from(module_name); + Err(ExecutorValidationError::CantHandle(_)) => { + LinuxContainerExecutor::new(self.stdio.clone()).exec(spec)?; - // TODO: do we need to validate the wasm binary? - // ```rust - // let bytes = std::fs::read(path).unwrap(); - // wasmparser::validate(&bytes).is_ok() - // ``` - - path.extension() - .map(|ext| ext.to_ascii_lowercase()) - .is_some_and(|ext| ext == "wasm" || ext == "wat") + Ok(()) + } + Err(_) => Err(ExecutorError::InvalidArg), + } } - fn name(&self) -> &'static str { - EXECUTOR_NAME + fn validate(&self, spec: &Spec) -> std::result::Result<(), ExecutorValidationError> { + match can_handle(spec) { + Ok(()) => Ok(()), + Err(ExecutorValidationError::CantHandle(_)) => { + LinuxContainerExecutor::new(self.stdio.clone()).validate(spec)?; + + Ok(()) + } + Err(err) => Err(err), + } } } @@ -119,3 +116,30 @@ impl WasmtimeExecutor { Ok((store, start_func)) } } + +fn can_handle(spec: &Spec) -> Result<(), ExecutorValidationError> { + // check if the entrypoint of the spec is a wasm binary. + let (module_name, _method) = oci::get_module(spec); + let module_name = match module_name { + Some(m) => m, + None => { + log::info!("Wasmtime cannot handle this workload, no arguments provided"); + return Err(ExecutorValidationError::CantHandle(EXECUTOR_NAME)); + } + }; + let path = PathBuf::from(module_name); + + // TODO: do we need to validate the wasm binary? + // ```rust + // let bytes = std::fs::read(path).unwrap(); + // wasmparser::validate(&bytes).is_ok() + // ``` + + path.extension() + .map(|ext| ext.to_ascii_lowercase()) + .is_some_and(|ext| ext == "wasm" || ext == "wat") + .then_some(()) + .ok_or(ExecutorValidationError::CantHandle(EXECUTOR_NAME))?; + + Ok(()) +} diff --git a/crates/containerd-shim-wasmtime/src/instance/instance_linux.rs b/crates/containerd-shim-wasmtime/src/instance/instance_linux.rs index 1a148a32a..01df4f6e8 100644 --- a/crates/containerd-shim-wasmtime/src/instance/instance_linux.rs +++ b/crates/containerd-shim-wasmtime/src/instance/instance_linux.rs @@ -1,7 +1,7 @@ use std::path::PathBuf; use std::sync::{Arc, Condvar, Mutex}; -use containerd_shim_wasm::libcontainer_instance::{LibcontainerInstance, LinuxContainerExecutor}; +use containerd_shim_wasm::libcontainer_instance::LibcontainerInstance; use containerd_shim_wasm::sandbox::error::Error; use containerd_shim_wasm::sandbox::instance::ExitCode; use containerd_shim_wasm::sandbox::instance_utils::determine_rootdir; @@ -9,7 +9,7 @@ use containerd_shim_wasm::sandbox::stdio::Stdio; use containerd_shim_wasm::sandbox::InstanceConfig; use libcontainer::container::builder::ContainerBuilder; use libcontainer::container::Container; -use libcontainer::syscall::syscall::create_syscall; +use libcontainer::syscall::syscall::SyscallType; use crate::executor::WasmtimeExecutor; @@ -67,16 +67,11 @@ impl LibcontainerInstance for Wasi { fn build_container(&self) -> std::result::Result { let engine = self.engine.clone(); - let syscall = create_syscall(); self.stdio.redirect()?; let err_others = |err| Error::Others(format!("failed to create container: {}", err)); - let wasmtime_executor = Box::new(WasmtimeExecutor::new(self.stdio.clone(), engine)); - let default_executor = Box::new(LinuxContainerExecutor::new(self.stdio.clone())); - - let container = ContainerBuilder::new(self.id.clone(), syscall.as_ref()) - .with_executor(vec![default_executor, wasmtime_executor]) - .map_err(err_others)? + let container = ContainerBuilder::new(self.id.clone(), SyscallType::Linux) + .with_executor(WasmtimeExecutor::new(self.stdio.clone(), engine)) .with_root_path(self.rootdir.clone()) .map_err(err_others)? .as_init(&self.bundle)