fix: Instead of copying the file pointed to by the symlink ...

... create a symlink to the original path under the pasted path

See #433
This commit is contained in:
eatradish 2023-12-06 19:16:11 +08:00 committed by sxyazi
parent 32aa1909cf
commit 7a3c70f144
No known key found for this signature in database

View file

@ -1,7 +1,14 @@
use std::{collections::VecDeque, path::{Path, PathBuf}}; use std::{
collections::VecDeque,
path::{Path, PathBuf},
};
use anyhow::Result; use anyhow::Result;
use tokio::{fs, io, select, sync::{mpsc, oneshot}, time}; use tokio::{
fs, io, select,
sync::{mpsc, oneshot},
time,
};
pub async fn calculate_size(path: &Path) -> u64 { pub async fn calculate_size(path: &Path) -> u64 {
let mut total = 0; let mut total = 0;
@ -38,15 +45,23 @@ pub async fn calculate_size(path: &Path) -> u64 {
pub fn copy_with_progress(from: &Path, to: &Path) -> mpsc::Receiver<Result<u64, io::Error>> { pub fn copy_with_progress(from: &Path, to: &Path) -> mpsc::Receiver<Result<u64, io::Error>> {
let (tx, rx) = mpsc::channel(1); let (tx, rx) = mpsc::channel(1);
let (tick_tx, mut tick_rx) = oneshot::channel(); let (tick_tx, mut tick_rx) = oneshot::channel();
let is_symlink = from.is_symlink();
tokio::spawn({ tokio::spawn({
let (from, to) = (from.to_path_buf(), to.to_path_buf()); let (from, to) = (from.to_path_buf(), to.to_path_buf());
async move { async move {
_ = match fs::copy(from, to).await { if is_symlink {
Ok(len) => tick_tx.send(Ok(len)), _ = match fs::symlink(from, to).await {
Err(e) => tick_tx.send(Err(e)), Ok(()) => tick_tx.send(Ok(1)),
}; Err(e) => tick_tx.send(Err(e)),
}
} else {
_ = match fs::copy(from, to).await {
Ok(len) => tick_tx.send(Ok(len)),
Err(e) => tick_tx.send(Err(e)),
};
}
} }
}); });
@ -79,7 +94,12 @@ pub fn copy_with_progress(from: &Path, to: &Path) -> mpsc::Receiver<Result<u64,
None => {} None => {}
} }
let len = fs::symlink_metadata(&to).await.map(|m| m.len()).unwrap_or(0); let len = if is_symlink {
1
} else {
fs::symlink_metadata(&to).await.map(|m| m.len()).unwrap_or(0)
};
if len > last { if len > last {
tx.send(Ok(len - last)).await.ok(); tx.send(Ok(len - last)).await.ok();
last = len; last = len;
@ -95,7 +115,10 @@ pub fn copy_with_progress(from: &Path, to: &Path) -> mpsc::Receiver<Result<u64,
#[cfg(unix)] #[cfg(unix)]
#[allow(clippy::collapsible_else_if)] #[allow(clippy::collapsible_else_if)]
pub fn permissions(mode: u32) -> String { pub fn permissions(mode: u32) -> String {
use libc::{mode_t, S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFSOCK, S_IRGRP, S_IROTH, S_IRUSR, S_ISGID, S_ISUID, S_ISVTX, S_IWGRP, S_IWOTH, S_IWUSR, S_IXGRP, S_IXOTH, S_IXUSR}; use libc::{
mode_t, S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFSOCK, S_IRGRP, S_IROTH,
S_IRUSR, S_ISGID, S_ISUID, S_ISVTX, S_IWGRP, S_IWOTH, S_IWUSR, S_IXGRP, S_IXOTH, S_IXUSR,
};
let mut s = String::with_capacity(10); let mut s = String::with_capacity(10);
let m = mode as mode_t; let m = mode as mode_t;
@ -115,27 +138,51 @@ pub fn permissions(mode: u32) -> String {
s.push(if m & S_IRUSR != 0 { 'r' } else { '-' }); s.push(if m & S_IRUSR != 0 { 'r' } else { '-' });
s.push(if m & S_IWUSR != 0 { 'w' } else { '-' }); s.push(if m & S_IWUSR != 0 { 'w' } else { '-' });
s.push(if m & S_IXUSR != 0 { s.push(if m & S_IXUSR != 0 {
if m & S_ISUID != 0 { 's' } else { 'x' } if m & S_ISUID != 0 {
's'
} else {
'x'
}
} else { } else {
if m & S_ISUID != 0 { 'S' } else { '-' } if m & S_ISUID != 0 {
'S'
} else {
'-'
}
}); });
// Group // Group
s.push(if m & S_IRGRP != 0 { 'r' } else { '-' }); s.push(if m & S_IRGRP != 0 { 'r' } else { '-' });
s.push(if m & S_IWGRP != 0 { 'w' } else { '-' }); s.push(if m & S_IWGRP != 0 { 'w' } else { '-' });
s.push(if m & S_IXGRP != 0 { s.push(if m & S_IXGRP != 0 {
if m & S_ISGID != 0 { 's' } else { 'x' } if m & S_ISGID != 0 {
's'
} else {
'x'
}
} else { } else {
if m & S_ISGID != 0 { 'S' } else { '-' } if m & S_ISGID != 0 {
'S'
} else {
'-'
}
}); });
// Other // Other
s.push(if m & S_IROTH != 0 { 'r' } else { '-' }); s.push(if m & S_IROTH != 0 { 'r' } else { '-' });
s.push(if m & S_IWOTH != 0 { 'w' } else { '-' }); s.push(if m & S_IWOTH != 0 { 'w' } else { '-' });
s.push(if m & S_IXOTH != 0 { s.push(if m & S_IXOTH != 0 {
if m & S_ISVTX != 0 { 't' } else { 'x' } if m & S_ISVTX != 0 {
't'
} else {
'x'
}
} else { } else {
if m & S_ISVTX != 0 { 'T' } else { '-' } if m & S_ISVTX != 0 {
'T'
} else {
'-'
}
}); });
s s