Skip to content

Commit

Permalink
List valid trash bin paths
Browse files Browse the repository at this point in the history
This is a small refactor to support listing Freedesktop compliant trash
bins. Enumerating trash bins, which may reside across mount points or be
invalid in some way, is useful for end users who need the paths
themselves rather than the items in the trash.
  • Loading branch information
joshuamegnauth54 committed Mar 19, 2024
1 parent b6acac9 commit 3eba5c3
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 32 deletions.
91 changes: 59 additions & 32 deletions src/freedesktop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,39 +56,8 @@ impl TrashContext {
}

pub fn list() -> Result<Vec<TrashItem>, Error> {
let mut trash_folders = HashSet::new();
// Get home trash folder and add it to the set of trash folders.
// It may not exist and that's completely fine as long as there are other trash folders.
let home_error;
match home_trash() {
Ok(home_trash) => {
if !home_trash.is_dir() {
home_error = Some(Error::Unknown {
description:
"The 'home trash' either does not exist or is not a directory (or a link pointing to a dir)"
.into(),
});
} else {
trash_folders.insert(home_trash);
home_error = None;
}
}
Err(e) => {
home_error = Some(e);
}
}
let EvaluatedTrashFolders { trash_folders, home_error, sorted_mount_points } = eval_trash_folders()?;

// Get all mount-points and attempt to find a trash folder in each adding them to the SET of
// trash folders when found one.
let uid = unsafe { libc::getuid() };
let sorted_mount_points = get_sorted_mount_points()?;
for mount in &sorted_mount_points {
execute_on_mounted_trash_folders(uid, &mount.mnt_dir, false, false, |trash_path| {
trash_folders.insert(trash_path);
Ok(())
})
.map_err(|(p, e)| fs_error(p, e))?;
}
if trash_folders.is_empty() {
warn!("No trash folder was found. The error when looking for the 'home trash' was: {:?}", home_error);
return Ok(vec![]);
Expand Down Expand Up @@ -218,6 +187,64 @@ pub fn list() -> Result<Vec<TrashItem>, Error> {
Ok(result)
}

pub fn trash_folders() -> Result<HashSet<PathBuf>, Error> {
let EvaluatedTrashFolders { trash_folders, home_error, .. } = eval_trash_folders()?;

if trash_folders.is_empty() {
return match home_error {
Some(e) => Err(e),
None => Err(Error::Unknown {
description: "Could not find a valid 'home trash' nor valid trashes on other mount points".into(),
}),
};
}

Ok(trash_folders)
}

struct EvaluatedTrashFolders {
trash_folders: HashSet<PathBuf>,
home_error: Option<Error>,
sorted_mount_points: Vec<MountPoint>,
}

fn eval_trash_folders() -> Result<EvaluatedTrashFolders, Error> {
let mut trash_folders = HashSet::new();
// Get home trash folder and add it to the set of trash folders.
// It may not exist and that's completely fine as long as there are other trash folders.
let home_error;
match home_trash() {
Ok(home_trash) => {
if !home_trash.is_dir() {
home_error = Some(Error::Unknown {
description:
"The 'home trash' either does not exist or is not a directory (or a link pointing to a dir)"
.into(),
});
} else {
trash_folders.insert(home_trash);
home_error = None;
}
}
Err(e) => {
home_error = Some(e);
}
}

// Get all mount-points and attempt to find a trash folder in each adding them to the SET of
// trash folders when found one.
let uid = unsafe { libc::getuid() };
let sorted_mount_points = get_sorted_mount_points()?;
for mount in &sorted_mount_points {
execute_on_mounted_trash_folders(uid, &mount.mnt_dir, false, false, |trash_path| {
trash_folders.insert(trash_path);
Ok(())
})
.map_err(|(p, e)| fs_error(p, e))?;
}

Ok(EvaluatedTrashFolders { trash_folders, home_error, sorted_mount_points })
}
pub fn metadata(item: &TrashItem) -> Result<TrashItemMetadata, Error> {
// When purging an item the "in-trash" filename must be parsed from the trashinfo filename
// which is the filename in the `id` field.
Expand Down
18 changes: 18 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ pub mod os_limited {
borrow::Borrow,
collections::HashSet,
hash::{Hash, Hasher},
path::PathBuf,
};

use super::{platform, Error, TrashItem, TrashItemMetadata};
Expand All @@ -374,6 +375,23 @@ pub mod os_limited {
platform::list()
}

/// Returns all valid trash bins.
///
/// Valid trash folders include the user's personal "home trash" as well as designated trash
/// bins across mount points. Some, or all of these, may not exist or be invalid in some way.
///
/// # Example
///
/// ```
/// use trash::os_limited::trash_folders;
/// let trash_bins = trash_folders()?;
/// println!("{trash_bins:#?}");
/// # Ok::<(), trash::Error>(())
/// ```
pub fn trash_folders() -> Result<HashSet<PathBuf>, Error> {
platform::trash_folders()
}

/// Returns the [`TrashItemMetadata`] for a [`TrashItem`]
///
/// # Example
Expand Down

0 comments on commit 3eba5c3

Please sign in to comment.