Skip to content

Commit 0b6c902

Browse files
fix(main/fish): do not patch rust-lang/libc cargo crate
- Fixes termux/termux-packages#24741 - Cherry-pick fish-shell/fish-shell@bbf678e to replace `libc-src-unix-linux_like-android-mod.rs.diff` (since `libandroid-spawn` does not currently work with `fish`) - `libc-src-unix-linux_like-android.diff` is **causing** termux/termux-packages#24741 because of the problems explained by **maurer** in rust-lang/libc#4216 (comment) - I have rewritten `libc-src-unix-linux_like-android.diff` in **my own alternative way of solving [the errors](termux/termux-packages#22609 (comment) - My personal belief is that these errors should be solved by **patching `fish`**, _not_ by patching the **`libc` cargo crate**. - The reason I believe that is because **`fish` is using the type `libc::ino_t` to represent a value for storing the `d_ino` member of a `dirent` struct, which **cannot work on 32-bit Android** because 32-bit Android's `d_ino` is **not** an `ino_t`. [It is a `uint64_t`](https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/include/dirent.h;l=64?q=d_ino&ss=android%2Fplatform%2Fsuperproject%2Fmain:bionic%2Flibc%2Finclude%2F&start=1). - Therefore, the logical conclusion is that any successful port of `fish` to 32-bit Android **must explicitly store the value of a `dirent` `d_ino` as a `u64` anywhere it appears in Rust code.** - The same concept applies to `st_mode` - `st_mode` of `stat` on 32-bit Android is **not** a `mode_t`. [It is an `unsigned int`](https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/include/sys/stat.h;l=87), and [on Android, `unsigned int` is a 32-bit integer](https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/include/stdint.h;l=42;drc=61197364367c9e404c7da6900658f1b16c42d0da;bpv=0;bpt=1?q=stdint.h&ss=android%2Fplatform%2Fsuperproject%2Fmain). Therefore, any successful port of `fish` to 32-bit Android must explicitly store the value of a `stat` `st_mode` as `u32`. - In C, `S_IFMT` is a pure typeless literal preprocessor definition, which is [`00170000` in Android](https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/include/uapi/linux/stat.h;l=9?q=S_IFMT), preprocessor definitions do not really exist in Rust so there is unfortunately no correct alternative to a hardcoded integer literal for this on 32-bit Android - I previously read rust-lang/libc#4216 in January 2025, however, I unfortunately did not have the experience necessary at the time to fully understand how to solve this specific problem, so at the time, I did not change the version written by thunder-coding because I did not know how to make a better way to bypass the errors - However, in April 2025, I [ported Steel Bank Common Lisp to 64-bit Android-x86](https://github.com/robertkirkman/termux-packages/blob/b54fa7f61e3c9acdfdc13b9680b9ff023d69323d/packages/sbcl/fix-stat-st_nlink-x86.patch). In the process of doing that, I became more experienced with Android's `stat.h` and `dirent.h` files, and I have been able to use that experience to successfully create what appears to be a correct solution to termux/termux-packages#24741 The original errors, repeated here for convenint reference by others: ``` error[E0308]: mismatched types --> src/wutil/dir_iter.rs:114:50 | 114 | self.typ.set(stat_mode_to_entry_type(s.st_mode)); | ----------------------- ^^^^^^^^^ expected `u16`, found `u32` | | | arguments to this function are incorrect | note: function defined here --> src/wutil/dir_iter.rs:151:4 | 151 | fn stat_mode_to_entry_type(m: libc::mode_t) -> Option<DirEntryType> { | ^^^^^^^^^^^^^^^^^^^^^^^ --------------- help: you can convert a `u32` to a `u16` and panic if the converted value doesn't fit | 114 | self.typ.set(stat_mode_to_entry_type(s.st_mode.try_into().unwrap())); | ++++++++++++++++++++ error[E0308]: mismatched types --> src/wutil/dir_iter.rs:292:32 | 292 | self.entry.inode = dent.d_ino; | ---------------- ^^^^^^^^^^ expected `u32`, found `u64` | | | expected due to the type of this binding ```
1 parent 323c076 commit 0b6c902

5 files changed

+192
-267
lines changed

packages/fish/build.sh

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ TERMUX_PKG_DESCRIPTION="The user-friendly command line shell"
33
TERMUX_PKG_LICENSE="GPL-2.0"
44
TERMUX_PKG_MAINTAINER="@termux"
55
TERMUX_PKG_VERSION="4.0.2"
6-
TERMUX_PKG_REVISION=1
6+
TERMUX_PKG_REVISION=2
77
TERMUX_PKG_SRCURL=https://github.com/fish-shell/fish-shell/releases/download/$TERMUX_PKG_VERSION/fish-${TERMUX_PKG_VERSION}.tar.xz
88
TERMUX_PKG_SHA256=6e1ecdb164285fc057b2f35acbdc20815c1623099e7bb47bbfc011120adf7e83
99
TERMUX_PKG_AUTO_UPDATE=true
1010
# fish calls 'tput' from ncurses-utils, at least when cancelling (Ctrl+C) a command line.
1111
# man is needed since fish calls apropos during command completion.
12-
TERMUX_PKG_DEPENDS="bc, libandroid-support, libandroid-spawn, libc++, ncurses, ncurses-utils, mandoc, pcre2"
12+
TERMUX_PKG_DEPENDS="bc, libandroid-support, libc++, ncurses, ncurses-utils, mandoc, pcre2"
1313
TERMUX_PKG_BUILD_IN_SRC=true
1414
TERMUX_PKG_EXTRA_CONFIGURE_ARGS="
1515
-DBUILD_DOCS=OFF
@@ -35,19 +35,6 @@ termux_step_pre_configure() {
3535
export RUSTFLAGS=$(env | grep CARGO_TARGET_${env_host}_RUSTFLAGS | cut -d'=' -f2-)
3636
RUSTFLAGS+=" -C link-arg=-landroid-spawn"
3737
RUSTFLAGS+=" -L${TERMUX_PKG_BUILDDIR} -C link-arg=-l:libctermid.a"
38-
39-
: "${CARGO_HOME:=${HOME}/.cargo}"
40-
export CARGO_HOME
41-
42-
rm -rf "$CARGO_HOME"/registry/src/*/libc-*
43-
cargo fetch --target "${CARGO_TARGET_NAME}"
44-
45-
local libc p
46-
for libc in "${CARGO_HOME}"/registry/src/*/libc-*; do
47-
for p in "${TERMUX_PKG_BUILDER_DIR}"/libc-*.diff; do
48-
[[ -f "${p}" ]] && patch -p1 -d "${libc}" -i "${p}" || termux_error_exit "fish: failed to apply patch '$p'"
49-
done
50-
done
5138
}
5239

5340
termux_step_post_make_install() {
@@ -60,7 +47,3 @@ termux_step_post_make_install() {
6047
status test-feature keyboard-protocols && set -U fish_features no-keyboard-protocols
6148
EOF
6249
}
63-
64-
termux_step_post_massage() {
65-
rm -rf "$CARGO_HOME"/registry/src/*/libc-*
66-
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
Cherry-pick of https://github.com/fish-shell/fish-shell/commit/bbf678e7185fedce955587afbb23d83d37a87344
2+
3+
From bbf678e7185fedce955587afbb23d83d37a87344 Mon Sep 17 00:00:00 2001
4+
From: =?UTF-8?q?=E7=8E=8B=E5=AE=87=E9=80=B8?= <Strawberry_Str@hotmail.com>
5+
Date: Sat, 8 Mar 2025 02:09:45 +0800
6+
Subject: [PATCH] Reduce warnings when posix_spawn disabled.
7+
8+
---
9+
src/exec.rs | 8 ++++++--
10+
src/fork_exec/mod.rs | 1 +
11+
2 files changed, 7 insertions(+), 2 deletions(-)
12+
13+
diff --git a/src/exec.rs b/src/exec.rs
14+
index 89b8b86f462b..ba961e456e5f 100644
15+
--- a/src/exec.rs
16+
+++ b/src/exec.rs
17+
@@ -12,6 +12,7 @@ use crate::common::{
18+
ScopeGuard,
19+
};
20+
use crate::env::{EnvMode, EnvStack, Environment, Statuses, READ_BYTE_LIMIT};
21+
+#[cfg(FISH_USE_POSIX_SPAWN)]
22+
use crate::env_dispatch::use_posix_spawn;
23+
use crate::fds::make_fd_blocking;
24+
use crate::fds::{make_autoclose_pipes, open_cloexec, PIPE_ERROR};
25+
@@ -34,10 +35,12 @@ use crate::null_terminated_array::{
26+
null_terminated_array_length, AsNullTerminatedArray, OwningNullTerminatedArray,
27+
};
28+
use crate::parser::{Block, BlockId, BlockType, EvalRes, Parser};
29+
+#[cfg(FISH_USE_POSIX_SPAWN)]
30+
+use crate::proc::Pid;
31+
use crate::proc::{
32+
hup_jobs, is_interactive_session, jobs_requiring_warning_on_exit, no_exec,
33+
- print_exit_warning_for_jobs, InternalProc, Job, JobGroupRef, Pid, ProcStatus, Process,
34+
- ProcessType, TtyTransfer,
35+
+ print_exit_warning_for_jobs, InternalProc, Job, JobGroupRef, ProcStatus, Process, ProcessType,
36+
+ TtyTransfer,
37+
};
38+
use crate::reader::{reader_run_count, restore_term_mode};
39+
use crate::redirection::{dup2_list_resolve_chain, Dup2List};
40+
@@ -447,6 +450,7 @@ fn launch_process_nofork(vars: &EnvStack, p: &Process) -> ! {
41+
// To avoid the race between the caller calling tcsetpgrp() and the client checking the
42+
// foreground process group, we don't use posix_spawn if we're going to foreground the process. (If
43+
// we use fork(), we can call tcsetpgrp after the fork, before the exec, and avoid the race).
44+
+#[cfg(FISH_USE_POSIX_SPAWN)]
45+
fn can_use_posix_spawn_for_job(job: &Job, dup2s: &Dup2List) -> bool {
46+
// Is it globally disabled?
47+
if !use_posix_spawn() {
48+
diff --git a/src/fork_exec/mod.rs b/src/fork_exec/mod.rs
49+
index 2c10fccd5202..c0d0de46e2b9 100644
50+
--- a/src/fork_exec/mod.rs
51+
+++ b/src/fork_exec/mod.rs
52+
@@ -4,6 +4,7 @@
53+
54+
pub mod flog_safe;
55+
pub mod postfork;
56+
+#[cfg(FISH_USE_POSIX_SPAWN)]
57+
pub mod spawn;
58+
use crate::proc::Job;
59+
use libc::{SIGINT, SIGQUIT};
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
This fixes https://github.com/termux/termux-packages/issues/24741
2+
3+
To maintain:
4+
keep the conditionally-compiled implementations of DirEntry and stat_mode_to_entry_type()
5+
synchronized with their upstream counterparts that are developed for non-32-bit-Android platforms.
6+
keep the S_IFIFO, etc. definitions synchronized with this file:
7+
https://github.com/rust-lang/libc/blob/c1d2b8e055e29b239a308f10b38a6b6138711612/src/unix/linux_like/mod.rs#L563
8+
9+
This patch was not created by an automatic tool - unfortunately, it was created by manually typing the
10+
syntax of the unified-diff format, in order to artifically extend the context of each hunk an
11+
abnormal number of lines after the changed lines (but not before the changed lines).
12+
The reason for this is so that if anything in the normal implementation of the blocks changes,
13+
this patch is explicitly forced to fail so that the maintainer is reminded to make an equivalent change
14+
in the implementation of the block for 32-bit Android. If another maintianer of this patch is not
15+
familiar with manually writing the unified-diff format, this documentation might be helpful to
16+
preserve this failsafe in future revisions of this patch:
17+
https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Unified.html
18+
19+
--- a/src/wildcard.rs
20+
+++ b/src/wildcard.rs
21+
@@ -885,6 +885,9 @@ mod expander {
22+
// Ensure we don't fall into a symlink loop.
23+
// Ideally we would compare both devices and inodes, but devices require a stat call, so we
24+
// use inodes exclusively.
25+
+ #[cfg(all(target_os = "android", target_pointer_width = "32"))]
26+
+ let mut visited_inodes: HashSet<u64> = HashSet::new();
27+
+ #[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
28+
let mut visited_inodes: HashSet<libc::ino_t> = HashSet::new();
29+
30+
loop {
31+
--- a/src/wutil/dir_iter.rs
32+
+++ b/src/wutil/dir_iter.rs
33+
@@ -26,26 +26,52 @@ pub enum DirEntryType {
34+
whiteout, // whiteout (from BSD)
35+
}
36+
37+
-/// An entry returned by DirIter.
38+
+/// An entry returned by DirIter on 32-bit Android.
39+
+#[cfg(all(target_os = "android", target_pointer_width = "32"))]
40+
+#[derive(Clone)]
41+
+pub struct DirEntry {
42+
+ /// File name of this entry.
43+
+ pub name: WString,
44+
+
45+
+ /// inode of this entry.
46+
+ pub inode: u64,
47+
+
48+
+ // Device, inode pair for this entry, or none if not yet computed.
49+
+ dev_inode: Cell<Option<DevInode>>,
50+
+
51+
+ // The type of the entry. This is initially none; it may be populated eagerly via readdir()
52+
+ // on some filesystems, or later via stat(). If stat() fails, the error is silently ignored
53+
+ // and the type is left as none(). Note this is an unavoidable race.
54+
+ typ: Cell<Option<DirEntryType>>,
55+
+
56+
+ // whether this could be a link, false if we know definitively it isn't.
57+
+ possible_link: Option<bool>,
58+
+
59+
+ // fd of the DIR*, used for fstatat().
60+
+ dirfd: Rc<DirFd>,
61+
+}
62+
+
63+
+/// An entry returned by DirIter on everything except 32-bit Android.
64+
+#[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
65+
#[derive(Clone)]
66+
pub struct DirEntry {
67+
/// File name of this entry.
68+
pub name: WString,
69+
70+
/// inode of this entry.
71+
pub inode: libc::ino_t,
72+
73+
// Device, inode pair for this entry, or none if not yet computed.
74+
dev_inode: Cell<Option<DevInode>>,
75+
76+
// The type of the entry. This is initially none; it may be populated eagerly via readdir()
77+
// on some filesystems, or later via stat(). If stat() fails, the error is silently ignored
78+
// and the type is left as none(). Note this is an unavoidable race.
79+
typ: Cell<Option<DirEntryType>>,
80+
81+
// whether this could be a link, false if we know definitively it isn't.
82+
possible_link: Option<bool>,
83+
84+
// fd of the DIR*, used for fstatat().
85+
dirfd: Rc<DirFd>,
86+
}
87+
@@ -148,18 +174,44 @@ fn dirent_type_to_entry_type(dt: u8) -> Option<DirEntryType> {
88+
}
89+
}
90+
91+
+#[cfg(all(target_os = "android", target_pointer_width = "32"))]
92+
+fn stat_mode_to_entry_type(m: u32) -> Option<DirEntryType> {
93+
+ const S_IFIFO_32_bit_android: u32 = 0o1_0000;
94+
+ const S_IFCHR_32_bit_android: u32 = 0o2_0000;
95+
+ const S_IFBLK_32_bit_android: u32 = 0o6_0000;
96+
+ const S_IFDIR_32_bit_android: u32 = 0o4_0000;
97+
+ const S_IFREG_32_bit_android: u32 = 0o10_0000;
98+
+ const S_IFLNK_32_bit_android: u32 = 0o12_0000;
99+
+ const S_IFSOCK_32_bit_android: u32 = 0o14_0000;
100+
+ const S_IFMT_32_bit_android: u32 = 0o17_0000;
101+
+ match m & S_IFMT_32_bit_android {
102+
+ S_IFIFO_32_bit_android => Some(DirEntryType::fifo),
103+
+ S_IFCHR_32_bit_android => Some(DirEntryType::chr),
104+
+ S_IFDIR_32_bit_android => Some(DirEntryType::dir),
105+
+ S_IFBLK_32_bit_android => Some(DirEntryType::blk),
106+
+ S_IFREG_32_bit_android => Some(DirEntryType::reg),
107+
+ S_IFLNK_32_bit_android => Some(DirEntryType::lnk),
108+
+ S_IFSOCK_32_bit_android => Some(DirEntryType::sock),
109+
+ _ => {
110+
+ // todo!("whiteout")
111+
+ None
112+
+ }
113+
+ }
114+
+}
115+
+
116+
+#[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
117+
fn stat_mode_to_entry_type(m: libc::mode_t) -> Option<DirEntryType> {
118+
match m & S_IFMT {
119+
S_IFIFO => Some(DirEntryType::fifo),
120+
S_IFCHR => Some(DirEntryType::chr),
121+
S_IFDIR => Some(DirEntryType::dir),
122+
S_IFBLK => Some(DirEntryType::blk),
123+
S_IFREG => Some(DirEntryType::reg),
124+
S_IFLNK => Some(DirEntryType::lnk),
125+
S_IFSOCK => Some(DirEntryType::sock),
126+
_ => {
127+
// todo!("whiteout")
128+
None
129+
}
130+
}
131+
}

packages/fish/libc-src-unix-linux_like-android-mod.rs.diff

Lines changed: 0 additions & 95 deletions
This file was deleted.

0 commit comments

Comments
 (0)