From 16711ec6b86bb7b636bfdb0d0b395ec8a20dd17e Mon Sep 17 00:00:00 2001 From: usamoi Date: Sat, 24 Jan 2026 17:34:20 +0800 Subject: [PATCH 1/4] links old version of tc{g,s}etattr for glibc on mips(64) and sparc(64) --- libc-test/build.rs | 4 ++++ src/unix/mod.rs | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/libc-test/build.rs b/libc-test/build.rs index 6050c4d8a4b23..670695ad73731 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -3691,6 +3691,7 @@ fn test_linux(target: &str) { let ppc64 = target.contains("powerpc64"); let ppc32 = ppc && !ppc64; let s390x = target.contains("s390x"); + let sparc = target.contains("sparc"); let sparc64 = target.contains("sparc64"); let x32 = target.contains("x32"); let x86_32 = target.contains("i686"); @@ -4812,6 +4813,9 @@ fn test_linux(target: &str) { ] .contains(&s) }); + if mips || sparc { + cfg.skip_fn_ptrcheck(|s| ["tcgetattr", "tcsetattr"].contains(&s)); + } } ctest::generate_test(&mut cfg, "../src/lib.rs", "ctest_output.rs").unwrap(); diff --git a/src/unix/mod.rs b/src/unix/mod.rs index 0df5799e5b5e7..97ef54b00556f 100644 --- a/src/unix/mod.rs +++ b/src/unix/mod.rs @@ -1986,7 +1986,31 @@ extern "C" { link_name = "cfsetospeed@GLIBC_2.16" )] pub fn cfsetospeed(termios: *mut crate::termios, speed: crate::speed_t) -> c_int; + #[cfg_attr( + all( + target_os = "linux", + target_env = "gnu", + any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc"), + ), + link_name = "tcgetattr@GLIBC_2.0" + )] + #[cfg_attr( + all(target_os = "linux", target_env = "gnu", target_arch = "sparc64"), + link_name = "tcgetattr@GLIBC_2.2" + )] pub fn tcgetattr(fd: c_int, termios: *mut crate::termios) -> c_int; + #[cfg_attr( + all( + target_os = "linux", + target_env = "gnu", + any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc"), + ), + link_name = "tcsetattr@GLIBC_2.0" + )] + #[cfg_attr( + all(target_os = "linux", target_env = "gnu", target_arch = "sparc64"), + link_name = "tcsetattr@GLIBC_2.2" + )] pub fn tcsetattr(fd: c_int, optional_actions: c_int, termios: *const crate::termios) -> c_int; pub fn tcflow(fd: c_int, action: c_int) -> c_int; pub fn tcflush(fd: c_int, action: c_int) -> c_int; From 59158372fb6b343670a7d84a03205f2d982e5706 Mon Sep 17 00:00:00 2001 From: usamoi Date: Sat, 24 Jan 2026 17:36:31 +0800 Subject: [PATCH 2/4] links old version for glibc on mips{32,64}r6 --- src/unix/mod.rs | 76 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 12 deletions(-) diff --git a/src/unix/mod.rs b/src/unix/mod.rs index 97ef54b00556f..cbe7b72b31758 100644 --- a/src/unix/mod.rs +++ b/src/unix/mod.rs @@ -1627,7 +1627,11 @@ extern "C" { link_name = "cfgetispeed@GLIBC_2.0" )] #[cfg_attr( - all(target_os = "linux", target_env = "gnu", target_arch = "mips"), + all( + target_os = "linux", + target_env = "gnu", + any(target_arch = "mips", target_arch = "mips32r6") + ), link_name = "cfgetispeed@GLIBC_2.0" )] #[cfg_attr( @@ -1655,7 +1659,11 @@ extern "C" { link_name = "cfgetispeed@GLIBC_2.36" )] #[cfg_attr( - all(target_os = "linux", target_env = "gnu", target_arch = "mips64"), + all( + target_os = "linux", + target_env = "gnu", + any(target_arch = "mips64", target_arch = "mips64r6") + ), link_name = "cfgetispeed@GLIBC_2.0" )] #[cfg_attr( @@ -1720,7 +1728,11 @@ extern "C" { link_name = "cfgetospeed@GLIBC_2.0" )] #[cfg_attr( - all(target_os = "linux", target_env = "gnu", target_arch = "mips"), + all( + target_os = "linux", + target_env = "gnu", + any(target_arch = "mips", target_arch = "mips32r6") + ), link_name = "cfgetospeed@GLIBC_2.0" )] #[cfg_attr( @@ -1748,7 +1760,11 @@ extern "C" { link_name = "cfgetospeed@GLIBC_2.36" )] #[cfg_attr( - all(target_os = "linux", target_env = "gnu", target_arch = "mips64"), + all( + target_os = "linux", + target_env = "gnu", + any(target_arch = "mips64", target_arch = "mips64r6") + ), link_name = "cfgetospeed@GLIBC_2.0" )] #[cfg_attr( @@ -1813,7 +1829,11 @@ extern "C" { link_name = "cfsetispeed@GLIBC_2.0" )] #[cfg_attr( - all(target_os = "linux", target_env = "gnu", target_arch = "mips"), + all( + target_os = "linux", + target_env = "gnu", + any(target_arch = "mips", target_arch = "mips32r6") + ), link_name = "cfsetispeed@GLIBC_2.0" )] #[cfg_attr( @@ -1841,7 +1861,11 @@ extern "C" { link_name = "cfsetispeed@GLIBC_2.36" )] #[cfg_attr( - all(target_os = "linux", target_env = "gnu", target_arch = "mips64"), + all( + target_os = "linux", + target_env = "gnu", + any(target_arch = "mips64", target_arch = "mips64r6") + ), link_name = "cfsetispeed@GLIBC_2.0" )] #[cfg_attr( @@ -1906,7 +1930,11 @@ extern "C" { link_name = "cfsetospeed@GLIBC_2.0" )] #[cfg_attr( - all(target_os = "linux", target_env = "gnu", target_arch = "mips"), + all( + target_os = "linux", + target_env = "gnu", + any(target_arch = "mips", target_arch = "mips32r6") + ), link_name = "cfsetospeed@GLIBC_2.0" )] #[cfg_attr( @@ -1934,7 +1962,11 @@ extern "C" { link_name = "cfsetospeed@GLIBC_2.36" )] #[cfg_attr( - all(target_os = "linux", target_env = "gnu", target_arch = "mips64"), + all( + target_os = "linux", + target_env = "gnu", + any(target_arch = "mips64", target_arch = "mips64r6") + ), link_name = "cfsetospeed@GLIBC_2.0" )] #[cfg_attr( @@ -1990,7 +2022,13 @@ extern "C" { all( target_os = "linux", target_env = "gnu", - any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc"), + any( + target_arch = "mips", + target_arch = "mips32r6", + target_arch = "mips64", + target_arch = "mips64r6", + target_arch = "sparc" + ), ), link_name = "tcgetattr@GLIBC_2.0" )] @@ -2003,7 +2041,13 @@ extern "C" { all( target_os = "linux", target_env = "gnu", - any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc"), + any( + target_arch = "mips", + target_arch = "mips32r6", + target_arch = "mips64", + target_arch = "mips64r6", + target_arch = "sparc" + ), ), link_name = "tcsetattr@GLIBC_2.0" )] @@ -2312,7 +2356,11 @@ cfg_if! { link_name = "cfsetspeed@GLIBC_2.0" )] #[cfg_attr( - all(target_os = "linux", target_env = "gnu", target_arch = "mips"), + all( + target_os = "linux", + target_env = "gnu", + any(target_arch = "mips", target_arch = "mips32r6") + ), link_name = "cfsetspeed@GLIBC_2.0" )] #[cfg_attr( @@ -2340,7 +2388,11 @@ cfg_if! { link_name = "cfsetspeed@GLIBC_2.36" )] #[cfg_attr( - all(target_os = "linux", target_env = "gnu", target_arch = "mips64"), + all( + target_os = "linux", + target_env = "gnu", + any(target_arch = "mips64", target_arch = "mips64r6") + ), link_name = "cfsetspeed@GLIBC_2.0" )] #[cfg_attr( From e097c421f7a8758ecd3117f6668eb32c76df98dd Mon Sep 17 00:00:00 2001 From: usamoi Date: Wed, 28 Jan 2026 18:48:18 +0800 Subject: [PATCH 3/4] fix libc-test ctest on mips64 and sparc64 --- libc-test/build.rs | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/libc-test/build.rs b/libc-test/build.rs index 670695ad73731..24d8912e2e265 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -4794,27 +4794,37 @@ fn test_linux(target: &str) { if gnu { // old constants, so tests fail if glibc is too new cfg.skip_const(|s| { + // grep -E -h '^B([0-9])*$' libc-test/semver/* [ - "B50", "B75", "B110", "B134", "B150", "B200", "B300", "B600", "B1200", "B1800", - "B2400", "B4800", "B9600", "B19200", "B38400", "EXTA", "EXTB", "B57600", "B115200", - "B230400", "B460800", "B500000", "B576000", "B921600", "B1000000", "B1152000", - "B1500000", "B2000000", "B2500000", "B3000000", "B3500000", "B4000000", + "EXTA", "EXTB", "B0", "B1000000", "B110", "B115200", "B1152000", "B1200", "B134", + "B14400", "B150", "B1500000", "B153600", "B1800", "B19200", "B200", "B2000000", + "B230400", "B2400", "B2500000", "B28800", "B300", "B3000000", "B307200", + "B3500000", "B38400", "B4000000", "B460800", "B4800", "B50", "B500000", "B57600", + "B576000", "B600", "B614400", "B7200", "B75", "B76800", "B921600", "B9600", ] .contains(&s.ident()) }); + if mips || sparc { + cfg.skip_const(|s| s.ident() == "NCCS"); + } // old symbols, so tests fail if glibc is too new - cfg.skip_fn_ptrcheck(|s| { - [ - "cfgetispeed", - "cfgetospeed", - "cfsetispeed", - "cfsetospeed", - "cfsetspeed", - ] - .contains(&s) + // note: `skip_fn_ptrcheck` overrides the previous function + cfg.skip_fn_ptrcheck(move |s| { + let mut result = false; + result = result || s == "cfgetispeed"; + result = result || s == "cfgetospeed"; + result = result || s == "cfsetispeed"; + result = result || s == "cfsetospeed"; + result = result || s == "cfsetspeed"; + if mips || sparc { + result = result || s == "tcgetattr"; + result = result || s == "tcsetattr"; + } + result }); + // old structs, so tests fail if glibc is too new if mips || sparc { - cfg.skip_fn_ptrcheck(|s| ["tcgetattr", "tcsetattr"].contains(&s)); + cfg.skip_struct(|s| s.ident() == "termios"); } } From d376398248e0dbb84c667a8427a4bba4547e7cb3 Mon Sep 17 00:00:00 2001 From: usamoi Date: Wed, 28 Jan 2026 21:05:47 +0800 Subject: [PATCH 4/4] checks termios size in the baud test --- libc-test/tests/linux_gnu_baud.rs | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/libc-test/tests/linux_gnu_baud.rs b/libc-test/tests/linux_gnu_baud.rs index f38ab6326eb65..db8f5f939342e 100644 --- a/libc-test/tests/linux_gnu_baud.rs +++ b/libc-test/tests/linux_gnu_baud.rs @@ -13,21 +13,24 @@ fn baud() { assert!(ret >= 0); let terminal_fd = unsafe { open(buffer.as_ptr(), O_RDWR | O_NOCTTY) }; assert!(terminal_fd >= 0); - let mut tio: termios = unsafe { std::mem::zeroed() }; - let ret = unsafe { tcgetattr(terminal_fd, &mut tio) }; + #[repr(C)] + struct Protector(termios, [u8; 512]); + let mut tio: Protector = unsafe { Protector(std::mem::zeroed(), [0xcc; _]) }; + let ret = unsafe { tcgetattr(terminal_fd, &raw mut tio.0) }; assert!(ret >= 0); - assert_eq!(unsafe { cfgetispeed(&tio) }, B38400); - assert_eq!(unsafe { cfgetospeed(&tio) }, B38400); - let ret = unsafe { cfsetspeed(&mut tio, B1000000) }; + assert_eq!(tio.1, [0xcc; _]); + assert_eq!(unsafe { cfgetispeed(&tio.0) }, B38400); + assert_eq!(unsafe { cfgetospeed(&tio.0) }, B38400); + let ret = unsafe { cfsetspeed(&mut tio.0, B1000000) }; assert!(ret >= 0); - assert_eq!(unsafe { cfgetispeed(&tio) }, B1000000); - assert_eq!(unsafe { cfgetospeed(&tio) }, B1000000); - let ret = unsafe { cfsetispeed(&mut tio, B9600) }; + assert_eq!(unsafe { cfgetispeed(&tio.0) }, B1000000); + assert_eq!(unsafe { cfgetospeed(&tio.0) }, B1000000); + let ret = unsafe { cfsetispeed(&mut tio.0, B9600) }; assert!(ret >= 0); - assert_eq!(unsafe { cfgetispeed(&tio) }, B9600); - assert!(matches!(unsafe { cfgetospeed(&tio) }, B9600 | B1000000)); - let ret = unsafe { cfsetospeed(&mut tio, B19200) }; + assert_eq!(unsafe { cfgetispeed(&tio.0) }, B9600); + assert!(matches!(unsafe { cfgetospeed(&tio.0) }, B9600 | B1000000)); + let ret = unsafe { cfsetospeed(&mut tio.0, B19200) }; assert!(ret >= 0); - assert!(matches!(unsafe { cfgetispeed(&tio) }, B9600 | B19200)); - assert_eq!(unsafe { cfgetospeed(&tio) }, B19200); + assert!(matches!(unsafe { cfgetispeed(&tio.0) }, B9600 | B19200)); + assert_eq!(unsafe { cfgetospeed(&tio.0) }, B19200); }