Skip to content

Commit

Permalink
linux: Prevent target file from being trashed when trashing symlink (z…
Browse files Browse the repository at this point in the history
…ed-industries#22704)

Closes zed-industries#22399

Currently, the target file is being trashed when trashing a symlink, and
the symlink remains intact. Symlinks are not handled separately yet, so
when `open` is used on a symlink, it gets resolved to the target file.

To fix this, we can get the file descriptor of the symlink by passing
`libc::O_PATH | libc::O_NOFOLLOW` flags to `open`, and then pass this
file descriptor to the existing `trash::trash_file` from `ashpd`.
However, this would result in an error because `ashpd` currently does
not support trashing symlink files. I have created an issue for it here:
[https://github.com/bilelmoussaoui/ashpd/issues/255](https://github.com/bilelmoussaoui/ashpd/issues/255).

For the time being, this PR partially fixes the issue by removing the
symlink without trashing so that the target file won't be affected. Once
the upstream bug is fixed, we can switch this remove action back to
trashing.

Release Notes:

- Fixed target file from being trashed when trashing symlink on Linux.
  • Loading branch information
0xtimsb authored Jan 7, 2025
1 parent d2d1779 commit 7d0c571
Showing 1 changed file with 8 additions and 3 deletions.
11 changes: 8 additions & 3 deletions crates/fs/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ use git::GitHostingProviderRegistry;
use ashpd::desktop::trash;
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
use smol::process::Command;
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
use std::fs::File;

#[cfg(unix)]
use std::os::fd::AsFd;
#[cfg(unix)]
Expand Down Expand Up @@ -445,7 +444,13 @@ impl Fs for RealFs {

#[cfg(any(target_os = "linux", target_os = "freebsd"))]
async fn trash_file(&self, path: &Path, _options: RemoveOptions) -> Result<()> {
let file = File::open(path)?;
if let Ok(Some(metadata)) = self.metadata(path).await {
if metadata.is_symlink {
// TODO: trash_file does not support trashing symlinks yet - https://github.com/bilelmoussaoui/ashpd/issues/255
return self.remove_file(path, RemoveOptions::default()).await;
}
}
let file = smol::fs::File::open(path).await?;
match trash::trash_file(&file.as_fd()).await {
Ok(_) => Ok(()),
Err(err) => Err(anyhow::Error::new(err)),
Expand Down

0 comments on commit 7d0c571

Please sign in to comment.