2021-03-27 12:08:13 +01:00
|
|
|
use std::ffi::CString;
|
2021-04-10 16:36:41 +02:00
|
|
|
use std::path::{Path, PathBuf};
|
2021-03-27 12:08:13 +01:00
|
|
|
|
2021-04-07 14:07:01 +02:00
|
|
|
use anyhow::{bail, Result};
|
2021-05-15 08:51:12 +02:00
|
|
|
use nix::{env::clearenv, errno::Errno, unistd};
|
2021-03-27 12:08:13 +01:00
|
|
|
|
2021-04-07 14:07:01 +02:00
|
|
|
pub trait PathBufExt {
|
|
|
|
fn as_in_container(&self) -> Result<PathBuf>;
|
2021-04-10 16:36:41 +02:00
|
|
|
fn join_absolute_path(&self, p: &Path) -> Result<PathBuf>;
|
2021-04-07 14:07:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl PathBufExt for PathBuf {
|
|
|
|
fn as_in_container(&self) -> Result<PathBuf> {
|
|
|
|
if self.is_relative() {
|
|
|
|
bail!("Relative path cannnot be converted to the path in the container.")
|
|
|
|
} else {
|
|
|
|
let path_string = self.to_string_lossy().into_owned();
|
|
|
|
Ok(PathBuf::from(path_string[1..].to_string()))
|
|
|
|
}
|
|
|
|
}
|
2021-04-10 16:36:41 +02:00
|
|
|
|
|
|
|
fn join_absolute_path(&self, p: &Path) -> Result<PathBuf> {
|
|
|
|
if !p.is_absolute() && !p.as_os_str().is_empty() {
|
|
|
|
bail!(
|
|
|
|
"connnot join {:?} because it is not the absolute path.",
|
|
|
|
p.display()
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Ok(PathBuf::from(format!("{}{}", self.display(), p.display())))
|
|
|
|
}
|
2021-04-07 14:07:01 +02:00
|
|
|
}
|
|
|
|
|
2021-05-15 08:51:12 +02:00
|
|
|
pub fn do_exec(path: impl AsRef<Path>, args: &[String], envs: &[String]) -> Result<()> {
|
2021-05-05 13:54:11 +02:00
|
|
|
let p = CString::new(path.as_ref().to_string_lossy().to_string())?;
|
2021-03-27 12:08:13 +01:00
|
|
|
let a: Vec<CString> = args
|
|
|
|
.iter()
|
|
|
|
.map(|s| CString::new(s.to_string()).unwrap_or_default())
|
|
|
|
.collect();
|
2021-05-15 08:51:12 +02:00
|
|
|
let envs: Vec<CString> = envs
|
|
|
|
.iter()
|
|
|
|
.map(|s| CString::new(s.to_string()).unwrap_or_default())
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
clearenv()?;
|
|
|
|
}
|
|
|
|
for e in envs {
|
|
|
|
putenv(&e)?
|
|
|
|
}
|
2021-03-27 12:08:13 +01:00
|
|
|
|
|
|
|
unistd::execvp(&p, &a)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-05-15 08:51:12 +02:00
|
|
|
#[inline]
|
|
|
|
fn putenv(string: &CString) -> nix::Result<()> {
|
|
|
|
let ptr = string.clone().into_raw();
|
|
|
|
let res = unsafe { libc::putenv(ptr as *mut libc::c_char) };
|
|
|
|
Errno::result(res).map(drop)
|
|
|
|
}
|
|
|
|
|
2021-03-27 12:08:13 +01:00
|
|
|
// TODO implement
|
|
|
|
pub fn set_name(_name: &str) -> Result<()> {
|
|
|
|
Ok(())
|
|
|
|
}
|
2021-04-29 10:34:23 +02:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_join_absolute_path() {
|
|
|
|
assert_eq!(
|
|
|
|
PathBuf::from("sample/a/")
|
|
|
|
.join_absolute_path(&PathBuf::from("/b"))
|
|
|
|
.unwrap(),
|
|
|
|
PathBuf::from("sample/a/b")
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_join_absolute_path_error() {
|
|
|
|
assert_eq!(
|
|
|
|
PathBuf::from("sample/a/")
|
|
|
|
.join_absolute_path(&PathBuf::from("b/c"))
|
|
|
|
.is_err(),
|
|
|
|
true
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|