Skip to content

Commit 08a5528

Browse files
overmindercarllerche
authored andcommitted
Make it compatible for Android.
* Fixed an unused_import error in `termios.rs` for Android. * Fixed undefined references to `preadv` and `pwritev` for Android - At least they don't exist from API level 3 to 21. * Fixed the uid > 0 and gid > 0 checks in `stat`'s tests - Running the tests by root is possible, especially when running on a rooted Android device. Those changes made rust-nix buildable (again) on Android. All the tests passed as well.
1 parent 5801318 commit 08a5528

File tree

4 files changed

+45
-30
lines changed

4 files changed

+45
-30
lines changed

src/sys/termios.rs

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,35 @@ pub use self::ffi::consts::FlushArg::*;
1010
pub use self::ffi::consts::FlowArg::*;
1111

1212
mod ffi {
13-
use libc::c_int;
14-
1513
pub use self::consts::*;
1614

17-
// `Termios` contains bitflags which are not considered
18-
// `foreign-function-safe` by the compiler.
19-
#[allow(improper_ctypes)]
2015
#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "openbsd", target_os = "linux"))]
21-
extern {
22-
pub fn cfgetispeed(termios: *const Termios) -> speed_t;
23-
pub fn cfgetospeed(termios: *const Termios) -> speed_t;
24-
pub fn cfsetispeed(termios: *mut Termios, speed: speed_t) -> c_int;
25-
pub fn cfsetospeed(termios: *mut Termios, speed: speed_t) -> c_int;
26-
pub fn tcgetattr(fd: c_int, termios: *mut Termios) -> c_int;
27-
pub fn tcsetattr(fd: c_int,
28-
optional_actions: c_int,
29-
termios: *const Termios) -> c_int;
30-
pub fn tcdrain(fd: c_int) -> c_int;
31-
pub fn tcflow(fd: c_int, action: c_int) -> c_int;
32-
pub fn tcflush(fd: c_int, action: c_int) -> c_int;
33-
pub fn tcsendbreak(fd: c_int, duration: c_int) -> c_int;
16+
mod non_android {
17+
use super::consts::*;
18+
use libc::c_int;
19+
20+
// `Termios` contains bitflags which are not considered
21+
// `foreign-function-safe` by the compiler.
22+
#[allow(improper_ctypes)]
23+
extern {
24+
pub fn cfgetispeed(termios: *const Termios) -> speed_t;
25+
pub fn cfgetospeed(termios: *const Termios) -> speed_t;
26+
pub fn cfsetispeed(termios: *mut Termios, speed: speed_t) -> c_int;
27+
pub fn cfsetospeed(termios: *mut Termios, speed: speed_t) -> c_int;
28+
pub fn tcgetattr(fd: c_int, termios: *mut Termios) -> c_int;
29+
pub fn tcsetattr(fd: c_int,
30+
optional_actions: c_int,
31+
termios: *const Termios) -> c_int;
32+
pub fn tcdrain(fd: c_int) -> c_int;
33+
pub fn tcflow(fd: c_int, action: c_int) -> c_int;
34+
pub fn tcflush(fd: c_int, action: c_int) -> c_int;
35+
pub fn tcsendbreak(fd: c_int, duration: c_int) -> c_int;
36+
}
3437
}
3538

39+
#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "openbsd", target_os = "linux"))]
40+
pub use self::non_android::*;
41+
3642
// On Android before 5.0, Bionic directly inline these to ioctl() calls.
3743
#[inline]
3844
#[cfg(all(target_os = "android", not(target_arch = "mips")))]

src/sys/uio.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ mod ffi {
2323

2424
// vectorized write at a specified offset
2525
// doc: http://man7.org/linux/man-pages/man2/pwritev.2.html
26-
#[cfg(any(target_os = "linux", target_os = "android"))]
26+
#[cfg(target_os = "linux")]
2727
pub fn pwritev(fd: RawFd, iov: *const IoVec<&[u8]>, iovcnt: c_int,
2828
offset: off_t) -> ssize_t;
2929

3030
// vectorized read at a specified offset
3131
// doc: http://man7.org/linux/man-pages/man2/preadv.2.html
32-
#[cfg(any(target_os = "linux", target_os = "android"))]
32+
#[cfg(target_os = "linux")]
3333
pub fn preadv(fd: RawFd, iov: *const IoVec<&mut [u8]>, iovcnt: c_int,
3434
offset: off_t) -> ssize_t;
3535

@@ -64,7 +64,7 @@ pub fn readv(fd: RawFd, iov: &mut [IoVec<&mut [u8]>]) -> Result<usize> {
6464
return Ok(res as usize)
6565
}
6666

67-
#[cfg(any(target_os = "linux", target_os = "android"))]
67+
#[cfg(target_os = "linux")]
6868
pub fn pwritev(fd: RawFd, iov: &[IoVec<&[u8]>],
6969
offset: off_t) -> Result<usize> {
7070
let res = unsafe {
@@ -77,7 +77,7 @@ pub fn pwritev(fd: RawFd, iov: &[IoVec<&[u8]>],
7777
}
7878
}
7979

80-
#[cfg(any(target_os = "linux", target_os = "android"))]
80+
#[cfg(target_os = "linux")]
8181
pub fn preadv(fd: RawFd, iov: &mut [IoVec<&mut [u8]>],
8282
offset: off_t) -> Result<usize> {
8383
let res = unsafe {

test/sys/test_uio.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ fn test_pread() {
130130
}
131131

132132
#[test]
133-
#[cfg(any(target_os = "linux", target_os = "android"))]
133+
#[cfg(target_os = "linux")]
134134
fn test_pwritev() {
135135
use std::io::Read;
136136

@@ -160,7 +160,7 @@ fn test_pwritev() {
160160
}
161161

162162
#[test]
163-
#[cfg(any(target_os = "linux", target_os = "android"))]
163+
#[cfg(target_os = "linux")]
164164
fn test_preadv() {
165165
use std::io::Write;
166166

test/test_stat.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ fn assert_stat_results(stat_result: Result<FileStat>) {
1818
assert!(stats.st_ino > 0); // inode is positive integer, exact number machine dependent
1919
assert!(stats.st_mode > 0); // must be positive integer
2020
assert!(stats.st_nlink == 1); // there links created, must be 1
21-
assert!(stats.st_uid > 0); // must be positive integer
22-
assert!(stats.st_gid > 0); // must be positive integer
21+
// uid could be 0 for the `root` user. This quite possible when
22+
// the tests are being run on a rooted Android device.
23+
assert!(stats.st_uid >= 0); // must be positive integer
24+
assert!(stats.st_gid >= 0); // must be positive integer
2325
assert!(stats.st_rdev == 0); // no special device
2426
assert!(stats.st_size == 0); // size is 0 because we did not write anything to the file
2527
assert!(stats.st_blksize > 0); // must be positive integer, exact number machine dependent
@@ -35,17 +37,24 @@ fn assert_lstat_results(stat_result: Result<FileStat>) {
3537
assert!(stats.st_dev > 0); // must be positive integer, exact number machine dependent
3638
assert!(stats.st_ino > 0); // inode is positive integer, exact number machine dependent
3739
assert!(stats.st_mode > 0); // must be positive integer
38-
assert!(stats.st_mode & posix88::S_IFMT
39-
== posix88::S_IFLNK); // should be a link
40+
41+
// st_mode is c_uint (u32 on Android) while S_IFMT is mode_t
42+
// (u16 on Android), and that will be a compile error.
43+
// On other platforms they are the same (either both are u16 or u32).
44+
assert!((stats.st_mode as usize) & (posix88::S_IFMT as usize)
45+
== posix88::S_IFLNK as usize); // should be a link
4046
assert!(stats.st_nlink == 1); // there links created, must be 1
41-
assert!(stats.st_uid > 0); // must be positive integer
42-
assert!(stats.st_gid > 0); // must be positive integer
47+
// uid could be 0 for the `root` user. This quite possible when
48+
// the tests are being run on a rooted Android device.
49+
assert!(stats.st_uid >= 0); // must be positive integer
50+
assert!(stats.st_gid >= 0); // must be positive integer
4351
assert!(stats.st_rdev == 0); // no special device
4452
assert!(stats.st_size > 0); // size is > 0 because it points to another file
4553
assert!(stats.st_blksize > 0); // must be positive integer, exact number machine dependent
4654

4755
// st_blocks depends on whether the machine's file system uses fast
4856
// or slow symlinks, so just make sure it's not negative
57+
// (Android's st_blocks is ulonglong which is always non-negative.)
4958
assert!(stats.st_blocks >= 0);
5059
}
5160
Err(_) => panic!("stat call failed") // if stats system call fails, something is seriously wrong on that machine

0 commit comments

Comments
 (0)