Fix permissions on demand instead of every launch
Instead of chmod on every app start, catch EACCES (error 13) when spawning sidecar or ffmpeg, fix permissions, then retry once: - sidecar spawn: catches permission denied, runs set_executable_permissions on the sidecar dir, retries spawn - ffmpeg: catches permission denied, chmod +x ffmpeg and ffprobe, retries Zero overhead on normal launches. Only fixes permissions when actually needed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -50,9 +50,37 @@ pub fn extract_audio(file_path: String, output_path: Option<String>) -> Result<S
|
||||
#[cfg(target_os = "windows")]
|
||||
cmd.creation_flags(0x08000000);
|
||||
|
||||
let status = cmd
|
||||
let status = match cmd.status() {
|
||||
Ok(s) => s,
|
||||
Err(e) if e.raw_os_error() == Some(13) => {
|
||||
// Permission denied — fix permissions and retry
|
||||
eprintln!("[media] Permission denied on ffmpeg, fixing permissions and retrying...");
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
if let Ok(meta) = std::fs::metadata(&ffmpeg) {
|
||||
let mut perms = meta.permissions();
|
||||
perms.set_mode(0o755);
|
||||
let _ = std::fs::set_permissions(&ffmpeg, perms);
|
||||
}
|
||||
// Also fix ffprobe if it exists
|
||||
let ffprobe = ffmpeg.replace("ffmpeg", "ffprobe");
|
||||
if let Ok(meta) = std::fs::metadata(&ffprobe) {
|
||||
let mut perms = meta.permissions();
|
||||
perms.set_mode(0o755);
|
||||
let _ = std::fs::set_permissions(&ffprobe, perms);
|
||||
}
|
||||
}
|
||||
Command::new(&ffmpeg)
|
||||
.args(["-y", "-i", &file_path, "-vn", "-acodec", "pcm_s16le", "-ar", "22050", "-ac", "1"])
|
||||
.arg(output.to_str().unwrap())
|
||||
.stdout(std::process::Stdio::null())
|
||||
.stderr(std::process::Stdio::piped())
|
||||
.status()
|
||||
.map_err(|e| format!("Failed to run ffmpeg: {e}"))?;
|
||||
.map_err(|e| format!("Failed to run ffmpeg after chmod: {e}"))?
|
||||
}
|
||||
Err(e) => return Err(format!("Failed to run ffmpeg: {e}")),
|
||||
};
|
||||
|
||||
if !status.success() {
|
||||
return Err(format!("ffmpeg exited with status {status}"));
|
||||
|
||||
@@ -98,9 +98,6 @@ impl SidecarManager {
|
||||
|
||||
// Already extracted — use it directly
|
||||
if binary_path.exists() {
|
||||
// Ensure all binaries are executable (fixes previously extracted dirs)
|
||||
#[cfg(unix)]
|
||||
Self::set_executable_permissions(&extract_dir);
|
||||
Self::cleanup_old_sidecars(data_dir, ¤t_version);
|
||||
return Ok(binary_path);
|
||||
}
|
||||
@@ -334,13 +331,40 @@ impl SidecarManager {
|
||||
#[cfg(target_os = "windows")]
|
||||
cmd.creation_flags(0x08000000);
|
||||
|
||||
let child = cmd
|
||||
.spawn()
|
||||
.map_err(|e| format!("Failed to start sidecar binary: {e}"))?;
|
||||
|
||||
match cmd.spawn() {
|
||||
Ok(child) => {
|
||||
self.attach(child)?;
|
||||
self.wait_for_ready()
|
||||
}
|
||||
Err(e) if e.raw_os_error() == Some(13) => {
|
||||
// Permission denied — fix permissions and retry once
|
||||
eprintln!("[sidecar-rs] Permission denied, fixing permissions and retrying...");
|
||||
if let Some(dir) = path.parent() {
|
||||
Self::set_executable_permissions(dir);
|
||||
}
|
||||
let mut retry_cmd = Command::new(path);
|
||||
retry_cmd
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(if let Some(data_dir) = DATA_DIR.get() {
|
||||
let log_path = data_dir.join("sidecar.log");
|
||||
std::fs::File::create(&log_path)
|
||||
.map(Stdio::from)
|
||||
.unwrap_or_else(|_| Stdio::inherit())
|
||||
} else {
|
||||
Stdio::inherit()
|
||||
});
|
||||
#[cfg(target_os = "windows")]
|
||||
retry_cmd.creation_flags(0x08000000);
|
||||
let child = retry_cmd
|
||||
.spawn()
|
||||
.map_err(|e| format!("Failed to start sidecar binary after chmod: {e}"))?;
|
||||
self.attach(child)?;
|
||||
self.wait_for_ready()
|
||||
}
|
||||
Err(e) => Err(format!("Failed to start sidecar binary: {e}")),
|
||||
}
|
||||
}
|
||||
|
||||
/// Spawn the Python sidecar in dev mode (system Python).
|
||||
fn start_python_dev(&self) -> Result<(), String> {
|
||||
|
||||
Reference in New Issue
Block a user