Try using 'mv' instead of fs::rename/copy on linux

This commit is contained in:
Caelan Sayler
2024-06-04 21:45:48 +01:00
parent bfb469566a
commit b95342a6d9

View File

@@ -22,29 +22,19 @@ pub fn apply_package_impl<'a>(root_path: &PathBuf, _app: &Manifest, pkg: &PathBu
std::fs::set_permissions(&temp_path, <std::fs::Permissions as std::os::unix::fs::PermissionsExt>::from_mode(0o755))?;
info!("Moving temp file to target: {}", &root_path.to_string_lossy());
let mut result: Result<(), std::io::Error> = std::fs::rename(&temp_path, &root_path);
if result.is_ok() {
// we use mv instead of fs::rename / fs::copy because rename fails cross-device
// and copy fails if the process is running (presumably because rust opens the file for writing)
// while mv works in both cases.
let mv_args = vec![&temp_path, &root_path.to_string_lossy().to_string()];
let mv_output = Command::new("mv").args(mv_args).output()?;
if mv_output.status.success() {
info!("AppImage moved successfully to: {}", &root_path.to_string_lossy());
return Ok(());
}
let mut result_err = result.unwrap_err();
// if we tried to rename across filesystems, let's try again with a copy.
// ideally we check against std::io::ErrorKind::CrossesDevices but that is unstable at the moment
if Some(18) == result_err.raw_os_error() {
info!("Move failed (cross-device), trying again with a copy.");
result = std::fs::copy(&temp_path, &root_path).map(|_| {});
if result.is_ok() {
info!("AppImage copied successfully to: {}", &root_path.to_string_lossy());
return Ok(());
}
result_err = result.unwrap_err();
}
// if the operation failed with permission denied, let's try again elevated with pkexec
if result_err.kind() == std::io::ErrorKind::PermissionDenied {
error!("An error occurred {}, will attempt to elevate permissions and try again...", result_err);
// if the operation failed, let's try again elevated with pkexec
error!("An error occurred ({:?}), will attempt to elevate permissions and try again...", mv_output);
dialogs::ask_user_to_elevate(&manifest)?;
let script = format!("#!/bin/sh\nmv -f '{}' '{}'", temp_path, &root_path.to_string_lossy());
info!("Writing script for elevation: \n{}", script);
@@ -52,16 +42,15 @@ pub fn apply_package_impl<'a>(root_path: &PathBuf, _app: &Manifest, pkg: &PathBu
std::fs::set_permissions(&script_path, <std::fs::Permissions as std::os::unix::fs::PermissionsExt>::from_mode(0o755))?;
let args = vec![&script_path];
info!("Attempting to elevate: pkexec {:?}", args);
let status = Command::new("pkexec").args(args).status()?;
if status.success() {
let elev_output = Command::new("pkexec").args(args).output()?;
if elev_output.status.success() {
info!("AppImage moved (elevated) to {}", &root_path.to_string_lossy());
return Ok(());
} else {
bail!("pkexec exited with status: {}", status);
}
bail!("pkexec failed with status: {:?}", elev_output);
}
bail!("Failed to move the AppImage to target ({})", result_err);
bail!("Failed to move the AppImage to target, bailing...");
})();
let _ = fs::remove_file(&script_path);
let _ = fs::remove_file(&temp_path);