fix(main/yazi): force-enable trash-rs support on Android

- Force-enable `trash-rs` and force the 'd' key to work to move files to `/data/data/com.termux/files/home/.local/share/Trash/files`, i.e. `$HOME/.local/share/Trash/files`

- Since for some reason `libc::getmntent()` does not exist in Rust for Android, it is necessary to make a dirty implementation of a function within `trash-rs` that is otherwise unimplemented for Android by avoiding the use of `getmntent()`. This implementation is not a fully proper way to detect mount points on Android, but it is sufficient to allow sending files to Trash to work without failure. It assumes that `/data` is mounted (since without `/data`, Termux cannot be running anyway), which allows the Termux home folder Trash to work (`/data/data/com.termux/files/home/.local/share/Trash/files`), and also pretends that `/storage/emulated/0` is a mounted filesystem so that Trashing files from `/sdcard` or `/storage/emulated/0` sends them to the Android system Home folder Trash (since, unlike the case of the Termux home folder, `/storage/emulated` is the actual mountpoint, but that folder does not grant permission for users to write to even if the user has used `termux-setup-storage`, only `/storage/emulated/0` does)

- Has has been tested and confirmed to work good enough to suceessfully move files to trash in `yazi` on Samsung Galaxy A70 SM-A705FN with LineageOS 20 Android 13 SELinux Enabled
This commit is contained in:
termux-pacman-bot
2026-01-27 06:47:21 +00:00
parent c5da7e69fa
commit 0eb6e7632b
3 changed files with 103 additions and 2 deletions

View File

@@ -3,6 +3,7 @@ TERMUX_PKG_DESCRIPTION="Blazing fast terminal file manager written in Rust, base
TERMUX_PKG_LICENSE="MIT"
TERMUX_PKG_MAINTAINER="@termux"
TERMUX_PKG_VERSION="26.1.22"
TERMUX_PKG_REVISION=1
TERMUX_PKG_SRCURL=https://github.com/sxyazi/yazi/archive/refs/tags/v${TERMUX_PKG_VERSION}.tar.gz
TERMUX_PKG_SHA256=83b8a1bf166bfcb54b44b966fa3f34afa7c55584bf81d29275a1cdd99d1c9c4c
TERMUX_PKG_BUILD_DEPENDS='aosp-libs, imagemagick'
@@ -12,7 +13,29 @@ TERMUX_PKG_BUILD_IN_SRC=true
termux_step_pre_configure() {
termux_setup_rust
[[ "$TERMUX_ON_DEVICE_BUILD" == "false" ]] && termux_setup_proot
if [[ "$TERMUX_ON_DEVICE_BUILD" == "false" ]]; then
termux_setup_proot
fi
cargo vendor
find ./vendor \
-mindepth 1 -maxdepth 1 -type d \
! -wholename ./vendor/trash \
-exec rm -rf '{}' \;
find vendor/trash -type f -print0 | \
xargs -0 sed -i \
-e 's|"android"|"disabling_this_because_it_is_for_building_an_apk"|g' \
-e "s|/tmp|$TERMUX_PREFIX/tmp|g"
local patch="$TERMUX_PKG_BUILDER_DIR/trash-rs-implement-get_mount_points-android.diff"
local dir="vendor/trash"
echo "Applying patch: $patch"
patch -p1 -d "$dir" < "$patch"
echo "" >> Cargo.toml
echo '[patch.crates-io]' >> Cargo.toml
echo 'trash = { path = "./vendor/trash" }' >> Cargo.toml
}
termux_step_make() {
@@ -37,10 +60,14 @@ termux_step_make_install() {
# application icons
local res
local termux_proot_run=''
if [[ "$TERMUX_ON_DEVICE_BUILD" == "false" ]]; then
termux_proot_run=termux-proot-run
fi
echo -n "Generating icons:"
for res in 16 24 32 48 64 128 256; do
mkdir -p "${TERMUX_PREFIX}/share/icons/hicolor/${res}x${res}/apps"
termux-proot-run magick assets/logo.png \
$termux_proot_run magick assets/logo.png \
-resize "${res}x${res}" \
"${TERMUX_PREFIX}/share/icons/hicolor/${res}x${res}/apps/yazi.png"
[[ -e "${TERMUX_PREFIX}/share/icons/hicolor/${res}x${res}/apps/yazi.png" ]] && {

View File

@@ -0,0 +1,29 @@
--- a/yazi-fs/Cargo.toml
+++ b/yazi-fs/Cargo.toml
@@ -45,5 +45,5 @@ windows-sys = { version = "0.61.2", features = [ "Win32_Storage_FileSystem" ] }
core-foundation-sys = { workspace = true }
objc2 = { workspace = true }
-[target.'cfg(not(target_os = "android"))'.dependencies]
+[target.'cfg(not(target_os = "disabling_this_because_it_is_for_building_an_apk"))'.dependencies]
trash = "5.2.5"
--- a/yazi-fs/src/provider/local/local.rs
+++ b/yazi-fs/src/provider/local/local.rs
@@ -189,7 +189,7 @@ impl<'a> Provider for Local<'a> {
async fn trash(&self) -> io::Result<()> {
let path = self.path.to_owned();
tokio::task::spawn_blocking(move || {
- #[cfg(target_os = "android")]
+ #[cfg(target_os = "disabling_this_because_it_is_for_building_an_apk")]
{
Err(io::Error::new(io::ErrorKind::Unsupported, "Unsupported OS for trash operation"))
}
@@ -200,7 +200,7 @@ impl<'a> Provider for Local<'a> {
ctx.set_delete_method(DeleteMethod::NsFileManager);
ctx.delete(path).map_err(io::Error::other)
}
- #[cfg(all(not(target_os = "macos"), not(target_os = "android")))]
+ #[cfg(all(not(target_os = "macos"), not(target_os = "disabling_this_because_it_is_for_building_an_apk")))]
{
trash::delete(path).map_err(io::Error::other)
}

View File

@@ -0,0 +1,45 @@
This dirty implementation of get_mount_points() for trash-rs for Android
has been tested and confirmed to work good enough to suceessfully move files to trash
in reverse dependency Yazi on Samsung Galaxy A70 SM-A705FN with LineageOS 20 Android 13 SELinux Enabled
--- a/src/freedesktop.rs
+++ b/src/freedesktop.rs
@@ -784,6 +784,28 @@ fn get_mount_points() -> Result<Vec<MountPoint>, Error> {
Ok(result)
}
+#[cfg(target_os = "android")]
+fn get_mount_points() -> Result<Vec<MountPoint>, Error> {
+ // assume '/data' and '/strorage/emulated/0' are mounted
+ // for some reason, 'getmntent()' is not available in Rust on Android,
+ // despite being available in C on Android.
+ // https://github.com/rust-lang/libc/blob/0403150379d66216e90a0f8a804ae1ca33691067/src/unix/linux_like/android/mod.rs
+ let mut result = Vec::new();
+ let mount_point = MountPoint {
+ mnt_dir: "/data".into(),
+ _mnt_fsname: "/this/should/not/matter".to_string(),
+ _mnt_type: "ext4".to_string()
+ };
+ result.push(mount_point);
+ let mount_point = MountPoint {
+ mnt_dir: "/storage/emulated/0".into(),
+ _mnt_fsname: "/this/should/not/matter".to_string(),
+ _mnt_type: "fuse".to_string()
+ };
+ result.push(mount_point);
+ Ok(result)
+}
+
#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
fn get_mount_points() -> Result<Vec<MountPoint>, Error> {
use once_cell::sync::Lazy;
@@ -898,7 +914,8 @@ fn get_mount_points() -> Result<Vec<MountPoint>, Error> {
target_os = "dragonfly",
target_os = "freebsd",
target_os = "openbsd",
- target_os = "netbsd"
+ target_os = "netbsd",
+ target_os = "android"
)))]
fn get_mount_points() -> Result<Vec<MountPoint>, Error> {
// On platforms that don't have support yet, return an error