use std::path::{Path, PathBuf};
use crate::error::SessionError;
use crate::session_user::SessionUser;
const HELPER_BINARY: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/openjd_helper"));
pub(crate) fn create_helpers_dir(
working_dir: &Path,
user: Option<&dyn SessionUser>,
) -> Result<PathBuf, SessionError> {
let dir = working_dir.join(format!(".helpers-{}", uuid::Uuid::new_v4().simple()));
#[cfg(unix)]
{
nix::unistd::mkdir(&dir, nix::sys::stat::Mode::from_bits_truncate(0o700)).map_err(|e| {
SessionError::WorkingDirectory {
path: dir.clone(),
source: std::io::Error::from(e),
}
})?;
if let Some(u) = user.filter(|u| !u.is_process_user()) {
if let Ok(Some(grp)) = nix::unistd::Group::from_name(u.group()) {
nix::unistd::chown(&dir, None, Some(grp.gid)).map_err(|e| {
SessionError::PathPermissions {
path: dir.display().to_string(),
reason: e.to_string(),
}
})?;
}
use std::os::unix::fs::PermissionsExt;
std::fs::set_permissions(&dir, std::fs::Permissions::from_mode(0o750)).map_err(
|source| SessionError::WorkingDirectory {
path: dir.clone(),
source,
},
)?;
}
}
#[cfg(windows)]
{
std::fs::create_dir(&dir).map_err(|source| SessionError::WorkingDirectory {
path: dir.clone(),
source,
})?;
if let Some(u) = user.filter(|u| !u.is_process_user()) {
let process_user =
crate::win32::get_process_user().map_err(|e| SessionError::PathPermissions {
path: dir.display().to_string(),
reason: format!("Could not determine process user: {e}"),
})?;
crate::win32_permissions::set_permissions_protected(
&dir.to_string_lossy(),
&[process_user.as_str()],
&[],
&[u.user()],
)
.map_err(|reason| SessionError::PathPermissions {
path: dir.display().to_string(),
reason,
})?;
}
}
Ok(dir)
}
pub(crate) fn write_helper(
helpers_dir: &Path,
user: &dyn SessionUser,
) -> Result<PathBuf, SessionError> {
let ext = if cfg!(windows) { ".exe" } else { "" };
let filename = format!("h-{}{}", uuid::Uuid::new_v4().simple(), ext);
let path = helpers_dir.join(filename);
std::fs::write(&path, HELPER_BINARY).map_err(|source| SessionError::WorkingDirectory {
path: path.clone(),
source,
})?;
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
if let Ok(Some(grp)) = nix::unistd::Group::from_name(user.group()) {
nix::unistd::chown(&path, None, Some(grp.gid)).map_err(|e| {
SessionError::PathPermissions {
path: path.display().to_string(),
reason: e.to_string(),
}
})?;
}
std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o750)).map_err(
|source| SessionError::WorkingDirectory {
path: path.clone(),
source,
},
)?;
}
#[cfg(windows)]
{
if !user.is_process_user() {
let process_user =
crate::win32::get_process_user().map_err(|e| SessionError::PathPermissions {
path: path.display().to_string(),
reason: format!("Could not determine process user: {e}"),
})?;
crate::win32_permissions::set_permissions_protected(
&path.to_string_lossy(),
&[process_user.as_str()],
&[],
&[user.user()],
)
.map_err(|reason| SessionError::PathPermissions {
path: path.display().to_string(),
reason,
})?;
}
}
Ok(path)
}