diff options
author | Alec Di Vito <me@alecdivito.com> | 2025-03-12 22:04:10 +0000 |
---|---|---|
committer | Alec Di Vito <me@alecdivito.com> | 2025-03-12 22:04:10 +0000 |
commit | 4dd19e66241eff3c54cd2f0c68989bbf9d434b18 (patch) | |
tree | 16fe05129fa542b79c3c75a26ba2dbc0464102e0 | |
parent | Add link to miniserve GitHub to footer (diff) | |
download | miniserve-4dd19e66241eff3c54cd2f0c68989bbf9d434b18.tar.gz miniserve-4dd19e66241eff3c54cd2f0c68989bbf9d434b18.zip |
fix: copy file if rename operation fails
-rw-r--r-- | src/file_op.rs | 33 |
1 files changed, 26 insertions, 7 deletions
diff --git a/src/file_op.rs b/src/file_op.rs index 375ff7d..3504011 100644 --- a/src/file_op.rs +++ b/src/file_op.rs @@ -16,7 +16,7 @@ use std::sync::Arc; use actix_web::{HttpRequest, HttpResponse, http::header, web}; use async_walkdir::WalkDir; use futures::{StreamExt, TryStreamExt}; -use log::{info, warn}; +use log::{error, info, warn}; use serde::Deserialize; use sha2::digest::DynDigest; use sha2::{Digest, Sha256, Sha512}; @@ -227,12 +227,31 @@ async fn save_file( } info!("File upload successful to {temp_path:?}. Moving to {file_path:?}",); - if let Err(e) = tokio::fs::rename(&temp_path, &file_path).await { - let _ = tokio::fs::remove_file(&temp_path).await; - return Err(RuntimeError::IoError( - format!("Failed to move temporary file {temp_path:?} to {file_path:?}",), - e, - )); + if let Err(err) = tokio::fs::rename(&temp_path, &file_path).await { + match err.kind() { + ErrorKind::CrossesDevices => { + warn!( + "File writen to {temp_path:?} must be copied to {file_path:?} because it's on a different filesystem" + ); + let copy_result = tokio::fs::copy(&temp_path, &file_path).await; + if let Err(e) = tokio::fs::remove_file(&temp_path).await { + error!("Failed to clean up temp file at {temp_path:?} with error {e:?}"); + } + copy_result.map_err(|e| { + RuntimeError::IoError( + format!("Failed to copy file from {temp_path:?} to {file_path:?}"), + e, + ) + })?; + } + _ => { + let _ = tokio::fs::remove_file(&temp_path).await; + return Err(RuntimeError::IoError( + format!("Failed to move temporary file {temp_path:?} to {file_path:?}",), + err, + )); + } + } } Ok(written_len) |