use serde_json::to_string;
use std::collections::VecDeque;
#[cfg(windows)]
use std::ffi::OsString;
#[cfg(unix)]
use std::ffi::{CStr, CString};
use std::fs;
use std::io;
#[cfg(unix)]
use std::os::fd::{AsRawFd, FromRawFd, OwnedFd, RawFd};
#[cfg(unix)]
use std::os::unix::ffi::OsStrExt;
#[cfg(unix)]
use std::os::unix::fs::MetadataExt;
#[cfg(windows)]
use std::os::windows::ffi::{OsStrExt, OsStringExt};
#[cfg(windows)]
use std::os::windows::fs::OpenOptionsExt;
#[cfg(windows)]
use std::os::windows::io::{AsRawHandle, FromRawHandle, OwnedHandle};
use std::path::{Component, Path, PathBuf};
use std::process::Command;
use std::sync::Arc;
use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
use std::sync::{Condvar, Mutex, OnceLock};
use std::time::Duration;
#[cfg(windows)]
use windows_sys::Win32::Foundation::GENERIC_READ;
#[cfg(windows)]
use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE;
#[cfg(windows)]
use windows_sys::Win32::Storage::FileSystem::{
BY_HANDLE_FILE_INFORMATION, CreateFileW, FILE_ATTRIBUTE_DIRECTORY, FILE_ATTRIBUTE_READONLY,
FILE_ATTRIBUTE_REPARSE_POINT, FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT,
FILE_NAME_NORMALIZED, FILE_READ_ATTRIBUTES, FILE_SHARE_DELETE, FILE_SHARE_READ,
FILE_SHARE_WRITE, GetFileAttributesW, GetFileInformationByHandle, GetFinalPathNameByHandleW,
INVALID_FILE_ATTRIBUTES, OPEN_EXISTING, SetFileAttributesW, VOLUME_NAME_DOS,
};
use crate::runtime::encoding::RuntimeTextEncoding;
use crate::runtime::managed_package::{
ManagedFilesystemObjectIdentity, ManagedRuntimePackageContext,
};
use crate::runtime::managed_runtime::{
ManagedRuntimeEnvLease, ManagedRuntimeEnvPlan, acquire_ready_managed_env_lease,
configure_managed_command_base_environment,
current_managed_runtime_persistent_session_capability, ensure_managed_env,
resolve_node_env_plan, resolve_python_env_plan,
};
use crate::runtime::path::{host_process_path_argument, render_host_visible_path};
use crate::runtime::process_session::{
ManagedProcessSessionCleanup, ManagedProcessSessionCore, ManagedProcessSessionLaunchOptions,
ManagedProcessSessionObserver,
};
use crate::runtime_logging::warn as log_warn;
static NEXT_MANAGED_PACKAGE_SNAPSHOT: AtomicU64 = AtomicU64::new(0);
const MAX_MANAGED_PACKAGE_SNAPSHOT_CREATE_ATTEMPTS: usize = 64;
const MANAGED_SNAPSHOT_CLEANUP_CAPACITY: usize = 256;
const MANAGED_SNAPSHOT_CLEANUP_RETRY_DELAY: Duration = Duration::from_millis(100);
static MANAGED_SNAPSHOT_CLEANUP_RETRY: OnceLock<Result<ManagedSnapshotCleanupRetry, String>> =
OnceLock::new();
#[cfg(windows)]
const WINDOWS_DELETE_ACCESS: u32 = 0x0001_0000;
pub(crate) struct ManagedRuntimeSessionOpenRequest {
pub(crate) file: String,
pub(crate) args: Vec<String>,
pub(crate) cwd: Option<String>,
pub(crate) stdout_encoding: RuntimeTextEncoding,
pub(crate) stderr_encoding: RuntimeTextEncoding,
pub(crate) stdin_encoding: RuntimeTextEncoding,
pub(crate) buffer_limit_bytes: usize,
}
pub(crate) struct ManagedRuntimeSessionLaunch {
pub(crate) core: ManagedProcessSessionCore,
pub(crate) cleanup: Option<ManagedProcessSessionCleanup>,
}
#[derive(Debug)]
pub(crate) struct ManagedPackageSnapshot {
ownership: Option<ManagedSnapshotCleanupOwnership>,
execution_pin: Option<ManagedSnapshotExecutionPin>,
}
#[derive(Debug)]
enum ManagedSnapshotExecutionPin {
#[cfg(unix)]
Unix {
directory: OwnedFd,
},
#[cfg(windows)]
Windows {
_handles: Vec<fs::File>,
},
}
#[derive(Debug)]
struct ManagedSnapshotCleanupOwnership {
record: ManagedSnapshotCleanupRecord,
permit: ManagedSnapshotCleanupPermit,
}
#[derive(Debug)]
struct ManagedSnapshotCleanupRecord {
_environment_lease: Option<ManagedRuntimeEnvLease>,
snapshots_root: PathBuf,
snapshot_root: PathBuf,
quarantine_root: Option<PathBuf>,
orphan_quarantine_root: Option<PathBuf>,
snapshot_present: bool,
identity: Option<ManagedPackageSnapshotIdentity>,
error_reported: bool,
}
#[derive(Debug)]
struct ManagedSnapshotCleanupRetry {
queue: Arc<ManagedSnapshotCleanupQueue>,
reserved: Arc<AtomicUsize>,
}
#[derive(Debug)]
struct ManagedSnapshotCleanupQueue {
records: Mutex<VecDeque<ManagedSnapshotCleanupRecord>>,
changed: Condvar,
}
#[derive(Debug)]
struct ManagedSnapshotCleanupPermit {
retry: &'static ManagedSnapshotCleanupRetry,
reserved: bool,
}
#[derive(Clone, Debug, Eq, PartialEq)]
struct ManagedPackageSnapshotIdentity {
#[cfg(unix)]
device: u64,
#[cfg(unix)]
inode: u64,
#[cfg(windows)]
volume_serial_number: u32,
#[cfg(windows)]
file_index: u64,
}
impl ManagedPackageSnapshot {
pub(crate) fn root(&self) -> &Path {
&self
.ownership
.as_ref()
.expect("live managed snapshot must retain cleanup ownership")
.record
.snapshot_root
}
pub(crate) fn execution_source_path(&self, relative_path: &str) -> Result<PathBuf, String> {
let pin = self
.execution_pin
.as_ref()
.ok_or_else(|| "managed snapshot execution pin is unavailable".to_string())?;
#[cfg(target_os = "linux")]
{
let ManagedSnapshotExecutionPin::Unix { directory } = pin;
let descriptor_root = PathBuf::from(format!("/proc/self/fd/{}", directory.as_raw_fd()));
Ok(descriptor_root.join(relative_path))
}
#[cfg(target_os = "macos")]
{
let ManagedSnapshotExecutionPin::Unix { directory } = pin;
macos_snapshot_execution_source_path(
directory.as_raw_fd(),
Path::new(relative_path),
self.root(),
)
}
#[cfg(all(unix, not(any(target_os = "linux", target_os = "macos"))))]
{
let _ = pin;
Err("managed snapshot execution paths are unsupported on this Unix target".to_string())
}
#[cfg(windows)]
{
let _ = pin;
Ok(self.root().join(relative_path))
}
#[cfg(not(any(unix, windows)))]
{
let _ = pin;
Err("managed snapshot execution paths are unsupported".to_string())
}
}
pub(crate) fn node_execution_source_path(
&self,
relative_path: &str,
) -> Result<PathBuf, String> {
let source_path = self.execution_source_path(relative_path)?;
#[cfg(windows)]
{
windows_non_verbatim_path(&source_path)
}
#[cfg(not(windows))]
{
Ok(source_path)
}
}
pub(crate) fn worker_source_path(&self, relative_path: &str) -> Result<PathBuf, String> {
let relative = Path::new(relative_path);
if relative_path.is_empty()
|| !relative
.components()
.all(|component| matches!(component, Component::Normal(_)))
{
return Err("managed worker source must be a non-empty safe relative path".to_string());
}
let pin = self
.execution_pin
.as_ref()
.ok_or_else(|| "managed snapshot execution pin is unavailable".to_string())?;
#[cfg(unix)]
{
let ManagedSnapshotExecutionPin::Unix { directory } = pin;
validate_unix_snapshot_regular_file(directory.as_raw_fd(), relative, self.root())?;
Ok(relative.to_path_buf())
}
#[cfg(windows)]
{
let _ = pin;
let source = self.root().join(relative);
ensure_regular_file(&source, "managed worker snapshot source")?;
Ok(source)
}
#[cfg(not(any(unix, windows)))]
{
let _ = pin;
Err("managed worker snapshot source paths are unsupported".to_string())
}
}
pub(crate) fn node_worker_source_path(&self, relative_path: &str) -> Result<PathBuf, String> {
let source_path = self.worker_source_path(relative_path)?;
#[cfg(windows)]
{
windows_non_verbatim_path(&source_path)
}
#[cfg(not(windows))]
{
Ok(source_path)
}
}
pub(crate) fn python_worker_import_root(&self) -> Result<PathBuf, String> {
#[cfg(unix)]
{
Ok(PathBuf::from("."))
}
#[cfg(windows)]
{
Ok(self.root().to_path_buf())
}
#[cfg(not(any(unix, windows)))]
{
Err("managed Python worker import roots are unsupported".to_string())
}
}
pub(crate) fn configure_source_inheritance(&self, command: &mut Command) -> Result<(), String> {
#[cfg(unix)]
{
use std::os::unix::process::CommandExt;
let Some(ManagedSnapshotExecutionPin::Unix { directory }) = self.execution_pin.as_ref()
else {
return Err("managed snapshot Unix execution pin is unavailable".to_string());
};
let directory_fd = directory.as_raw_fd();
unsafe {
command.pre_exec(move || {
let flags = libc::fcntl(directory_fd, libc::F_GETFD);
if flags < 0
|| libc::fcntl(directory_fd, libc::F_SETFD, flags & !libc::FD_CLOEXEC) < 0
{
Err(std::io::Error::last_os_error())
} else {
Ok(())
}
});
}
}
#[cfg(windows)]
{
let _ = command;
}
#[cfg(not(any(unix, windows)))]
{
let _ = command;
return Err("managed snapshot source inheritance is unsupported".to_string());
}
Ok(())
}
pub(crate) fn configure_execution_path_revalidation(
&self,
command: &mut Command,
relative_path: &str,
source_path: &Path,
) -> Result<(), String> {
#[cfg(target_os = "macos")]
{
use std::os::unix::process::CommandExt;
let Some(ManagedSnapshotExecutionPin::Unix { directory }) = self.execution_pin.as_ref()
else {
return Err("managed snapshot macOS execution pin is unavailable".to_string());
};
let directory_fd = directory.as_raw_fd();
let source = path_to_c_string(source_path, "managed snapshot execution source")?;
let expected_root =
macos_file_identity_from_fd(directory_fd).map_err(|error| error.to_string())?;
let expected_source = macos_file_identity_from_snapshot(
directory_fd,
Path::new(relative_path),
self.root(),
)?;
macos_validate_named_execution_source(&source, expected_source)
.map_err(|error| error.to_string())?;
unsafe {
command.pre_exec(move || {
let actual_root = macos_file_identity_from_fd(directory_fd)?;
if actual_root != expected_root {
return Err(io::Error::other(
"managed snapshot root identity changed before exec",
));
}
macos_validate_named_execution_source(&source, expected_source)
});
}
}
#[cfg(not(target_os = "macos"))]
{
let _ = command;
let _ = relative_path;
let _ = source_path;
}
Ok(())
}
pub(crate) fn configure_worker_command(&self, command: &mut Command) -> Result<(), String> {
#[cfg(unix)]
{
use std::os::unix::process::CommandExt;
let Some(ManagedSnapshotExecutionPin::Unix { directory }) = self.execution_pin.as_ref()
else {
return Err("managed snapshot Unix execution pin is unavailable".to_string());
};
let directory_fd = directory.as_raw_fd();
unsafe {
command.pre_exec(move || {
if libc::fchdir(directory_fd) == 0 {
Ok(())
} else {
Err(std::io::Error::last_os_error())
}
});
}
}
#[cfg(windows)]
{
let neutral_cwd = windows_worker_neutral_cwd(self.root())?;
command.current_dir(neutral_cwd);
}
Ok(())
}
}
#[cfg(unix)]
fn validate_unix_snapshot_regular_file(
root_fd: RawFd,
relative_path: &Path,
display_root: &Path,
) -> Result<(), String> {
open_unix_snapshot_regular_file(root_fd, relative_path, display_root).map(drop)
}
#[cfg(unix)]
fn open_unix_snapshot_regular_file(
root_fd: RawFd,
relative_path: &Path,
display_root: &Path,
) -> Result<OwnedFd, String> {
let components = relative_path.components().collect::<Vec<_>>();
let mut opened_directories = Vec::<OwnedFd>::new();
let mut parent_fd = root_fd;
for (index, component) in components.iter().enumerate() {
let Component::Normal(name) = component else {
return Err("managed worker source contains a non-normal path component".to_string());
};
let encoded_name = CString::new(name.as_bytes()).map_err(|_| {
format!(
"managed worker source contains an interior NUL: {}",
render_host_visible_path(&display_root.join(relative_path))
)
})?;
let is_final = index + 1 == components.len();
let flags = if is_final {
libc::O_RDONLY | libc::O_NONBLOCK | libc::O_CLOEXEC | libc::O_NOFOLLOW
} else {
libc::O_RDONLY
| libc::O_NONBLOCK
| libc::O_DIRECTORY
| libc::O_CLOEXEC
| libc::O_NOFOLLOW
};
let opened_fd = unsafe { libc::openat(parent_fd, encoded_name.as_ptr(), flags) };
if opened_fd < 0 {
return Err(format!(
"failed to open managed worker snapshot source {}: {}",
render_host_visible_path(&display_root.join(relative_path)),
std::io::Error::last_os_error()
));
}
let opened = unsafe { OwnedFd::from_raw_fd(opened_fd) };
let mut stat: libc::stat = unsafe { std::mem::zeroed() };
if unsafe { libc::fstat(opened.as_raw_fd(), &mut stat) } != 0 {
return Err(format!(
"failed to inspect managed worker snapshot source {}: {}",
render_host_visible_path(&display_root.join(relative_path)),
std::io::Error::last_os_error()
));
}
let object_type = stat.st_mode & libc::S_IFMT;
if is_final {
if object_type != libc::S_IFREG {
return Err(format!(
"managed worker snapshot source is not a regular file: {}",
render_host_visible_path(&display_root.join(relative_path))
));
}
return Ok(opened);
} else {
if object_type != libc::S_IFDIR {
return Err(format!(
"managed worker snapshot source parent is not a directory: {}",
render_host_visible_path(&display_root.join(relative_path))
));
}
parent_fd = opened.as_raw_fd();
opened_directories.push(opened);
}
}
Err("managed worker source must contain at least one path component".to_string())
}
#[cfg(target_os = "macos")]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
struct MacosFileIdentity {
device: u64,
inode: u64,
}
#[cfg(target_os = "macos")]
fn path_to_c_string(path: &Path, label: &str) -> Result<CString, String> {
CString::new(path.as_os_str().as_bytes()).map_err(|_| {
format!(
"{label} contains an interior NUL: {}",
render_host_visible_path(path)
)
})
}
#[cfg(target_os = "macos")]
fn macos_file_identity_from_fd(fd: RawFd) -> Result<MacosFileIdentity, io::Error> {
let mut stat: libc::stat = unsafe { std::mem::zeroed() };
if unsafe { libc::fstat(fd, &mut stat) } != 0 {
return Err(io::Error::last_os_error());
}
let (device, inode) = unix_stat_device_inode(&stat).map_err(io::Error::other)?;
Ok(MacosFileIdentity { device, inode })
}
#[cfg(unix)]
fn unix_stat_device_inode(stat: &libc::stat) -> Result<(u64, u64), String> {
let device = unix_identity_component_to_u64(stat.st_dev, "device")?;
let inode = unix_identity_component_to_u64(stat.st_ino, "inode")?;
Ok((device, inode))
}
#[cfg(unix)]
fn unix_identity_component_to_u64<T>(value: T, component: &str) -> Result<u64, String>
where
u64: TryFrom<T>,
{
u64::try_from(value)
.map_err(|_| format!("Unix filesystem {component} identifier cannot be represented as u64"))
}
#[cfg(target_os = "macos")]
fn macos_file_identity_from_snapshot(
root_fd: RawFd,
relative_path: &Path,
display_root: &Path,
) -> Result<MacosFileIdentity, String> {
let source = open_unix_snapshot_regular_file(root_fd, relative_path, display_root)?;
macos_file_identity_from_fd(source.as_raw_fd()).map_err(|error| error.to_string())
}
#[cfg(target_os = "macos")]
fn macos_validate_named_execution_source(
source_path: &CStr,
expected: MacosFileIdentity,
) -> Result<(), io::Error> {
let raw_fd = unsafe {
libc::open(
source_path.as_ptr(),
libc::O_RDONLY | libc::O_CLOEXEC | libc::O_NOFOLLOW,
)
};
if raw_fd < 0 {
return Err(io::Error::last_os_error());
}
let source = unsafe { OwnedFd::from_raw_fd(raw_fd) };
let actual = macos_file_identity_from_fd(source.as_raw_fd())?;
if actual != expected {
return Err(io::Error::other(
"managed snapshot execution source identity changed",
));
}
Ok(())
}
#[cfg(target_os = "macos")]
fn macos_snapshot_execution_source_path(
root_fd: RawFd,
relative_path: &Path,
display_root: &Path,
) -> Result<PathBuf, String> {
validate_unix_snapshot_regular_file(root_fd, relative_path, display_root)?;
let mut buffer = [0_u8; libc::PATH_MAX as usize];
if unsafe { libc::fcntl(root_fd, libc::F_GETPATH, buffer.as_mut_ptr()) } < 0 {
return Err(format!(
"failed to derive managed snapshot path from macOS directory descriptor: {}",
io::Error::last_os_error()
));
}
let object_path = unsafe { CStr::from_ptr(buffer.as_ptr().cast()) };
let root_path = PathBuf::from(std::ffi::OsStr::from_bytes(object_path.to_bytes()));
let named_root = path_to_c_string(&root_path, "managed snapshot object path")?;
let named_root_fd = unsafe {
libc::open(
named_root.as_ptr(),
libc::O_RDONLY | libc::O_DIRECTORY | libc::O_CLOEXEC | libc::O_NOFOLLOW,
)
};
if named_root_fd < 0 {
return Err(format!(
"failed to reopen macOS managed snapshot object path {}: {}",
render_host_visible_path(&root_path),
io::Error::last_os_error()
));
}
let named_root_owner = unsafe { OwnedFd::from_raw_fd(named_root_fd) };
let expected_root = macos_file_identity_from_fd(root_fd).map_err(|error| error.to_string())?;
let actual_root = macos_file_identity_from_fd(named_root_owner.as_raw_fd())
.map_err(|error| error.to_string())?;
if actual_root != expected_root {
return Err("macOS managed snapshot object path identity changed".to_string());
}
let source_path = root_path.join(relative_path);
let expected_source = macos_file_identity_from_snapshot(root_fd, relative_path, display_root)?;
let named_source = path_to_c_string(&source_path, "managed snapshot execution source")?;
macos_validate_named_execution_source(&named_source, expected_source)
.map_err(|error| error.to_string())?;
Ok(source_path)
}
impl Drop for ManagedPackageSnapshot {
fn drop(&mut self) {
drop(self.execution_pin.take());
cleanup_or_handoff_managed_snapshot(self.ownership.take());
}
}
fn cleanup_or_handoff_managed_snapshot(ownership: Option<ManagedSnapshotCleanupOwnership>) {
cleanup_or_handoff_managed_snapshot_with(ownership, remove_managed_package_snapshot);
}
fn cleanup_or_handoff_managed_snapshot_with<F>(
ownership: Option<ManagedSnapshotCleanupOwnership>,
remove_snapshot: F,
) where
F: FnOnce(&mut ManagedSnapshotCleanupRecord) -> Result<(), String>,
{
let Some(ManagedSnapshotCleanupOwnership { mut record, permit }) = ownership else {
return;
};
let immediate_cleanup = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
remove_snapshot(&mut record)
}));
let cleanup_error = match immediate_cleanup {
Ok(Ok(())) => None,
Ok(Err(error)) => Some(error),
Err(_) => Some("managed snapshot immediate cleanup panicked".to_string()),
};
if let Some(error) = cleanup_error {
log_warn(format!(
"[LuaSkill:warn] managed package snapshot cleanup failed and was queued for retry: {error}"
));
permit.handoff(record);
}
}
struct ManagedSnapshotPreparation {
ownership: Option<ManagedSnapshotCleanupOwnership>,
}
impl Drop for ManagedSnapshotPreparation {
fn drop(&mut self) {
cleanup_or_handoff_managed_snapshot(self.ownership.take());
}
}
impl ManagedSnapshotCleanupPermit {
fn handoff(mut self, record: ManagedSnapshotCleanupRecord) {
self.retry
.queue
.records
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.push_back(record);
self.reserved = false;
self.retry.queue.changed.notify_one();
}
}
impl Drop for ManagedSnapshotCleanupPermit {
fn drop(&mut self) {
if self.reserved {
self.retry.reserved.fetch_sub(1, Ordering::AcqRel);
}
}
}
fn reserve_managed_snapshot_cleanup_slot() -> Result<ManagedSnapshotCleanupPermit, String> {
let retry = managed_snapshot_cleanup_retry()?;
retry
.reserved
.fetch_update(Ordering::AcqRel, Ordering::Acquire, |reserved| {
(reserved < MANAGED_SNAPSHOT_CLEANUP_CAPACITY).then_some(reserved + 1)
})
.map_err(|_| {
format!(
"managed snapshot cleanup capacity is exhausted ({MANAGED_SNAPSHOT_CLEANUP_CAPACITY})"
)
})?;
Ok(ManagedSnapshotCleanupPermit {
retry,
reserved: true,
})
}
fn managed_snapshot_cleanup_retry() -> Result<&'static ManagedSnapshotCleanupRetry, String> {
MANAGED_SNAPSHOT_CLEANUP_RETRY
.get_or_init(|| {
let retry = ManagedSnapshotCleanupRetry {
queue: Arc::new(ManagedSnapshotCleanupQueue {
records: Mutex::new(VecDeque::new()),
changed: Condvar::new(),
}),
reserved: Arc::new(AtomicUsize::new(0)),
};
let queue = Arc::clone(&retry.queue);
std::thread::Builder::new()
.name("luaskills-snapshot-cleanup".to_string())
.spawn(move || managed_snapshot_cleanup_worker(queue))
.map_err(|error| {
format!("failed to start managed snapshot cleanup worker: {error}")
})?;
Ok(retry)
})
.as_ref()
.map_err(Clone::clone)
}
fn managed_snapshot_cleanup_worker(queue: Arc<ManagedSnapshotCleanupQueue>) {
loop {
let mut record = {
let mut records = queue
.records
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
while records.is_empty() {
records = queue
.changed
.wait(records)
.unwrap_or_else(std::sync::PoisonError::into_inner);
}
records
.pop_front()
.expect("non-empty managed snapshot cleanup queue must yield one record")
};
let cleanup_result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
remove_managed_package_snapshot(&mut record)
}));
match cleanup_result {
Ok(Ok(())) => {
if let Ok(retry) = managed_snapshot_cleanup_retry() {
retry.reserved.fetch_sub(1, Ordering::AcqRel);
}
}
Ok(Err(error)) => {
if !record.error_reported {
log_warn(format!(
"[LuaSkill:warn] managed package snapshot cleanup retry remains pending: {error}"
));
record.error_reported = true;
}
queue
.records
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.push_back(record);
std::thread::sleep(MANAGED_SNAPSHOT_CLEANUP_RETRY_DELAY);
}
Err(_) => {
log_warn(
"[LuaSkill:warn] managed snapshot cleanup worker panicked; retaining record for retry"
.to_string(),
);
queue
.records
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.push_back(record);
std::thread::sleep(MANAGED_SNAPSHOT_CLEANUP_RETRY_DELAY);
}
}
}
}
pub(crate) fn ensure_persistent_managed_runtime_session_platform_supported() -> Result<(), String> {
let capability = current_managed_runtime_persistent_session_capability();
if capability.supported {
return Ok(());
}
Err(format!(
"persistent managed runtime sessions are unsupported: {}",
capability
.reason
.unwrap_or_else(|| "platform_family_is_not_supported".to_string())
))
}
pub(crate) fn launch_managed_python_session(
package: &ManagedRuntimePackageContext,
request: ManagedRuntimeSessionOpenRequest,
observer: Option<Arc<dyn ManagedProcessSessionObserver>>,
) -> Result<ManagedRuntimeSessionLaunch, String> {
ensure_persistent_managed_runtime_session_platform_supported()?;
let manifest = package
.dependency_manifest()
.ok_or_else(|| "dependencies.yaml is required for managed Python sessions".to_string())?;
let runtime_spec = manifest
.python_runtime
.as_ref()
.ok_or_else(|| "python_runtime is not declared".to_string())?;
let plan = resolve_python_env_plan(package, runtime_spec)?;
ensure_managed_env(&plan)?;
let _source_file = package.resolve_existing_file(&request.file, "file")?;
let snapshot = Arc::new(prepare_managed_package_snapshot(&plan, package, ".ls-s")?);
let cwd = resolve_managed_session_cwd(package, request.cwd.as_deref())?;
let python_executable = managed_python_session_executable(&plan);
ensure_regular_file(&python_executable, "managed Python executable")?;
let mut command = Command::new(&python_executable);
snapshot.configure_source_inheritance(&mut command)?;
let snapshot_source = snapshot.execution_source_path(&request.file)?;
snapshot.configure_execution_path_revalidation(
&mut command,
&request.file,
&snapshot_source,
)?;
ensure_regular_file(&snapshot_source, "managed Python snapshot source")?;
let execution_cwd = cwd.canonical.clone();
command
.arg(host_process_path_argument(&snapshot_source))
.args(&request.args);
configure_managed_command_cwd(&mut command, &cwd)?;
configure_managed_python_command_environment(&mut command, &plan)?;
install_controlled_context_environment(&mut command, package)?;
let options = launch_options_from_request(&request);
let reaper_snapshot = Arc::clone(&snapshot);
let core = launch_managed_process_core(
command,
options,
observer,
Some(Box::new(move || drop(reaper_snapshot))),
)
.map_err(|error| {
format!(
"{error}; managed Python snapshot source {}; execution cwd {}",
render_host_visible_path(&snapshot_source),
render_host_visible_path(&execution_cwd)
)
})?;
let cleanup: ManagedProcessSessionCleanup = Box::new(move || drop(snapshot));
Ok(ManagedRuntimeSessionLaunch {
core,
cleanup: Some(cleanup),
})
}
pub(crate) fn launch_managed_node_session(
package: &ManagedRuntimePackageContext,
request: ManagedRuntimeSessionOpenRequest,
observer: Option<Arc<dyn ManagedProcessSessionObserver>>,
) -> Result<ManagedRuntimeSessionLaunch, String> {
ensure_persistent_managed_runtime_session_platform_supported()?;
let manifest = package
.dependency_manifest()
.ok_or_else(|| "dependencies.yaml is required for managed Node sessions".to_string())?;
let runtime_spec = manifest
.node_runtime
.as_ref()
.ok_or_else(|| "node_runtime is not declared".to_string())?;
let plan = resolve_node_env_plan(package, runtime_spec)?;
ensure_managed_env(&plan)?;
ensure_regular_file(&plan.runtime_executable, "managed Node executable")?;
let _source_file = package.resolve_existing_file(&request.file, "file")?;
let snapshot = Arc::new(prepare_managed_package_snapshot(&plan, package, ".ls-s")?);
let cwd = resolve_managed_session_cwd(package, request.cwd.as_deref())?;
let mut command = Command::new(&plan.runtime_executable);
snapshot.configure_source_inheritance(&mut command)?;
let snapshot_source = snapshot.node_execution_source_path(&request.file)?;
snapshot.configure_execution_path_revalidation(
&mut command,
&request.file,
&snapshot_source,
)?;
ensure_regular_file(&snapshot_source, "managed Node snapshot source")?;
let execution_cwd = cwd.canonical.clone();
command.arg(&snapshot_source).args(&request.args);
configure_managed_command_cwd(&mut command, &cwd)?;
configure_managed_node_command_environment(&mut command, &plan)?;
install_controlled_context_environment(&mut command, package)?;
let options = launch_options_from_request(&request);
let reaper_snapshot = Arc::clone(&snapshot);
let core = launch_managed_process_core(
command,
options,
observer,
Some(Box::new(move || drop(reaper_snapshot))),
)
.map_err(|error| {
format!(
"{error}; managed Node snapshot source {}; execution cwd {}",
render_host_visible_path(&snapshot_source),
render_host_visible_path(&execution_cwd)
)
})?;
let cleanup: ManagedProcessSessionCleanup = Box::new(move || drop(snapshot));
Ok(ManagedRuntimeSessionLaunch {
core,
cleanup: Some(cleanup),
})
}
fn launch_managed_process_core(
command: Command,
options: ManagedProcessSessionLaunchOptions,
observer: Option<Arc<dyn ManagedProcessSessionObserver>>,
keepalive: Option<Box<dyn FnOnce() + Send>>,
) -> Result<ManagedProcessSessionCore, String> {
ManagedProcessSessionCore::launch_with_optional_observer_and_keepalive(
command, options, observer, keepalive,
)
}
#[cfg(test)]
pub(crate) fn copy_managed_package_tree(source: &Path, destination: &Path) -> Result<(), String> {
copy_managed_package_tree_from_fixed_root(source, destination, None, None).map(drop)
}
fn copy_managed_package_tree_from_fixed_root(
source: &Path,
destination: &Path,
expected_identity: Option<&ManagedFilesystemObjectIdentity>,
expected_destination_identity: Option<&ManagedPackageSnapshotIdentity>,
) -> Result<ManagedSnapshotExecutionPin, String> {
fs::create_dir_all(destination).map_err(|error| {
format!(
"failed to create {}: {error}",
render_host_visible_path(destination)
)
})?;
#[cfg(unix)]
{
let encoded_source = CString::new(source.as_os_str().as_bytes()).map_err(|_| {
format!(
"managed package source contains an interior NUL: {}",
render_host_visible_path(source)
)
})?;
let raw_fd = unsafe {
libc::open(
encoded_source.as_ptr(),
libc::O_RDONLY | libc::O_DIRECTORY | libc::O_CLOEXEC | libc::O_NOFOLLOW,
)
};
if raw_fd < 0 {
return Err(format!(
"failed to pin managed package source {}: {}",
render_host_visible_path(source),
std::io::Error::last_os_error()
));
}
let source_directory = unsafe { OwnedFd::from_raw_fd(raw_fd) };
let actual_identity = unix_managed_package_identity(source_directory.as_raw_fd(), source)?;
if expected_identity.is_some_and(|expected| expected != &actual_identity) {
return Err(format!(
"managed package root changed before snapshot copy: {}",
render_host_visible_path(source)
));
}
let encoded_destination =
CString::new(destination.as_os_str().as_bytes()).map_err(|_| {
format!(
"managed snapshot destination contains an interior NUL: {}",
render_host_visible_path(destination)
)
})?;
let destination_fd = unsafe {
libc::open(
encoded_destination.as_ptr(),
libc::O_RDONLY | libc::O_DIRECTORY | libc::O_CLOEXEC | libc::O_NOFOLLOW,
)
};
if destination_fd < 0 {
return Err(format!(
"failed to pin managed snapshot destination {}: {}",
render_host_visible_path(destination),
std::io::Error::last_os_error()
));
}
let destination_directory = unsafe { OwnedFd::from_raw_fd(destination_fd) };
if let Some(expected) = expected_destination_identity {
let actual =
unix_managed_package_identity(destination_directory.as_raw_fd(), destination)?;
let actual = ManagedPackageSnapshotIdentity {
device: actual.device,
inode: actual.inode,
};
if &actual != expected {
return Err(format!(
"managed snapshot destination changed before copy: {}",
render_host_visible_path(destination)
));
}
}
let execution_fd =
unsafe { libc::fcntl(destination_directory.as_raw_fd(), libc::F_DUPFD_CLOEXEC, 3) };
if execution_fd < 0 {
return Err(format!(
"failed to reserve managed snapshot execution descriptor {}: {}",
render_host_visible_path(destination),
std::io::Error::last_os_error()
));
}
copy_unix_managed_package_directory(
source_directory.as_raw_fd(),
destination_directory.as_raw_fd(),
source,
destination,
)?;
Ok(ManagedSnapshotExecutionPin::Unix {
directory: unsafe { OwnedFd::from_raw_fd(execution_fd) },
})
}
#[cfg(windows)]
{
let (source_directory, information) = open_windows_managed_package_object(source)?;
if information.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == 0 {
return Err(format!(
"managed package source is not a directory: {}",
render_host_visible_path(source)
));
}
let actual_identity = ManagedFilesystemObjectIdentity {
volume_serial_number: information.dwVolumeSerialNumber,
file_index: (u64::from(information.nFileIndexHigh) << 32)
| u64::from(information.nFileIndexLow),
};
if expected_identity.is_some_and(|expected| expected != &actual_identity) {
return Err(format!(
"managed package root changed before snapshot copy: {}",
render_host_visible_path(source)
));
}
copy_windows_managed_package_tree_pinned(
source_directory,
source,
destination,
expected_destination_identity,
)
}
#[cfg(not(any(unix, windows)))]
{
let _ = expected_identity;
let _ = expected_destination_identity;
Err(format!(
"fixed-object managed package copy is unsupported: {}",
render_host_visible_path(source)
))
}
}
#[cfg(unix)]
fn unix_managed_package_identity(
directory_fd: RawFd,
display_path: &Path,
) -> Result<ManagedFilesystemObjectIdentity, String> {
let mut stat: libc::stat = unsafe { std::mem::zeroed() };
if unsafe { libc::fstat(directory_fd, &mut stat) } != 0 {
return Err(format!(
"failed to inspect pinned managed package directory {}: {}",
render_host_visible_path(display_path),
std::io::Error::last_os_error()
));
}
let (device, inode) = unix_stat_device_inode(&stat)?;
Ok(ManagedFilesystemObjectIdentity { device, inode })
}
#[cfg(unix)]
fn copy_unix_managed_package_directory(
source_directory_fd: RawFd,
destination_directory_fd: RawFd,
source_display_path: &Path,
destination: &Path,
) -> Result<(), String> {
use std::os::unix::ffi::OsStringExt;
let duplicate_fd = unsafe { libc::dup(source_directory_fd) };
if duplicate_fd < 0 {
return Err(format!(
"failed to duplicate managed package directory {}: {}",
render_host_visible_path(source_display_path),
std::io::Error::last_os_error()
));
}
let stream = unsafe { libc::fdopendir(duplicate_fd) };
if stream.is_null() {
unsafe { libc::close(duplicate_fd) };
return Err(format!(
"failed to enumerate managed package directory {}: {}",
render_host_visible_path(source_display_path),
std::io::Error::last_os_error()
));
}
let mut names = Vec::<CString>::new();
loop {
let entry = unsafe { libc::readdir(stream) };
if entry.is_null() {
break;
}
let name = unsafe { CStr::from_ptr((*entry).d_name.as_ptr()) };
if name.to_bytes() == b"." || name.to_bytes() == b".." {
continue;
}
names.push(CString::new(name.to_bytes()).map_err(|_| {
format!(
"managed package entry contains an interior NUL under {}",
render_host_visible_path(source_display_path)
)
})?);
}
unsafe { libc::closedir(stream) };
for name in names {
let name_bytes = name.as_bytes();
if name_bytes == b"node_modules" {
continue;
}
let name_os = std::ffi::OsString::from_vec(name_bytes.to_vec());
let source_path = source_display_path.join(&name_os);
let destination_path = destination.join(&name_os);
let source_fd = unsafe {
libc::openat(
source_directory_fd,
name.as_ptr(),
libc::O_RDONLY | libc::O_NONBLOCK | libc::O_CLOEXEC | libc::O_NOFOLLOW,
)
};
if source_fd < 0 {
let error = std::io::Error::last_os_error();
if error.raw_os_error() == Some(libc::ELOOP) {
return Err(format!(
"unsupported file type: {}",
render_host_visible_path(&source_path)
));
}
return Err(format!(
"failed to pin managed package entry {}: {}",
render_host_visible_path(&source_path),
error
));
}
let opened = unsafe { OwnedFd::from_raw_fd(source_fd) };
let mut stat: libc::stat = unsafe { std::mem::zeroed() };
if unsafe { libc::fstat(opened.as_raw_fd(), &mut stat) } != 0 {
return Err(format!(
"failed to inspect pinned managed package entry {}: {}",
render_host_visible_path(&source_path),
std::io::Error::last_os_error()
));
}
let file_kind = stat.st_mode & libc::S_IFMT;
if file_kind == libc::S_IFDIR {
if unsafe { libc::mkdirat(destination_directory_fd, name.as_ptr(), 0o700) } != 0 {
return Err(format!(
"failed to create snapshot directory {}: {}",
render_host_visible_path(&destination_path),
std::io::Error::last_os_error()
));
}
let destination_child_fd = unsafe {
libc::openat(
destination_directory_fd,
name.as_ptr(),
libc::O_RDONLY | libc::O_DIRECTORY | libc::O_CLOEXEC | libc::O_NOFOLLOW,
)
};
if destination_child_fd < 0 {
return Err(format!(
"failed to pin snapshot directory {}: {}",
render_host_visible_path(&destination_path),
std::io::Error::last_os_error()
));
}
let destination_child = unsafe { OwnedFd::from_raw_fd(destination_child_fd) };
copy_unix_managed_package_directory(
opened.as_raw_fd(),
destination_child.as_raw_fd(),
&source_path,
&destination_path,
)?;
} else if file_kind == libc::S_IFREG {
let mut source_file = fs::File::from(opened);
let destination_fd = unsafe {
libc::openat(
destination_directory_fd,
name.as_ptr(),
libc::O_WRONLY
| libc::O_CREAT
| libc::O_EXCL
| libc::O_CLOEXEC
| libc::O_NOFOLLOW,
0o600,
)
};
if destination_fd < 0 {
return Err(format!(
"failed to copy {} to {}: {}",
render_host_visible_path(&source_path),
render_host_visible_path(&destination_path),
std::io::Error::last_os_error()
));
}
let mut destination_file = unsafe { fs::File::from_raw_fd(destination_fd) };
io::copy(&mut source_file, &mut destination_file).map_err(|error| {
format!(
"failed to copy {} to {}: {error}",
render_host_visible_path(&source_path),
render_host_visible_path(&destination_path)
)
})?;
} else {
return Err(format!(
"unsupported file type: {}",
render_host_visible_path(&source_path)
));
}
}
Ok(())
}
#[cfg(windows)]
fn open_windows_managed_package_object(
path: &Path,
) -> Result<(fs::File, BY_HANDLE_FILE_INFORMATION), String> {
let mut wide = path.as_os_str().encode_wide().collect::<Vec<_>>();
wide.push(0);
let raw_handle = unsafe {
CreateFileW(
wide.as_ptr(),
GENERIC_READ,
FILE_SHARE_READ,
std::ptr::null(),
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
std::ptr::null_mut(),
)
};
if raw_handle == INVALID_HANDLE_VALUE {
return Err(format!(
"failed to pin managed package object {}: {}",
render_host_visible_path(path),
std::io::Error::last_os_error()
));
}
let file = unsafe { fs::File::from_raw_handle(raw_handle as _) };
let mut information: BY_HANDLE_FILE_INFORMATION = unsafe { std::mem::zeroed() };
if unsafe { GetFileInformationByHandle(file.as_raw_handle() as _, &mut information) } == 0 {
return Err(format!(
"failed to inspect pinned managed package object {}: {}",
render_host_visible_path(path),
std::io::Error::last_os_error()
));
}
if information.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT != 0 {
return Err(format!(
"unsupported file type: {}",
render_host_visible_path(path)
));
}
Ok((file, information))
}
#[cfg(windows)]
fn copy_windows_managed_package_tree_pinned(
source_directory: fs::File,
source: &Path,
destination: &Path,
expected_destination_identity: Option<&ManagedPackageSnapshotIdentity>,
) -> Result<ManagedSnapshotExecutionPin, String> {
let destination_root = open_windows_mutable_snapshot_directory(destination)?;
if let Some(expected) = expected_destination_identity {
let actual = windows_snapshot_identity_from_file(&destination_root, destination)?;
if &actual != expected {
return Err(format!(
"managed snapshot destination changed before copy: {}",
render_host_visible_path(destination)
));
}
}
let mut mutable_directories = vec![destination_root];
let mut directory_paths = vec![destination.to_path_buf()];
let mut execution_handles = Vec::new();
copy_windows_managed_package_directory(
source_directory,
source,
destination,
&mut mutable_directories,
&mut directory_paths,
&mut execution_handles,
)?;
for directory_path in directory_paths {
let (handle, information) = open_windows_managed_package_object(&directory_path)?;
if information.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == 0 {
return Err(format!(
"managed snapshot directory changed during pin transfer: {}",
render_host_visible_path(&directory_path)
));
}
execution_handles.push(handle);
}
drop(mutable_directories);
Ok(ManagedSnapshotExecutionPin::Windows {
_handles: execution_handles,
})
}
#[cfg(windows)]
fn windows_snapshot_identity_from_file(
file: &fs::File,
path: &Path,
) -> Result<ManagedPackageSnapshotIdentity, String> {
let mut information: BY_HANDLE_FILE_INFORMATION = unsafe { std::mem::zeroed() };
if unsafe { GetFileInformationByHandle(file.as_raw_handle() as _, &mut information) } == 0 {
return Err(format!(
"failed to inspect managed snapshot destination {}: {}",
render_host_visible_path(path),
std::io::Error::last_os_error()
));
}
Ok(ManagedPackageSnapshotIdentity {
volume_serial_number: information.dwVolumeSerialNumber,
file_index: (u64::from(information.nFileIndexHigh) << 32)
| u64::from(information.nFileIndexLow),
})
}
#[cfg(windows)]
fn open_windows_mutable_snapshot_directory(path: &Path) -> Result<fs::File, String> {
let mut wide = path.as_os_str().encode_wide().collect::<Vec<_>>();
wide.push(0);
let raw_handle = unsafe {
CreateFileW(
wide.as_ptr(),
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE,
std::ptr::null(),
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
std::ptr::null_mut(),
)
};
if raw_handle == INVALID_HANDLE_VALUE {
return Err(format!(
"failed to pin mutable snapshot directory {}: {}",
render_host_visible_path(path),
std::io::Error::last_os_error()
));
}
let file = unsafe { fs::File::from_raw_handle(raw_handle as _) };
let mut information: BY_HANDLE_FILE_INFORMATION = unsafe { std::mem::zeroed() };
if unsafe { GetFileInformationByHandle(file.as_raw_handle() as _, &mut information) } == 0
|| information.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT != 0
|| information.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == 0
{
return Err(format!(
"mutable snapshot path is not a real directory: {}",
render_host_visible_path(path)
));
}
Ok(file)
}
#[cfg(windows)]
fn copy_windows_managed_package_directory(
_source_directory: fs::File,
source: &Path,
destination: &Path,
mutable_directories: &mut Vec<fs::File>,
directory_paths: &mut Vec<PathBuf>,
execution_handles: &mut Vec<fs::File>,
) -> Result<(), String> {
let entries = fs::read_dir(source).map_err(|error| {
format!(
"failed to enumerate pinned managed package directory {}: {error}",
render_host_visible_path(source)
)
})?;
for entry in entries {
let entry = entry.map_err(|error| {
format!(
"failed to read managed package entry under {}: {error}",
render_host_visible_path(source)
)
})?;
let name = entry.file_name();
if name == "node_modules" {
continue;
}
let source_path = source.join(&name);
let destination_path = destination.join(&name);
let (mut source_object, information) = open_windows_managed_package_object(&source_path)?;
if information.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY != 0 {
fs::create_dir(&destination_path).map_err(|error| {
format!(
"failed to create snapshot directory {}: {error}",
render_host_visible_path(&destination_path)
)
})?;
let destination_directory = open_windows_mutable_snapshot_directory(&destination_path)?;
mutable_directories.push(destination_directory);
directory_paths.push(destination_path.clone());
copy_windows_managed_package_directory(
source_object,
&source_path,
&destination_path,
mutable_directories,
directory_paths,
execution_handles,
)?;
} else {
let mut destination_file = fs::OpenOptions::new()
.write(true)
.create_new(true)
.share_mode(FILE_SHARE_READ)
.open(&destination_path)
.map_err(|error| {
format!(
"failed to copy {} to {}: {error}",
render_host_visible_path(&source_path),
render_host_visible_path(&destination_path)
)
})?;
io::copy(&mut source_object, &mut destination_file).map_err(|error| {
format!(
"failed to copy {} to {}: {error}",
render_host_visible_path(&source_path),
render_host_visible_path(&destination_path)
)
})?;
clear_windows_readonly_attribute(&destination_path)?;
execution_handles.push(destination_file);
}
}
Ok(())
}
#[cfg(all(test, windows))]
fn pin_managed_snapshot_execution_tree(
snapshot_root: &Path,
) -> Result<ManagedSnapshotExecutionPin, String> {
#[cfg(unix)]
{
let encoded = CString::new(snapshot_root.as_os_str().as_bytes()).map_err(|_| {
format!(
"managed snapshot path contains an interior NUL: {}",
render_host_visible_path(snapshot_root)
)
})?;
let raw_fd = unsafe {
libc::open(
encoded.as_ptr(),
libc::O_RDONLY | libc::O_DIRECTORY | libc::O_CLOEXEC | libc::O_NOFOLLOW,
)
};
if raw_fd < 0 {
return Err(format!(
"failed to pin managed snapshot root {}: {}",
render_host_visible_path(snapshot_root),
std::io::Error::last_os_error()
));
}
let original = unsafe { OwnedFd::from_raw_fd(raw_fd) };
let safe_fd = unsafe { libc::fcntl(original.as_raw_fd(), libc::F_DUPFD_CLOEXEC, 3) };
if safe_fd < 0 {
return Err(format!(
"failed to reserve a non-stdio managed snapshot descriptor {}: {}",
render_host_visible_path(snapshot_root),
std::io::Error::last_os_error()
));
}
Ok(ManagedSnapshotExecutionPin::Unix {
directory: unsafe { OwnedFd::from_raw_fd(safe_fd) },
})
}
#[cfg(windows)]
{
let mut handles = Vec::new();
collect_windows_snapshot_execution_pins(snapshot_root, &mut handles)?;
Ok(ManagedSnapshotExecutionPin::Windows { _handles: handles })
}
#[cfg(not(any(unix, windows)))]
{
Err(format!(
"managed snapshot execution pinning is unsupported: {}",
render_host_visible_path(snapshot_root)
))
}
}
#[cfg(all(test, windows))]
fn collect_windows_snapshot_execution_pins(
path: &Path,
handles: &mut Vec<fs::File>,
) -> Result<(), String> {
let (handle, information) = open_windows_managed_package_object(path)?;
let is_directory = information.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY != 0;
handles.push(handle);
if is_directory {
for entry in fs::read_dir(path).map_err(|error| {
format!(
"failed to enumerate managed snapshot {} while pinning: {error}",
render_host_visible_path(path)
)
})? {
let entry = entry.map_err(|error| {
format!(
"failed to read managed snapshot entry under {}: {error}",
render_host_visible_path(path)
)
})?;
collect_windows_snapshot_execution_pins(&entry.path(), handles)?;
}
}
Ok(())
}
#[cfg(windows)]
fn clear_windows_readonly_attribute(path: &Path) -> Result<(), String> {
use std::os::windows::ffi::OsStrExt;
let mut wide = path.as_os_str().encode_wide().collect::<Vec<_>>();
if wide.contains(&0) {
return Err(format!(
"copied Node session file path contains an embedded NUL: {}",
render_host_visible_path(path)
));
}
wide.push(0);
let attributes = unsafe { GetFileAttributesW(wide.as_ptr()) };
if attributes == INVALID_FILE_ATTRIBUTES {
return Err(format!(
"failed to inspect copied Node session file {}: {}",
render_host_visible_path(path),
std::io::Error::last_os_error()
));
}
if attributes & FILE_ATTRIBUTE_READONLY == 0 {
return Ok(());
}
let status =
unsafe { SetFileAttributesW(wide.as_ptr(), attributes & !FILE_ATTRIBUTE_READONLY) };
if status == 0 {
return Err(format!(
"failed to clear read-only attribute on copied Node session file {}: {}",
render_host_visible_path(path),
std::io::Error::last_os_error()
));
}
Ok(())
}
fn launch_options_from_request(
request: &ManagedRuntimeSessionOpenRequest,
) -> ManagedProcessSessionLaunchOptions {
ManagedProcessSessionLaunchOptions {
stdout_encoding: request.stdout_encoding,
stderr_encoding: request.stderr_encoding,
stdin_encoding: request.stdin_encoding,
buffer_limit_bytes: request.buffer_limit_bytes,
}
}
struct ManagedSessionCwd {
canonical: PathBuf,
pin: ManagedSessionCwdPin,
}
enum ManagedSessionCwdPin {
#[cfg(unix)]
Unix(OwnedFd),
#[cfg(windows)]
Windows(OwnedHandle),
}
fn resolve_managed_session_cwd(
package: &ManagedRuntimePackageContext,
requested: Option<&str>,
) -> Result<ManagedSessionCwd, String> {
let candidate = match requested.map(str::trim).filter(|value| !value.is_empty()) {
Some(value) => {
let path = PathBuf::from(value);
if path.is_absolute() {
path
} else {
package.package_root().join(path)
}
}
None => package.package_root().to_path_buf(),
};
let resolved_candidate = fs::canonicalize(&candidate).map_err(|error| {
format!(
"failed to canonicalize session cwd {}: {error}",
render_host_visible_path(&candidate)
)
})?;
let pin = pin_managed_session_cwd(&resolved_candidate)?;
let canonical = authoritative_managed_session_cwd_path(&pin, &resolved_candidate)?;
let workspace_root = package
.lease_binding()
.and_then(|binding| binding.workspace_root());
if !canonical.starts_with(package.package_root())
&& !workspace_root.is_some_and(|root| canonical.starts_with(root))
{
return Err(format!(
"session cwd {} is outside the package root and authorized workspace root",
render_host_visible_path(&canonical)
));
}
Ok(ManagedSessionCwd { canonical, pin })
}
fn pin_managed_session_cwd(path: &Path) -> Result<ManagedSessionCwdPin, String> {
#[cfg(unix)]
{
let encoded = CString::new(path.as_os_str().as_bytes()).map_err(|_| {
format!(
"managed session cwd contains an interior NUL: {}",
render_host_visible_path(path)
)
})?;
let raw_fd = unsafe {
libc::open(
encoded.as_ptr(),
libc::O_RDONLY | libc::O_DIRECTORY | libc::O_CLOEXEC | libc::O_NOFOLLOW,
)
};
if raw_fd < 0 {
return Err(format!(
"failed to pin managed session cwd {}: {}",
render_host_visible_path(path),
std::io::Error::last_os_error()
));
}
Ok(ManagedSessionCwdPin::Unix(unsafe {
OwnedFd::from_raw_fd(raw_fd)
}))
}
#[cfg(windows)]
{
open_windows_pinned_session_cwd(path).map(ManagedSessionCwdPin::Windows)
}
#[cfg(not(any(unix, windows)))]
{
Err(format!(
"pinned managed session cwd is unsupported: {}",
render_host_visible_path(path)
))
}
}
fn authoritative_managed_session_cwd_path(
pin: &ManagedSessionCwdPin,
resolved_candidate: &Path,
) -> Result<PathBuf, String> {
#[cfg(unix)]
{
let ManagedSessionCwdPin::Unix(_directory) = pin;
Ok(resolved_candidate.to_path_buf())
}
#[cfg(windows)]
{
let ManagedSessionCwdPin::Windows(directory) = pin;
final_windows_path_from_handle(directory, resolved_candidate)
}
#[cfg(not(any(unix, windows)))]
{
let _ = pin;
Err(format!(
"authoritative managed session cwd is unsupported: {}",
render_host_visible_path(resolved_candidate)
))
}
}
fn configure_managed_command_cwd(
command: &mut Command,
cwd: &ManagedSessionCwd,
) -> Result<(), String> {
#[cfg(unix)]
{
use std::os::unix::process::CommandExt;
let ManagedSessionCwdPin::Unix(directory) = &cwd.pin;
let directory_fd = directory.as_raw_fd();
unsafe {
command.pre_exec(move || {
if libc::fchdir(directory_fd) == 0 {
Ok(())
} else {
Err(std::io::Error::last_os_error())
}
});
}
Ok(())
}
#[cfg(windows)]
{
let ManagedSessionCwdPin::Windows(_directory) = &cwd.pin;
command.current_dir(&cwd.canonical);
Ok(())
}
#[cfg(not(any(unix, windows)))]
{
let _ = command;
Err(format!(
"pinned managed session cwd is unsupported: {}",
render_host_visible_path(&cwd.canonical)
))
}
}
#[cfg(windows)]
fn open_windows_pinned_session_cwd(path: &Path) -> Result<OwnedHandle, String> {
let mut wide_path = path.as_os_str().encode_wide().collect::<Vec<_>>();
wide_path.push(0);
let raw_handle = unsafe {
CreateFileW(
wide_path.as_ptr(),
GENERIC_READ,
FILE_SHARE_READ,
std::ptr::null(),
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
std::ptr::null_mut(),
)
};
if raw_handle == INVALID_HANDLE_VALUE {
return Err(format!(
"failed to pin managed session cwd {}: {}",
render_host_visible_path(path),
std::io::Error::last_os_error()
));
}
let handle = unsafe { OwnedHandle::from_raw_handle(raw_handle as _) };
let mut information: BY_HANDLE_FILE_INFORMATION = unsafe { std::mem::zeroed() };
if unsafe { GetFileInformationByHandle(handle.as_raw_handle() as _, &mut information) } == 0 {
return Err(format!(
"failed to inspect pinned managed session cwd {}: {}",
render_host_visible_path(path),
std::io::Error::last_os_error()
));
}
if information.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT != 0
|| information.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == 0
{
return Err(format!(
"managed session cwd is not a real directory: {}",
render_host_visible_path(path)
));
}
Ok(handle)
}
#[cfg(windows)]
fn final_windows_path_from_handle(
handle: &OwnedHandle,
opened_path: &Path,
) -> Result<PathBuf, String> {
let mut buffer = vec![0_u16; 512];
loop {
let capacity = u32::try_from(buffer.len()).map_err(|_| {
format!(
"authoritative session cwd path is too long: {}",
render_host_visible_path(opened_path)
)
})?;
let written = unsafe {
GetFinalPathNameByHandleW(
handle.as_raw_handle() as _,
buffer.as_mut_ptr(),
capacity,
FILE_NAME_NORMALIZED | VOLUME_NAME_DOS,
)
};
if written == 0 {
return Err(format!(
"failed to resolve pinned managed session cwd {}: {}",
render_host_visible_path(opened_path),
std::io::Error::last_os_error()
));
}
if written < capacity {
buffer.truncate(written as usize);
return Ok(PathBuf::from(OsString::from_wide(&buffer)));
}
buffer.resize(written as usize, 0);
}
}
#[cfg(windows)]
fn windows_worker_neutral_cwd_path(snapshot_root: &Path) -> Result<PathBuf, String> {
use std::path::Prefix;
let mut components = snapshot_root.components();
let Some(Component::Prefix(prefix_component)) = components.next() else {
return Err(format!(
"managed worker snapshot lacks a Windows drive or UNC prefix: {}",
render_host_visible_path(snapshot_root)
));
};
if !matches!(components.next(), Some(Component::RootDir)) {
return Err(format!(
"managed worker snapshot is not rooted after its Windows prefix: {}",
render_host_visible_path(snapshot_root)
));
}
let neutral_root = match prefix_component.kind() {
Prefix::Disk(letter) | Prefix::VerbatimDisk(letter) => {
PathBuf::from(OsString::from_wide(&[
u16::from(letter),
u16::from(b':'),
92,
]))
}
Prefix::UNC(server, share) | Prefix::VerbatimUNC(server, share) => {
let mut encoded = vec![92, 92];
encoded.extend(server.encode_wide());
encoded.push(92);
encoded.extend(share.encode_wide());
encoded.push(92);
PathBuf::from(OsString::from_wide(&encoded))
}
_ => {
return Err(format!(
"unsupported Windows namespace for managed worker cwd: {}",
render_host_visible_path(snapshot_root)
));
}
};
let encoded_length = neutral_root.as_os_str().encode_wide().count();
if encoded_length.saturating_add(1) >= 260 {
return Err(format!(
"managed worker neutral Windows cwd reaches MAX_PATH: {}",
render_host_visible_path(&neutral_root)
));
}
Ok(neutral_root)
}
#[cfg(windows)]
fn windows_worker_neutral_cwd(snapshot_root: &Path) -> Result<PathBuf, String> {
let neutral_root = windows_worker_neutral_cwd_path(snapshot_root)?;
let metadata = fs::metadata(&neutral_root).map_err(|error| {
format!(
"failed to inspect managed worker neutral Windows cwd {}: {error}",
render_host_visible_path(&neutral_root)
)
})?;
if !metadata.is_dir() {
return Err(format!(
"managed worker neutral Windows cwd is not a directory: {}",
render_host_visible_path(&neutral_root)
));
}
Ok(neutral_root)
}
#[cfg(windows)]
fn windows_non_verbatim_path(path: &Path) -> Result<PathBuf, String> {
let encoded = path.as_os_str().encode_wide().collect::<Vec<_>>();
const VERBATIM_UNC_PREFIX: [u16; 8] = [92, 92, 63, 92, 85, 78, 67, 92];
const VERBATIM_PREFIX: [u16; 4] = [92, 92, 63, 92];
if encoded.starts_with(&VERBATIM_UNC_PREFIX) {
let mut normalized = Vec::with_capacity(encoded.len().saturating_sub(6));
normalized.extend_from_slice(&[92, 92]);
normalized.extend_from_slice(&encoded[VERBATIM_UNC_PREFIX.len()..]);
return Ok(PathBuf::from(OsString::from_wide(&normalized)));
}
if encoded.starts_with(&VERBATIM_PREFIX) {
let remainder = &encoded[VERBATIM_PREFIX.len()..];
let drive_qualified = remainder.len() >= 3
&& (remainder[0] >= u16::from(b'A') && remainder[0] <= u16::from(b'Z')
|| remainder[0] >= u16::from(b'a') && remainder[0] <= u16::from(b'z'))
&& remainder[1] == u16::from(b':')
&& remainder[2] == u16::from(b'\\');
if drive_qualified {
return Ok(PathBuf::from(OsString::from_wide(remainder)));
}
return Err(format!(
"unsupported Windows verbatim namespace for managed Node source: {}",
render_host_visible_path(path)
));
}
Ok(path.to_path_buf())
}
fn managed_python_session_executable(plan: &ManagedRuntimeEnvPlan) -> PathBuf {
if cfg!(windows) {
plan.env_dir
.join(".venv")
.join("Scripts")
.join("python.exe")
} else {
plan.env_dir.join(".venv").join("bin").join("python")
}
}
fn executable_parent(executable: &Path) -> Result<&Path, String> {
executable.parent().ok_or_else(|| {
format!(
"managed executable has no parent directory: {}",
render_host_visible_path(executable)
)
})
}
pub(crate) fn configure_managed_python_command_environment(
command: &mut Command,
plan: &ManagedRuntimeEnvPlan,
) -> Result<(), String> {
let virtual_env = plan.env_dir.join(".venv");
let python_executable = managed_python_session_executable(plan);
configure_managed_command_base_environment(
command,
&plan.env_dir,
&[
executable_parent(&python_executable)?.to_path_buf(),
executable_parent(&plan.runtime_executable)?.to_path_buf(),
],
)?;
command.env("VIRTUAL_ENV", virtual_env);
command.env("PYTHONNOUSERSITE", "1");
command.env("PYTHONUTF8", "1");
Ok(())
}
pub(crate) fn configure_managed_node_command_environment(
command: &mut Command,
plan: &ManagedRuntimeEnvPlan,
) -> Result<(), String> {
configure_managed_command_base_environment(
command,
&plan.env_dir,
&[
executable_parent(&plan.runtime_executable)?.to_path_buf(),
plan.env_dir.join("node_modules").join(".bin"),
],
)?;
command.env("NODE_PATH", plan.env_dir.join("node_modules"));
Ok(())
}
fn install_controlled_context_environment(
command: &mut Command,
package: &ManagedRuntimePackageContext,
) -> Result<(), String> {
let context = to_string(&package.worker_context_json())
.map_err(|error| format!("failed to encode managed session context: {error}"))?;
command.env("LUASKILLS_MANAGED_CONTEXT_JSON", context);
Ok(())
}
pub(crate) fn prepare_managed_package_snapshot(
plan: &ManagedRuntimeEnvPlan,
package: &ManagedRuntimePackageContext,
namespace: &str,
) -> Result<ManagedPackageSnapshot, String> {
let environment_lease = acquire_ready_managed_env_lease(plan)?;
prepare_managed_package_snapshot_with_lease(plan, package, namespace, Some(environment_lease))
}
#[cfg(test)]
pub(crate) fn prepare_unleased_managed_package_snapshot(
plan: &ManagedRuntimeEnvPlan,
package: &ManagedRuntimePackageContext,
namespace: &str,
) -> Result<ManagedPackageSnapshot, String> {
prepare_managed_package_snapshot_with_lease(plan, package, namespace, None)
}
fn prepare_managed_package_snapshot_with_lease(
plan: &ManagedRuntimeEnvPlan,
package: &ManagedRuntimePackageContext,
namespace: &str,
environment_lease: Option<ManagedRuntimeEnvLease>,
) -> Result<ManagedPackageSnapshot, String> {
if namespace.is_empty()
|| Path::new(namespace).components().count() != 1
|| namespace == "."
|| namespace == ".."
{
return Err("managed snapshot namespace must be one safe path component".to_string());
}
let cleanup_permit = reserve_managed_snapshot_cleanup_slot()?;
let snapshots_root = plan.env_dir.join(namespace);
fs::create_dir_all(&snapshots_root).map_err(|error| {
format!(
"failed to create managed package snapshot root {}: {error}",
render_host_visible_path(&snapshots_root)
)
})?;
let canonical_env_root = fs::canonicalize(&plan.env_dir).map_err(|error| {
format!(
"failed to canonicalize managed environment root {}: {error}",
render_host_visible_path(&plan.env_dir)
)
})?;
let canonical_snapshots_root = fs::canonicalize(&snapshots_root).map_err(|error| {
format!(
"failed to canonicalize managed package snapshot root {}: {error}",
render_host_visible_path(&snapshots_root)
)
})?;
if canonical_snapshots_root == canonical_env_root
|| !canonical_snapshots_root.starts_with(&canonical_env_root)
{
return Err(format!(
"managed package snapshot root {} escapes managed environment root {}",
render_host_visible_path(&canonical_snapshots_root),
render_host_visible_path(&canonical_env_root)
));
}
let mut snapshot_root = None;
let compact_package_hash = package
.identity()
.stable_hash()
.chars()
.take(8)
.collect::<String>();
for _attempt in 0..MAX_MANAGED_PACKAGE_SNAPSHOT_CREATE_ATTEMPTS {
let sequence = NEXT_MANAGED_PACKAGE_SNAPSHOT
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |current| {
current.checked_add(1)
})
.map(|previous| previous + 1)
.map_err(|_| "managed package snapshot sequence is exhausted".to_string())?;
let candidate = canonical_snapshots_root.join(format!(
"{:x}-{:x}-{sequence:x}-{compact_package_hash}",
std::process::id(),
package.owner_token()
));
match fs::create_dir(&candidate) {
Ok(()) => {
snapshot_root = Some(candidate);
break;
}
Err(error) if error.kind() == std::io::ErrorKind::AlreadyExists => continue,
Err(error) => {
return Err(format!(
"failed to create unique managed package snapshot {}: {error}",
render_host_visible_path(&candidate)
));
}
}
}
let snapshot_root = snapshot_root.ok_or_else(|| {
format!(
"failed to allocate a unique managed package snapshot after {MAX_MANAGED_PACKAGE_SNAPSHOT_CREATE_ATTEMPTS} attempts"
)
})?;
let mut preparation = ManagedSnapshotPreparation {
ownership: Some(ManagedSnapshotCleanupOwnership {
record: ManagedSnapshotCleanupRecord {
_environment_lease: environment_lease,
snapshots_root: canonical_snapshots_root.clone(),
snapshot_root: snapshot_root.clone(),
quarantine_root: None,
orphan_quarantine_root: None,
snapshot_present: true,
identity: None,
error_reported: false,
},
permit: cleanup_permit,
}),
};
let snapshot_metadata = fs::symlink_metadata(&snapshot_root).map_err(|error| {
format!(
"failed to inspect newly created managed package snapshot {}: {error}",
render_host_visible_path(&snapshot_root)
)
})?;
let snapshot_identity = managed_package_snapshot_identity(&snapshot_metadata, &snapshot_root)?;
preparation
.ownership
.as_mut()
.expect("live snapshot preparation must retain ownership")
.record
.identity = Some(snapshot_identity);
let canonical_snapshot_root = fs::canonicalize(&snapshot_root).map_err(|error| {
format!(
"failed to canonicalize newly created managed package snapshot {}: {error}",
render_host_visible_path(&snapshot_root)
)
})?;
if canonical_snapshot_root == canonical_snapshots_root
|| !canonical_snapshot_root.starts_with(&canonical_snapshots_root)
{
return Err(format!(
"new managed package snapshot {} escapes verified parent {}",
render_host_visible_path(&canonical_snapshot_root),
render_host_visible_path(&canonical_snapshots_root)
));
}
preparation
.ownership
.as_mut()
.expect("live snapshot preparation must retain ownership")
.record
.snapshot_root = canonical_snapshot_root;
let expected_snapshot_identity = preparation
.ownership
.as_ref()
.and_then(|ownership| ownership.record.identity.as_ref())
.cloned()
.ok_or_else(|| "managed snapshot identity is unavailable before copy".to_string())?;
let execution_pin = copy_managed_package_tree_from_fixed_root(
package.package_root(),
&snapshot_root,
Some(package.package_root_filesystem_identity()),
Some(&expected_snapshot_identity),
)?;
Ok(ManagedPackageSnapshot {
ownership: preparation.ownership.take(),
execution_pin: Some(execution_pin),
})
}
fn allocate_managed_snapshot_quarantine(snapshots_root: &Path) -> Result<PathBuf, String> {
for _attempt in 0..MAX_MANAGED_PACKAGE_SNAPSHOT_CREATE_ATTEMPTS {
let sequence = NEXT_MANAGED_PACKAGE_SNAPSHOT
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |current| {
current.checked_add(1)
})
.map(|previous| previous + 1)
.map_err(|_| "managed package snapshot sequence is exhausted".to_string())?;
let quarantine = snapshots_root.join(format!(".cleanup-{}-{sequence}", std::process::id()));
match fs::create_dir(&quarantine) {
Ok(()) => return Ok(quarantine),
Err(error) if error.kind() == std::io::ErrorKind::AlreadyExists => continue,
Err(error) => {
return Err(format!(
"failed to create managed snapshot quarantine {}: {error}",
render_host_visible_path(&quarantine)
));
}
}
}
Err(format!(
"failed to allocate a unique managed snapshot quarantine after {MAX_MANAGED_PACKAGE_SNAPSHOT_CREATE_ATTEMPTS} attempts"
))
}
fn remove_managed_package_snapshot(
record: &mut ManagedSnapshotCleanupRecord,
) -> Result<(), String> {
if let Some(orphan_quarantine_root) = record.orphan_quarantine_root.as_ref() {
match fs::remove_dir(orphan_quarantine_root) {
Ok(()) => record.orphan_quarantine_root = None,
Err(error) if error.kind() == std::io::ErrorKind::NotFound => {
record.orphan_quarantine_root = None;
}
Err(error) => {
return Err(format!(
"failed to remove orphaned managed snapshot quarantine {}: {error}",
render_host_visible_path(orphan_quarantine_root)
));
}
}
}
let Some(expected_identity) = record.identity.as_ref() else {
return match fs::remove_dir(&record.snapshot_root) {
Ok(()) => Ok(()),
Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(()),
Err(error) => Err(format!(
"failed to remove empty provisional managed snapshot {}: {error}",
render_host_visible_path(&record.snapshot_root)
)),
};
};
if record.quarantine_root.is_none() {
let canonical_parent = fs::canonicalize(&record.snapshots_root).map_err(|error| {
format!(
"failed to canonicalize managed package snapshot parent {}: {error}",
render_host_visible_path(&record.snapshots_root)
)
})?;
if canonical_parent != record.snapshots_root {
return Err(format!(
"refusing to remove managed package snapshot through a replaced parent: {}",
render_host_visible_path(&record.snapshots_root)
));
}
let quarantine_root = allocate_managed_snapshot_quarantine(&canonical_parent)?;
let isolated_snapshot = quarantine_root.join("captured");
match fs::rename(&record.snapshot_root, &isolated_snapshot) {
Ok(()) => {
record.snapshot_root = isolated_snapshot;
record.quarantine_root = Some(quarantine_root);
}
Err(error) if error.kind() == std::io::ErrorKind::NotFound => {
record.snapshot_root = isolated_snapshot;
record.quarantine_root = Some(quarantine_root);
record.snapshot_present = false;
}
Err(error) => {
record.orphan_quarantine_root = Some(quarantine_root);
let isolation_error = format!(
"failed to isolate managed package snapshot {}: {error}",
render_host_visible_path(&record.snapshot_root)
);
return match fs::remove_dir(
record
.orphan_quarantine_root
.as_ref()
.expect("failed rename must retain orphan quarantine ownership"),
) {
Ok(()) => {
record.orphan_quarantine_root = None;
Err(isolation_error)
}
Err(cleanup_error) if cleanup_error.kind() == std::io::ErrorKind::NotFound => {
record.orphan_quarantine_root = None;
Err(isolation_error)
}
Err(cleanup_error) => Err(format!(
"{isolation_error}; orphan quarantine cleanup also failed: {cleanup_error}"
)),
};
}
}
}
let quarantine_root = record
.quarantine_root
.as_ref()
.expect("isolated managed snapshot must retain its quarantine root");
if !record.snapshot_present {
return match fs::remove_dir(quarantine_root) {
Ok(()) => Ok(()),
Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(()),
Err(error) => Err(format!(
"failed to remove managed snapshot quarantine {}: {error}",
render_host_visible_path(quarantine_root)
)),
};
}
let isolated_snapshot = &record.snapshot_root;
let metadata = fs::symlink_metadata(isolated_snapshot).map_err(|error| {
format!(
"failed to inspect isolated managed package snapshot {}: {error}",
render_host_visible_path(isolated_snapshot)
)
})?;
if metadata.file_type().is_symlink() || !metadata.is_dir() {
return Err(format!(
"refusing to remove replaced managed package snapshot object: {}",
render_host_visible_path(isolated_snapshot)
));
}
let actual_identity = managed_package_snapshot_identity(&metadata, isolated_snapshot)?;
if &actual_identity != expected_identity {
return Err(format!(
"refusing to remove managed package snapshot whose filesystem identity changed: {}",
render_host_visible_path(isolated_snapshot)
));
}
let canonical_quarantine = fs::canonicalize(quarantine_root).map_err(|error| {
format!(
"failed to canonicalize managed snapshot quarantine {}: {error}",
render_host_visible_path(quarantine_root)
)
})?;
let canonical_isolated = fs::canonicalize(isolated_snapshot).map_err(|error| {
format!(
"failed to canonicalize isolated managed package snapshot {}: {error}",
render_host_visible_path(isolated_snapshot)
)
})?;
if canonical_quarantine != *quarantine_root
|| canonical_quarantine.parent() != Some(record.snapshots_root.as_path())
|| canonical_isolated != *isolated_snapshot
|| canonical_isolated.parent() != Some(canonical_quarantine.as_path())
{
return Err(format!(
"refusing to remove managed package snapshot outside its atomic quarantine: {}",
render_host_visible_path(&canonical_isolated)
));
}
remove_verified_managed_snapshot_tree(isolated_snapshot, expected_identity)?;
record.snapshot_present = false;
match fs::remove_dir(quarantine_root) {
Ok(()) => Ok(()),
Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(()),
Err(error) => Err(format!(
"failed to remove managed snapshot quarantine {}: {error}",
render_host_visible_path(quarantine_root)
)),
}
}
fn remove_verified_managed_snapshot_tree(
snapshot_root: &Path,
expected_identity: &ManagedPackageSnapshotIdentity,
) -> Result<(), String> {
#[cfg(unix)]
{
let path = CString::new(snapshot_root.as_os_str().as_bytes()).map_err(|_| {
format!(
"managed snapshot path contains an interior NUL: {}",
render_host_visible_path(snapshot_root)
)
})?;
let raw_fd = unsafe {
libc::open(
path.as_ptr(),
libc::O_RDONLY | libc::O_DIRECTORY | libc::O_CLOEXEC | libc::O_NOFOLLOW,
)
};
if raw_fd < 0 {
return Err(format!(
"failed to open isolated managed snapshot {}: {}",
render_host_visible_path(snapshot_root),
std::io::Error::last_os_error()
));
}
let directory = unsafe { OwnedFd::from_raw_fd(raw_fd) };
let mut stat: libc::stat = unsafe { std::mem::zeroed() };
if unsafe { libc::fstat(directory.as_raw_fd(), &mut stat) } != 0 {
return Err(format!(
"failed to inspect isolated managed snapshot handle {}: {}",
render_host_visible_path(snapshot_root),
std::io::Error::last_os_error()
));
}
let (device, inode) = unix_stat_device_inode(&stat)?;
let actual_identity = ManagedPackageSnapshotIdentity { device, inode };
if &actual_identity != expected_identity {
return Err(format!(
"isolated managed snapshot handle identity changed: {}",
render_host_visible_path(snapshot_root)
));
}
remove_unix_snapshot_directory_contents(directory.as_raw_fd(), snapshot_root)?;
drop(directory);
fs::remove_dir(snapshot_root).map_err(|error| {
format!(
"failed to remove empty isolated managed snapshot {}: {error}",
render_host_visible_path(snapshot_root)
)
})
}
#[cfg(windows)]
{
let directory = open_windows_snapshot_directory(snapshot_root, false)?;
let actual_identity = windows_snapshot_identity_from_handle(&directory, snapshot_root)?;
if &actual_identity != expected_identity {
return Err(format!(
"isolated managed snapshot handle identity changed: {}",
render_host_visible_path(snapshot_root)
));
}
remove_windows_snapshot_directory_contents(snapshot_root)?;
drop(directory);
fs::remove_dir(snapshot_root).map_err(|error| {
format!(
"failed to remove empty isolated managed snapshot {}: {error}",
render_host_visible_path(snapshot_root)
)
})
}
#[cfg(not(any(unix, windows)))]
{
let _ = expected_identity;
Err(format!(
"handle-anchored managed snapshot deletion is unsupported on this platform: {}",
render_host_visible_path(snapshot_root)
))
}
}
#[cfg(unix)]
fn remove_unix_snapshot_directory_contents(
directory_fd: RawFd,
display_path: &Path,
) -> Result<(), String> {
let duplicate_fd = unsafe { libc::dup(directory_fd) };
if duplicate_fd < 0 {
return Err(format!(
"failed to duplicate managed snapshot directory handle {}: {}",
render_host_visible_path(display_path),
std::io::Error::last_os_error()
));
}
let directory_stream = unsafe { libc::fdopendir(duplicate_fd) };
if directory_stream.is_null() {
unsafe { libc::close(duplicate_fd) };
return Err(format!(
"failed to enumerate managed snapshot directory handle {}: {}",
render_host_visible_path(display_path),
std::io::Error::last_os_error()
));
}
let mut names = Vec::<CString>::new();
loop {
let entry = unsafe { libc::readdir(directory_stream) };
if entry.is_null() {
break;
}
let name = unsafe { CStr::from_ptr((*entry).d_name.as_ptr()) };
if name.to_bytes() == b"." || name.to_bytes() == b".." {
continue;
}
names.push(CString::new(name.to_bytes()).map_err(|_| {
format!(
"managed snapshot entry contains an interior NUL under {}",
render_host_visible_path(display_path)
)
})?);
}
unsafe { libc::closedir(directory_stream) };
for name in names {
let mut stat: libc::stat = unsafe { std::mem::zeroed() };
if unsafe {
libc::fstatat(
directory_fd,
name.as_ptr(),
&mut stat,
libc::AT_SYMLINK_NOFOLLOW,
)
} != 0
{
return Err(format!(
"failed to inspect managed snapshot entry under {}: {}",
render_host_visible_path(display_path),
std::io::Error::last_os_error()
));
}
if stat.st_mode & libc::S_IFMT == libc::S_IFDIR {
let child_fd = unsafe {
libc::openat(
directory_fd,
name.as_ptr(),
libc::O_RDONLY | libc::O_DIRECTORY | libc::O_CLOEXEC | libc::O_NOFOLLOW,
)
};
if child_fd < 0 {
return Err(format!(
"failed to open managed snapshot child directory under {}: {}",
render_host_visible_path(display_path),
std::io::Error::last_os_error()
));
}
let child = unsafe { OwnedFd::from_raw_fd(child_fd) };
remove_unix_snapshot_directory_contents(child.as_raw_fd(), display_path)?;
drop(child);
if unsafe { libc::unlinkat(directory_fd, name.as_ptr(), libc::AT_REMOVEDIR) } != 0 {
return Err(format!(
"failed to remove managed snapshot child directory under {}: {}",
render_host_visible_path(display_path),
std::io::Error::last_os_error()
));
}
} else if unsafe { libc::unlinkat(directory_fd, name.as_ptr(), 0) } != 0 {
return Err(format!(
"failed to remove managed snapshot entry under {}: {}",
render_host_visible_path(display_path),
std::io::Error::last_os_error()
));
}
}
Ok(())
}
#[cfg(windows)]
fn remove_windows_snapshot_directory_contents(directory: &Path) -> Result<(), String> {
for entry in fs::read_dir(directory).map_err(|error| {
format!(
"failed to enumerate pinned managed snapshot {}: {error}",
render_host_visible_path(directory)
)
})? {
let entry = entry.map_err(|error| {
format!(
"failed to read pinned managed snapshot entry under {}: {error}",
render_host_visible_path(directory)
)
})?;
let path = entry.path();
let metadata = fs::symlink_metadata(&path).map_err(|error| {
format!(
"failed to inspect pinned managed snapshot entry {}: {error}",
render_host_visible_path(&path)
)
})?;
if metadata.file_type().is_symlink() || metadata.is_file() {
clear_windows_readonly_attribute(&path)?;
fs::remove_file(&path).map_err(|error| {
format!(
"failed to remove pinned managed snapshot file {}: {error}",
render_host_visible_path(&path)
)
})?;
} else if metadata.is_dir() {
remove_windows_snapshot_directory_contents(&path)?;
fs::remove_dir(&path).map_err(|error| {
format!(
"failed to remove pinned managed snapshot directory {}: {error}",
render_host_visible_path(&path)
)
})?;
} else {
return Err(format!(
"refusing to remove unsupported managed snapshot entry: {}",
render_host_visible_path(&path)
));
}
}
Ok(())
}
#[cfg(windows)]
fn open_windows_snapshot_directory(path: &Path, share_delete: bool) -> Result<OwnedHandle, String> {
let mut wide_path = path.as_os_str().encode_wide().collect::<Vec<_>>();
wide_path.push(0);
let share_mode =
FILE_SHARE_READ | FILE_SHARE_WRITE | if share_delete { FILE_SHARE_DELETE } else { 0 };
let desired_access = FILE_READ_ATTRIBUTES
| if share_delete {
0
} else {
WINDOWS_DELETE_ACCESS
};
let raw_handle = unsafe {
CreateFileW(
wide_path.as_ptr(),
desired_access,
share_mode,
std::ptr::null(),
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
std::ptr::null_mut(),
)
};
if raw_handle == INVALID_HANDLE_VALUE {
return Err(format!(
"failed to open managed package snapshot identity {}: {}",
render_host_visible_path(path),
std::io::Error::last_os_error()
));
}
Ok(unsafe { OwnedHandle::from_raw_handle(raw_handle as _) })
}
#[cfg(windows)]
fn windows_snapshot_identity_from_handle(
handle: &OwnedHandle,
path: &Path,
) -> Result<ManagedPackageSnapshotIdentity, String> {
let mut information: BY_HANDLE_FILE_INFORMATION = unsafe { std::mem::zeroed() };
let status =
unsafe { GetFileInformationByHandle(handle.as_raw_handle() as _, &mut information) };
if status == 0 {
return Err(format!(
"failed to read managed package snapshot identity {}: {}",
render_host_visible_path(path),
std::io::Error::last_os_error()
));
}
let volume_serial_number = information.dwVolumeSerialNumber;
let file_index =
(u64::from(information.nFileIndexHigh) << 32) | u64::from(information.nFileIndexLow);
if volume_serial_number == 0 && file_index == 0 {
return Err(format!(
"managed package snapshot has no Windows filesystem identity: {}",
render_host_visible_path(path)
));
}
Ok(ManagedPackageSnapshotIdentity {
volume_serial_number,
file_index,
})
}
fn managed_package_snapshot_identity(
metadata: &fs::Metadata,
path: &Path,
) -> Result<ManagedPackageSnapshotIdentity, String> {
#[cfg(unix)]
{
let _ = path;
Ok(ManagedPackageSnapshotIdentity {
device: metadata.dev(),
inode: metadata.ino(),
})
}
#[cfg(windows)]
{
let _ = metadata;
let handle = open_windows_snapshot_directory(path, true)?;
windows_snapshot_identity_from_handle(&handle, path)
}
#[cfg(not(any(unix, windows)))]
{
let _ = metadata;
Err(format!(
"managed package snapshot identity is unsupported on this platform: {}",
render_host_visible_path(path)
))
}
}
fn ensure_regular_file(path: &Path, label: &str) -> Result<(), String> {
let metadata = fs::metadata(path).map_err(|error| {
format!(
"failed to inspect {label} {}: {error}",
render_host_visible_path(path)
)
})?;
if !metadata.is_file() {
return Err(format!(
"{label} is not a file: {}",
render_host_visible_path(path)
));
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
fn snapshot_cleanup_test_record(
snapshots_root: PathBuf,
snapshot_root: PathBuf,
identity: ManagedPackageSnapshotIdentity,
) -> ManagedSnapshotCleanupRecord {
ManagedSnapshotCleanupRecord {
_environment_lease: None,
snapshots_root,
snapshot_root,
quarantine_root: None,
orphan_quarantine_root: None,
snapshot_present: true,
identity: Some(identity),
error_reported: false,
}
}
fn snapshot_identity_test_root(label: &str) -> PathBuf {
std::env::temp_dir().join(format!(
"luaskills-snapshot-identity-{label}-{}-{}",
std::process::id(),
NEXT_MANAGED_PACKAGE_SNAPSHOT.fetch_add(1, Ordering::Relaxed)
))
}
fn snapshot_test_tree_contains_file(root: &Path, file_name: &str) -> bool {
let Ok(entries) = fs::read_dir(root) else {
return false;
};
for entry in entries.flatten() {
let path = entry.path();
let Ok(metadata) = fs::symlink_metadata(&path) else {
continue;
};
if metadata.is_file() && entry.file_name() == file_name {
return true;
}
if metadata.is_dir() && snapshot_test_tree_contains_file(&path, file_name) {
return true;
}
}
false
}
#[test]
fn managed_snapshot_cleanup_panic_is_retried_without_losing_ownership() {
let root = snapshot_identity_test_root("cleanup-panic");
let snapshot = root.join("snapshot");
fs::create_dir_all(&snapshot).expect("create cleanup panic snapshot");
fs::write(snapshot.join("owned.txt"), b"owned")
.expect("write cleanup panic snapshot evidence");
let canonical_root = fs::canonicalize(&root).expect("canonicalize cleanup panic root");
let canonical_snapshot =
fs::canonicalize(&snapshot).expect("canonicalize cleanup panic snapshot");
let identity = managed_package_snapshot_identity(
&fs::symlink_metadata(&canonical_snapshot).expect("inspect cleanup panic snapshot"),
&canonical_snapshot,
)
.expect("capture cleanup panic snapshot identity");
let permit =
reserve_managed_snapshot_cleanup_slot().expect("reserve cleanup panic retry capacity");
let ownership = ManagedSnapshotCleanupOwnership {
record: snapshot_cleanup_test_record(
canonical_root,
canonical_snapshot.clone(),
identity,
),
permit,
};
cleanup_or_handoff_managed_snapshot_with(Some(ownership), |_record| {
panic!("forced managed snapshot cleanup panic");
});
let deadline = std::time::Instant::now() + Duration::from_secs(5);
while canonical_snapshot.exists() && std::time::Instant::now() < deadline {
std::thread::sleep(Duration::from_millis(10));
}
assert!(
!canonical_snapshot.exists(),
"persistent retry must remove the snapshot retained across panic"
);
let _ = fs::remove_dir_all(root);
}
#[test]
fn managed_snapshot_cleanup_rejects_directory_identity_replacement() {
let root = snapshot_identity_test_root("directory");
let snapshot = root.join("snapshot");
let original = root.join("original");
fs::create_dir_all(&snapshot).expect("create original snapshot directory");
let canonical_root = fs::canonicalize(&root).expect("canonicalize snapshot test root");
let canonical_snapshot =
fs::canonicalize(&snapshot).expect("canonicalize original snapshot");
let identity = managed_package_snapshot_identity(
&fs::symlink_metadata(&snapshot).expect("inspect original snapshot"),
&snapshot,
)
.expect("capture original snapshot identity");
fs::rename(&snapshot, &original).expect("move original snapshot object");
fs::create_dir(&snapshot).expect("create replacement snapshot directory");
fs::write(snapshot.join("replacement.txt"), b"replacement")
.expect("write replacement marker");
let mut record = snapshot_cleanup_test_record(canonical_root, canonical_snapshot, identity);
let error = remove_managed_package_snapshot(&mut record)
.expect_err("replacement directory identity must be rejected");
assert!(error.contains("filesystem identity changed"));
assert!(record.quarantine_root.is_some());
assert_eq!(
record
.snapshot_root
.file_name()
.and_then(|name| name.to_str()),
Some("captured")
);
assert!(snapshot_test_tree_contains_file(&root, "replacement.txt"));
fs::remove_dir_all(&root).expect("remove snapshot identity test root");
}
#[cfg(windows)]
#[test]
fn windows_snapshot_cleanup_handle_prevents_root_replacement() {
let root = snapshot_identity_test_root("windows-handle");
let snapshot = root.join("snapshot");
let replacement = root.join("replacement");
fs::create_dir_all(&snapshot).expect("create pinned snapshot directory");
let handle = open_windows_snapshot_directory(&snapshot, false)
.expect("open non-delete-sharing snapshot handle");
let rename_error = fs::rename(&snapshot, &replacement)
.expect_err("pinned Windows snapshot root must reject rename");
assert!(
snapshot.is_dir(),
"pinned snapshot root must remain in place"
);
assert!(!replacement.exists());
drop(rename_error);
drop(handle);
fs::remove_dir_all(&root).expect("remove Windows handle test root");
}
#[cfg(windows)]
#[test]
fn windows_pinned_session_cwd_uses_handle_authoritative_path() {
let root = snapshot_identity_test_root("windows-cwd-pin");
let cwd = root.join("cwd");
let replacement = root.join("replacement");
fs::create_dir_all(&cwd).expect("create pinned Windows session cwd");
let resolved = fs::canonicalize(&cwd).expect("canonicalize Windows session cwd");
let pin = pin_managed_session_cwd(&resolved).expect("pin Windows session cwd");
let authoritative = authoritative_managed_session_cwd_path(&pin, &resolved)
.expect("derive authoritative Windows session cwd");
assert_eq!(authoritative, resolved);
fs::rename(&cwd, &replacement)
.expect_err("pinned Windows session cwd must reject replacement");
assert!(cwd.is_dir());
assert!(!replacement.exists());
drop(pin);
fs::remove_dir_all(&root).expect("remove Windows cwd-pin test root");
}
#[cfg(windows)]
#[test]
fn windows_node_path_rejects_non_dos_verbatim_namespace() {
let volume_path = Path::new(r"\\?\Volume{00000000-0000-0000-0000-000000000000}\entry.mjs");
let error = windows_non_verbatim_path(volume_path)
.expect_err("volume GUID path must not become a relative Node source");
assert!(error.contains("unsupported Windows verbatim namespace"));
}
#[cfg(windows)]
#[test]
fn windows_worker_neutral_cwd_derives_drive_and_share_roots() {
assert_eq!(
windows_worker_neutral_cwd_path(Path::new(r"C:\deep\snapshot"))
.expect("derive DOS drive root"),
PathBuf::from(r"C:\")
);
assert_eq!(
windows_worker_neutral_cwd_path(Path::new(r"\\?\C:\deep\snapshot"))
.expect("derive verbatim DOS drive root"),
PathBuf::from(r"C:\")
);
assert_eq!(
windows_worker_neutral_cwd_path(Path::new(r"\\server\share\deep\snapshot"))
.expect("derive UNC share root"),
PathBuf::from(r"\\server\share\")
);
assert_eq!(
windows_worker_neutral_cwd_path(Path::new(r"\\?\UNC\server\share\deep\snapshot",))
.expect("derive verbatim UNC share root"),
PathBuf::from(r"\\server\share\")
);
}
#[cfg(windows)]
#[test]
fn windows_worker_neutral_cwd_rejects_unsupported_or_oversized_roots() {
let volume_error = windows_worker_neutral_cwd_path(Path::new(
r"\\?\Volume{00000000-0000-0000-0000-000000000000}\snapshot",
))
.expect_err("Volume GUID cwd must be rejected");
assert!(volume_error.contains("unsupported Windows namespace"));
let oversized_server = "s".repeat(250);
let oversized_path = PathBuf::from(format!(r"\\{oversized_server}\share\snapshot"));
let length_error = windows_worker_neutral_cwd_path(&oversized_path)
.expect_err("oversized UNC root must be rejected");
assert!(length_error.contains("reaches MAX_PATH"));
}
#[cfg(windows)]
#[test]
fn windows_snapshot_execution_pin_denies_mutation_and_replacement() {
let root = snapshot_identity_test_root("windows-execution-pin");
let snapshot = root.join("snapshot");
let replacement = root.join("replacement");
let source = snapshot.join("runtime.js");
fs::create_dir_all(&snapshot).expect("create execution snapshot directory");
fs::write(&source, "console.log('pinned')").expect("write execution snapshot source");
let pin = pin_managed_snapshot_execution_tree(&snapshot)
.expect("pin complete Windows execution snapshot");
fs::write(&source, "console.log('replaced')")
.expect_err("pinned snapshot source must reject writes");
fs::rename(&snapshot, &replacement)
.expect_err("pinned snapshot root must reject replacement");
drop(pin);
fs::remove_dir_all(&root).expect("remove Windows execution-pin test root");
}
#[cfg(unix)]
#[test]
fn unix_worker_source_validation_is_fd_relative_and_symlink_safe() {
let root = snapshot_identity_test_root("unix-worker-source");
let runtime_dir = root.join("runtime");
let source = runtime_dir.join("entry.py");
let outside = root.join("outside.py");
fs::create_dir_all(&runtime_dir).expect("create Unix worker source directory");
fs::write(&source, b"print('ok')\n").expect("write Unix worker source");
fs::write(&outside, b"print('outside')\n").expect("write outside Unix worker source");
let encoded_root = CString::new(root.as_os_str().as_bytes()).expect("encode Unix root");
let raw_fd = unsafe {
libc::open(
encoded_root.as_ptr(),
libc::O_RDONLY | libc::O_DIRECTORY | libc::O_CLOEXEC | libc::O_NOFOLLOW,
)
};
assert!(raw_fd >= 0, "open Unix worker source root");
let root_directory = unsafe { OwnedFd::from_raw_fd(raw_fd) };
validate_unix_snapshot_regular_file(
root_directory.as_raw_fd(),
Path::new("runtime/entry.py"),
&root,
)
.expect("validate fd-relative Unix worker source");
let redirected = runtime_dir.join("redirected.py");
std::os::unix::fs::symlink(&outside, &redirected)
.expect("create redirected Unix worker source");
let error = validate_unix_snapshot_regular_file(
root_directory.as_raw_fd(),
Path::new("runtime/redirected.py"),
&root,
)
.expect_err("Unix worker source symlink must be rejected");
assert!(error.contains("failed to open managed worker snapshot source"));
let outside_directory = root.join("outside-directory");
fs::create_dir_all(&outside_directory).expect("create outside Unix source directory");
fs::write(
outside_directory.join("entry.py"),
b"print('outside directory')\n",
)
.expect("write outside directory source");
std::os::unix::fs::symlink(&outside_directory, root.join("redirected-directory"))
.expect("create redirected Unix source directory");
let intermediate_error = validate_unix_snapshot_regular_file(
root_directory.as_raw_fd(),
Path::new("redirected-directory/entry.py"),
&root,
)
.expect_err("Unix worker source intermediate symlink must be rejected");
assert!(intermediate_error.contains("failed to open managed worker snapshot source"));
fs::remove_dir_all(&root).expect("remove Unix worker source validation root");
}
#[cfg(unix)]
#[test]
fn managed_snapshot_cleanup_rejects_symlink_redirection() {
let root = snapshot_identity_test_root("symlink");
let snapshot = root.join("snapshot");
let original = root.join("original");
let sibling = root.join("sibling");
fs::create_dir_all(&snapshot).expect("create original snapshot directory");
fs::create_dir_all(&sibling).expect("create sibling snapshot directory");
fs::write(sibling.join("active.txt"), b"active").expect("write sibling marker");
let canonical_root = fs::canonicalize(&root).expect("canonicalize snapshot test root");
let canonical_snapshot =
fs::canonicalize(&snapshot).expect("canonicalize original snapshot");
let identity = managed_package_snapshot_identity(
&fs::symlink_metadata(&snapshot).expect("inspect original snapshot"),
&snapshot,
)
.expect("capture original snapshot identity");
fs::rename(&snapshot, &original).expect("move original snapshot object");
std::os::unix::fs::symlink(&sibling, &snapshot).expect("redirect snapshot symlink");
let mut record = snapshot_cleanup_test_record(canonical_root, canonical_snapshot, identity);
let error = remove_managed_package_snapshot(&mut record)
.expect_err("snapshot symlink redirection must be rejected");
assert!(error.contains("replaced managed package snapshot object"));
assert!(sibling.join("active.txt").is_file());
fs::remove_dir_all(&root).expect("remove snapshot symlink test root");
}
#[cfg(unix)]
#[test]
fn unix_snapshot_cleanup_stays_anchored_after_root_replacement() {
let root = snapshot_identity_test_root("unix-handle");
let snapshot = root.join("snapshot");
let moved = root.join("moved");
fs::create_dir_all(&snapshot).expect("create Unix anchored snapshot");
fs::write(snapshot.join("owned.txt"), b"owned").expect("write owned snapshot file");
let path = CString::new(snapshot.as_os_str().as_bytes()).expect("encode snapshot path");
let raw_fd = unsafe {
libc::open(
path.as_ptr(),
libc::O_RDONLY | libc::O_DIRECTORY | libc::O_CLOEXEC | libc::O_NOFOLLOW,
)
};
assert!(raw_fd >= 0, "open Unix snapshot directory fd");
let directory = unsafe { OwnedFd::from_raw_fd(raw_fd) };
fs::rename(&snapshot, &moved).expect("move opened Unix snapshot");
fs::create_dir(&snapshot).expect("create replacement Unix snapshot path");
fs::write(snapshot.join("replacement.txt"), b"replacement")
.expect("write replacement Unix snapshot marker");
remove_unix_snapshot_directory_contents(directory.as_raw_fd(), &snapshot)
.expect("remove contents through anchored Unix fd");
assert!(!moved.join("owned.txt").exists());
assert!(snapshot.join("replacement.txt").is_file());
drop(directory);
fs::remove_dir_all(&root).expect("remove Unix anchored snapshot test root");
}
#[cfg(target_os = "macos")]
#[test]
fn macos_execution_path_follows_pinned_root_object() {
let root = snapshot_identity_test_root("macos-execution-object");
let snapshot = root.join("snapshot");
let moved = root.join("moved");
fs::create_dir_all(snapshot.join("runtime")).expect("create macOS snapshot source tree");
fs::write(snapshot.join("runtime/entry.py"), b"trusted\n")
.expect("write trusted macOS snapshot source");
let encoded_snapshot =
path_to_c_string(&snapshot, "macOS snapshot test root").expect("encode snapshot root");
let raw_fd = unsafe {
libc::open(
encoded_snapshot.as_ptr(),
libc::O_RDONLY | libc::O_DIRECTORY | libc::O_CLOEXEC | libc::O_NOFOLLOW,
)
};
assert!(raw_fd >= 0, "open macOS snapshot root");
let directory = unsafe { OwnedFd::from_raw_fd(raw_fd) };
fs::rename(&snapshot, &moved).expect("move pinned macOS snapshot root");
let canonical_moved = fs::canonicalize(&moved).expect("canonicalize moved macOS snapshot");
fs::create_dir_all(snapshot.join("runtime")).expect("create replacement snapshot root");
fs::write(snapshot.join("runtime/entry.py"), b"replacement\n")
.expect("write replacement macOS source");
let execution_path = macos_snapshot_execution_source_path(
directory.as_raw_fd(),
Path::new("runtime/entry.py"),
&snapshot,
)
.expect("derive path from pinned macOS root object");
assert_eq!(
fs::read(&execution_path).expect("read object-derived macOS source"),
b"trusted\n"
);
assert!(execution_path.starts_with(&canonical_moved));
fs::remove_dir_all(&root).expect("remove macOS execution object test root");
}
#[cfg(target_os = "macos")]
#[test]
fn macos_execution_source_revalidation_rejects_replacement() {
let root = snapshot_identity_test_root("macos-source-replacement");
let snapshot = root.join("snapshot");
let source = snapshot.join("entry.py");
let moved_source = snapshot.join("entry-original.py");
fs::create_dir_all(&snapshot).expect("create macOS source replacement root");
fs::write(&source, b"trusted\n").expect("write original macOS source");
let encoded_snapshot =
path_to_c_string(&snapshot, "macOS source test root").expect("encode snapshot root");
let raw_fd = unsafe {
libc::open(
encoded_snapshot.as_ptr(),
libc::O_RDONLY | libc::O_DIRECTORY | libc::O_CLOEXEC | libc::O_NOFOLLOW,
)
};
assert!(raw_fd >= 0, "open macOS source replacement root");
let directory = unsafe { OwnedFd::from_raw_fd(raw_fd) };
let expected = macos_file_identity_from_snapshot(
directory.as_raw_fd(),
Path::new("entry.py"),
&snapshot,
)
.expect("capture original macOS source identity");
fs::rename(&source, &moved_source).expect("move original macOS source");
fs::write(&source, b"replacement\n").expect("write replacement macOS source");
let encoded_source =
path_to_c_string(&source, "macOS named source").expect("encode named source");
let error = macos_validate_named_execution_source(&encoded_source, expected)
.expect_err("replacement macOS source must fail identity validation");
assert!(error.to_string().contains("identity changed"));
fs::remove_dir_all(&root).expect("remove macOS source replacement test root");
}
}