Preserve symlinks in file copy
ci / test (push) Has been cancelled
ci / fuzz-smoke (push) Has been cancelled
ci / windows-client (push) Has been cancelled
ci / package-release (linux-x86_64, ubuntu-latest) (push) Has been cancelled
ci / package-release (macos-aarch64, macos-14) (push) Has been cancelled
ci / package-release (macos-x86_64, macos-13) (push) Has been cancelled
ci / package-release (windows-x86_64, windows-latest) (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
ci / test (push) Has been cancelled
ci / fuzz-smoke (push) Has been cancelled
ci / windows-client (push) Has been cancelled
ci / package-release (linux-x86_64, ubuntu-latest) (push) Has been cancelled
ci / package-release (macos-aarch64, macos-14) (push) Has been cancelled
ci / package-release (macos-x86_64, macos-13) (push) Has been cancelled
ci / package-release (windows-x86_64, windows-latest) (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
This commit is contained in:
@@ -2681,6 +2681,46 @@ async fn handle_file_request(
|
||||
send_file_response_to_client(state, socket, client_id, stream_id, FileResponse::Ok)
|
||||
.await
|
||||
}
|
||||
FileRequest::Readlink { path } => {
|
||||
let path = clean_remote_path(&path, home)?;
|
||||
let target =
|
||||
fs::read_link(&path).with_context(|| format!("readlink {}", path.display()))?;
|
||||
let target = target
|
||||
.to_str()
|
||||
.ok_or_else(|| anyhow!("symlink target is not valid UTF-8"))?
|
||||
.to_string();
|
||||
send_file_response_to_client(
|
||||
state,
|
||||
socket,
|
||||
client_id,
|
||||
stream_id,
|
||||
FileResponse::LinkTarget { target },
|
||||
)
|
||||
.await
|
||||
}
|
||||
FileRequest::Symlink {
|
||||
path,
|
||||
target,
|
||||
overwrite,
|
||||
} => {
|
||||
let path = clean_remote_path(&path, home)?;
|
||||
if let Some(parent) = path.parent() {
|
||||
fs::create_dir_all(parent)
|
||||
.with_context(|| format!("create {}", parent.display()))?;
|
||||
}
|
||||
if let Ok(metadata) = fs::symlink_metadata(&path) {
|
||||
anyhow::ensure!(overwrite, "destination exists: {}", path.display());
|
||||
anyhow::ensure!(
|
||||
!metadata.is_dir(),
|
||||
"destination is a directory: {}",
|
||||
path.display()
|
||||
);
|
||||
fs::remove_file(&path).with_context(|| format!("remove {}", path.display()))?;
|
||||
}
|
||||
create_symlink(&target, &path)?;
|
||||
send_file_response_to_client(state, socket, client_id, stream_id, FileResponse::Ok)
|
||||
.await
|
||||
}
|
||||
FileRequest::Remove { path, recursive } => {
|
||||
let path = clean_remote_path(&path, home)?;
|
||||
let metadata =
|
||||
@@ -3065,6 +3105,17 @@ fn set_mode(path: &Path, mode: u32) -> Result<()> {
|
||||
fs::set_permissions(path, permissions).with_context(|| format!("chmod {}", path.display()))
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn create_symlink(target: &str, path: &Path) -> Result<()> {
|
||||
std::os::unix::fs::symlink(target, path)
|
||||
.with_context(|| format!("symlink {} -> {}", path.display(), target))
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn create_symlink(_target: &str, _path: &Path) -> Result<()> {
|
||||
bail!("symlink creation is not supported on this server platform")
|
||||
}
|
||||
|
||||
fn upload_temp_path(final_path: &Path, stream_id: u64) -> PathBuf {
|
||||
let name = final_path
|
||||
.file_name()
|
||||
|
||||
Reference in New Issue
Block a user