diff --git a/Cargo.lock b/Cargo.lock index d832e547c..ff0319353 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -791,9 +791,9 @@ checksum = "31a7a908b8f32538a2143e59a6e4e2508988832d5d4d6f7c156b3cbc762643a5" [[package]] name = "filetime" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" +checksum = "c0408e2626025178a6a7f7ffc05a25bc47103229f19c113755de7bf63816290c" dependencies = [ "cfg-if 1.0.0", "libc", diff --git a/Cargo.toml b/Cargo.toml index 41532cd45..17f686008 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ # coreutils (uutils) # * see the repository LICENSE, README, and CONTRIBUTING files for more information -# spell-checker:ignore (libs) libselinux +# spell-checker:ignore (libs) libselinux gethostid [package] name = "coreutils" @@ -120,6 +120,7 @@ feat_Tier1 = [ # "feat_os_macos" == set of utilities which can be built/run on the MacOS platform feat_os_macos = [ "feat_os_unix", ## == a modern/usual *nix platform + "feat_require_hostid", ] # "feat_os_unix" == set of utilities which can be built/run on modern/usual *nix platforms feat_os_unix = [ @@ -140,12 +141,19 @@ feat_os_unix_gnueabihf = [ # "feat_require_unix", "feat_require_unix_utmpx", + "feat_require_hostid", ] # "feat_os_unix_musl" == set of utilities which can be built/run on targets binding to the "musl" library (ref: ) feat_os_unix_musl = [ "feat_Tier1", # "feat_require_unix", + "feat_require_hostid", +] +feat_os_unix_android = [ + "feat_Tier1", + # + "feat_require_unix", ] # "feat_selinux" == set of utilities providing support for SELinux Security Context if enabled with `--features feat_selinux`. # NOTE: @@ -172,7 +180,6 @@ feat_require_unix = [ "chown", "chroot", "groups", - "hostid", "id", "install", "kill", @@ -195,6 +202,10 @@ feat_require_unix_utmpx = [ "users", "who", ] +# "feat_require_hostid" == set of utilities requiring gethostid in libc (only some unixes provide) +feat_require_hostid = [ + "hostid", +] # "feat_require_selinux" == set of utilities depending on SELinux. feat_require_selinux = [ "chcon", @@ -386,7 +397,7 @@ walkdir = "2.2" atty = "0.2" hex-literal = "0.3.1" -[target.'cfg(target_os = "linux")'.dev-dependencies] +[target.'cfg(any(target_os = "linux", target_os = "android"))'.dev-dependencies] rlimit = "0.8.3" [target.'cfg(unix)'.dev-dependencies] diff --git a/src/uu/chroot/src/chroot.rs b/src/uu/chroot/src/chroot.rs index 713336104..e54cc3f8f 100644 --- a/src/uu/chroot/src/chroot.rs +++ b/src/uu/chroot/src/chroot.rs @@ -208,7 +208,7 @@ fn set_groups(groups: &[libc::gid_t]) -> libc::c_int { unsafe { setgroups(groups.len() as libc::c_int, groups.as_ptr()) } } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] fn set_groups(groups: &[libc::gid_t]) -> libc::c_int { unsafe { setgroups(groups.len() as libc::size_t, groups.as_ptr()) } } diff --git a/src/uu/cp/Cargo.toml b/src/uu/cp/Cargo.toml index b60006df1..1aab9c37b 100644 --- a/src/uu/cp/Cargo.toml +++ b/src/uu/cp/Cargo.toml @@ -27,7 +27,7 @@ selinux = { version="0.2", optional=true } uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["entries", "fs", "perms", "mode"] } walkdir = "2.2" -[target.'cfg(target_os = "linux")'.dependencies] +[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies] ioctl-sys = "0.8" [target.'cfg(target_os = "windows")'.dependencies] diff --git a/src/uu/cp/src/cp.rs b/src/uu/cp/src/cp.rs index d69bb705b..df9cb0293 100644 --- a/src/uu/cp/src/cp.rs +++ b/src/uu/cp/src/cp.rs @@ -10,7 +10,7 @@ // spell-checker:ignore (ToDO) ficlone linkgs lstat nlink nlinks pathbuf reflink strs xattrs symlinked -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] #[macro_use] extern crate ioctl_sys; #[macro_use] @@ -49,7 +49,7 @@ use std::mem; use std::os::unix::ffi::OsStrExt; #[cfg(unix)] use std::os::unix::fs::{FileTypeExt, PermissionsExt}; -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] use std::os::unix::io::AsRawFd; #[cfg(windows)] use std::os::windows::ffi::OsStrExt; @@ -61,7 +61,7 @@ use uucore::error::{set_exit_code, ExitCode, UError, UResult}; use uucore::fs::{canonicalize, MissingHandling, ResolveMode}; use walkdir::WalkDir; -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] ioctl!(write ficlone with 0x94, 9; std::os::raw::c_int); quick_error! { @@ -686,11 +686,15 @@ impl Options { } } } else { - #[cfg(any(target_os = "linux", target_os = "macos"))] + #[cfg(any(target_os = "linux", target_os = "android", target_os = "macos"))] { ReflinkMode::Auto } - #[cfg(not(any(target_os = "linux", target_os = "macos")))] + #[cfg(not(any( + target_os = "linux", + target_os = "android", + target_os = "macos" + )))] { ReflinkMode::Never } @@ -1467,14 +1471,14 @@ fn copy_helper( } else if source_is_symlink { copy_link(source, dest, symlinked_files)?; } else if options.reflink_mode != ReflinkMode::Never { - #[cfg(not(any(target_os = "linux", target_os = "macos")))] + #[cfg(not(any(target_os = "linux", target_os = "android", target_os = "macos")))] return Err("--reflink is only supported on linux and macOS" .to_string() .into()); #[cfg(target_os = "macos")] copy_on_write_macos(source, dest, options.reflink_mode, context)?; - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] copy_on_write_linux(source, dest, options.reflink_mode, context)?; } else { fs::copy(source, dest).context(context)?; @@ -1528,7 +1532,7 @@ fn copy_link( } /// Copies `source` to `dest` using copy-on-write if possible. -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] fn copy_on_write_linux( source: &Path, dest: &Path, diff --git a/src/uu/dd/Cargo.toml b/src/uu/dd/Cargo.toml index d311c9733..c805685ad 100644 --- a/src/uu/dd/Cargo.toml +++ b/src/uu/dd/Cargo.toml @@ -21,7 +21,7 @@ gcd = "2.0" libc = "0.2" uucore = { version=">=0.0.8", package="uucore", path="../../uucore" } -[target.'cfg(target_os = "linux")'.dependencies] +[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies] signal-hook = "0.3.9" [[bin]] diff --git a/src/uu/dd/src/dd.rs b/src/uu/dd/src/dd.rs index 3b9bb02d8..3f1a54b1c 100644 --- a/src/uu/dd/src/dd.rs +++ b/src/uu/dd/src/dd.rs @@ -26,7 +26,7 @@ use std::cmp; use std::env; use std::fs::{File, OpenOptions}; use std::io::{self, Read, Seek, Write}; -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] use std::os::unix::fs::OpenOptionsExt; use std::path::Path; use std::sync::mpsc; @@ -88,7 +88,7 @@ impl Input { } } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] fn make_linux_iflags(iflags: &IFlags) -> Option { let mut flag = 0; @@ -140,7 +140,7 @@ impl Input { let mut opts = OpenOptions::new(); opts.read(true); - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] if let Some(libc_flags) = make_linux_iflags(&iflags) { opts.custom_flags(libc_flags); } @@ -455,7 +455,7 @@ where } } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] fn make_linux_oflags(oflags: &OFlags) -> Option { let mut flag = 0; @@ -504,7 +504,7 @@ impl OutputTrait for Output { .create_new(cflags.excl) .append(oflags.append); - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] if let Some(libc_flags) = make_linux_oflags(oflags) { opts.custom_flags(libc_flags); } diff --git a/src/uu/dd/src/parseargs.rs b/src/uu/dd/src/parseargs.rs index 4bc65bc1c..0a2fae99a 100644 --- a/src/uu/dd/src/parseargs.rs +++ b/src/uu/dd/src/parseargs.rs @@ -235,7 +235,7 @@ impl std::str::FromStr for Flag { "direct" => // Ok(Self::Direct), { - if cfg!(target_os = "linux") { + if cfg!(any(target_os = "linux", target_os = "android")) { Ok(Self::Direct) } else { Err(ParseError::Unimplemented(s.to_string())) @@ -244,7 +244,7 @@ impl std::str::FromStr for Flag { "directory" => // Ok(Self::Directory), { - if cfg!(target_os = "linux") { + if cfg!(any(target_os = "linux", target_os = "android")) { Ok(Self::Directory) } else { Err(ParseError::Unimplemented(s.to_string())) @@ -253,7 +253,7 @@ impl std::str::FromStr for Flag { "dsync" => // Ok(Self::Dsync), { - if cfg!(target_os = "linux") { + if cfg!(any(target_os = "linux", target_os = "android")) { Ok(Self::Dsync) } else { Err(ParseError::Unimplemented(s.to_string())) @@ -262,7 +262,7 @@ impl std::str::FromStr for Flag { "sync" => // Ok(Self::Sync), { - if cfg!(target_os = "linux") { + if cfg!(any(target_os = "linux", target_os = "android")) { Ok(Self::Sync) } else { Err(ParseError::Unimplemented(s.to_string())) @@ -276,7 +276,7 @@ impl std::str::FromStr for Flag { "nonblock" => // Ok(Self::NonBlock), { - if cfg!(target_os = "linux") { + if cfg!(any(target_os = "linux", target_os = "android")) { Ok(Self::NonBlock) } else { Err(ParseError::Unimplemented(s.to_string())) @@ -285,7 +285,7 @@ impl std::str::FromStr for Flag { "noatime" => // Ok(Self::NoATime), { - if cfg!(target_os = "linux") { + if cfg!(any(target_os = "linux", target_os = "android")) { Ok(Self::NoATime) } else { Err(ParseError::Unimplemented(s.to_string())) @@ -294,7 +294,7 @@ impl std::str::FromStr for Flag { "noctty" => // Ok(Self::NoCtty), { - if cfg!(target_os = "linux") { + if cfg!(any(target_os = "linux", target_os = "android")) { Ok(Self::NoCtty) } else { Err(ParseError::Unimplemented(s.to_string())) @@ -303,7 +303,7 @@ impl std::str::FromStr for Flag { "nofollow" => // Ok(Self::NoFollow), { - if cfg!(target_os = "linux") { + if cfg!(any(target_os = "linux", target_os = "android")) { Ok(Self::NoFollow) } else { Err(ParseError::Unimplemented(s.to_string())) diff --git a/src/uu/dd/src/parseargs/unit_tests.rs b/src/uu/dd/src/parseargs/unit_tests.rs index 95e783c58..9d8349873 100644 --- a/src/uu/dd/src/parseargs/unit_tests.rs +++ b/src/uu/dd/src/parseargs/unit_tests.rs @@ -4,7 +4,7 @@ use super::*; use crate::StatusLevel; -#[cfg(not(target_os = "linux"))] +#[cfg(not(any(target_os = "linux", target_os = "android")))] #[test] fn unimplemented_flags_should_error_non_linux() { let mut succeeded = Vec::new(); @@ -617,7 +617,7 @@ fn parse_oflag_tokens() { } } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] #[test] fn parse_iflag_tokens_linux() { let exp = vec![ @@ -645,7 +645,7 @@ fn parse_iflag_tokens_linux() { } } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] #[test] fn parse_oflag_tokens_linux() { let exp = vec![ diff --git a/src/uu/id/src/id.rs b/src/uu/id/src/id.rs index 714ade035..cc23ce19f 100644 --- a/src/uu/id/src/id.rs +++ b/src/uu/id/src/id.rs @@ -201,7 +201,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { if state.cflag { if state.selinux_supported { // print SElinux context and exit - #[cfg(all(target_os = "linux", feature = "selinux"))] + #[cfg(all(any(target_os = "linux", target_os = "android"), feature = "selinux"))] if let Ok(context) = selinux::SecurityContext::current(false) { let bytes = context.as_bytes(); print!("{}{}", String::from_utf8_lossy(bytes), line_ending); @@ -520,7 +520,7 @@ fn pline(possible_uid: Option) { ); } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] fn pline(possible_uid: Option) { let uid = possible_uid.unwrap_or_else(getuid); let pw = Passwd::locate(uid).unwrap(); @@ -537,10 +537,10 @@ fn pline(possible_uid: Option) { ); } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] fn auditid() {} -#[cfg(not(target_os = "linux"))] +#[cfg(not(any(target_os = "linux", target_os = "android")))] fn auditid() { #[allow(deprecated)] let mut auditinfo: audit::c_auditinfo_addr_t = unsafe { std::mem::uninitialized() }; @@ -620,7 +620,7 @@ fn id_print(state: &mut State, groups: &[u32]) { .join(",") ); - #[cfg(all(target_os = "linux", feature = "selinux"))] + #[cfg(all(any(target_os = "linux", target_os = "android"), feature = "selinux"))] if state.selinux_supported && !state.user_specified && std::env::var_os("POSIXLY_CORRECT").is_none() @@ -633,7 +633,7 @@ fn id_print(state: &mut State, groups: &[u32]) { } } -#[cfg(not(target_os = "linux"))] +#[cfg(not(any(target_os = "linux", target_os = "android")))] mod audit { use super::libc::{c_int, c_uint, dev_t, pid_t, uid_t}; diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index a55f29e23..17eec91ec 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -2370,7 +2370,7 @@ fn display_len_or_rdev(metadata: &Metadata, config: &Config) -> SizeOrDeviceId { return SizeOrDeviceId::Device(major.to_string(), minor.to_string()); } } - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] { let ft = metadata.file_type(); if ft.is_char_device() || ft.is_block_device() { diff --git a/src/uu/nohup/src/nohup.rs b/src/uu/nohup/src/nohup.rs index cfafb6b5b..0d67ad466 100644 --- a/src/uu/nohup/src/nohup.rs +++ b/src/uu/nohup/src/nohup.rs @@ -213,7 +213,7 @@ extern "C" { fn _vprocmgr_detach_from_console(flags: u32) -> *const libc::c_int; } -#[cfg(any(target_os = "linux", target_os = "freebsd"))] +#[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd"))] unsafe fn _vprocmgr_detach_from_console(_: u32) -> *const libc::c_int { std::ptr::null() } diff --git a/src/uu/nproc/src/nproc.rs b/src/uu/nproc/src/nproc.rs index 87fe9a4e7..cbabde292 100644 --- a/src/uu/nproc/src/nproc.rs +++ b/src/uu/nproc/src/nproc.rs @@ -13,7 +13,7 @@ use uucore::display::Quotable; use uucore::error::{UResult, USimpleError}; use uucore::format_usage; -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] pub const _SC_NPROCESSORS_CONF: libc::c_int = 83; #[cfg(target_vendor = "apple")] pub const _SC_NPROCESSORS_CONF: libc::c_int = libc::_SC_NPROCESSORS_CONF; diff --git a/src/uu/stdbuf/src/stdbuf.rs b/src/uu/stdbuf/src/stdbuf.rs index 5e0e71789..816c86717 100644 --- a/src/uu/stdbuf/src/stdbuf.rs +++ b/src/uu/stdbuf/src/stdbuf.rs @@ -78,6 +78,7 @@ struct ProgramOptionsError(String); #[cfg(any( target_os = "linux", + target_os = "android", target_os = "freebsd", target_os = "netbsd", target_os = "dragonflybsd" @@ -93,6 +94,7 @@ fn preload_strings() -> (&'static str, &'static str) { #[cfg(not(any( target_os = "linux", + target_os = "android", target_os = "freebsd", target_os = "netbsd", target_os = "dragonflybsd", diff --git a/src/uu/sync/src/sync.rs b/src/uu/sync/src/sync.rs index f9c18d500..9baf9b182 100644 --- a/src/uu/sync/src/sync.rs +++ b/src/uu/sync/src/sync.rs @@ -27,17 +27,21 @@ static ARG_FILES: &str = "files"; #[cfg(unix)] mod platform { use super::libc; - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] use std::fs::File; - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] use std::os::unix::io::AsRawFd; pub unsafe fn do_sync() -> isize { + // see https://github.com/rust-lang/libc/pull/2161 + #[cfg(target_os = "android")] + libc::syscall(libc::SYS_sync); + #[cfg(not(target_os = "android"))] libc::sync(); 0 } - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] pub unsafe fn do_syncfs(files: Vec) -> isize { for path in files { let f = File::open(&path).unwrap(); @@ -47,7 +51,7 @@ mod platform { 0 } - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] pub unsafe fn do_fdatasync(files: Vec) -> isize { for path in files { let f = File::open(&path).unwrap(); @@ -179,10 +183,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { #[allow(clippy::if_same_then_else)] if matches.is_present(options::FILE_SYSTEM) { - #[cfg(any(target_os = "linux", target_os = "windows"))] + #[cfg(any(target_os = "linux", target_os = "android", target_os = "windows"))] syncfs(files); } else if matches.is_present(options::DATA) { - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] fdatasync(files); } else { sync(); @@ -221,12 +225,12 @@ fn sync() -> isize { unsafe { platform::do_sync() } } -#[cfg(any(target_os = "linux", target_os = "windows"))] +#[cfg(any(target_os = "linux", target_os = "android", target_os = "windows"))] fn syncfs(files: Vec) -> isize { unsafe { platform::do_syncfs(files) } } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] fn fdatasync(files: Vec) -> isize { unsafe { platform::do_fdatasync(files) } } diff --git a/src/uu/touch/src/touch.rs b/src/uu/touch/src/touch.rs index 864917574..ff08a1b59 100644 --- a/src/uu/touch/src/touch.rs +++ b/src/uu/touch/src/touch.rs @@ -320,10 +320,14 @@ fn parse_timestamp(s: &str) -> UResult { /// On Windows, uses GetFinalPathNameByHandleW to attempt to get the path /// from the stdout handle. fn pathbuf_from_stdout() -> UResult { - #[cfg(unix)] + #[cfg(all(unix, not(target_os = "android")))] { Ok(PathBuf::from("/dev/stdout")) } + #[cfg(target_os = "android")] + { + Ok(PathBuf::from("/proc/self/fd/1")) + } #[cfg(windows)] { use std::os::windows::prelude::AsRawHandle; diff --git a/src/uu/uname/src/uname.rs b/src/uu/uname/src/uname.rs index bff033047..f7b578c27 100644 --- a/src/uu/uname/src/uname.rs +++ b/src/uu/uname/src/uname.rs @@ -36,6 +36,8 @@ pub mod options { const HOST_OS: &str = "GNU/Linux"; #[cfg(all(target_os = "linux", not(any(target_env = "gnu", target_env = ""))))] const HOST_OS: &str = "Linux"; +#[cfg(target_os = "android")] +const HOST_OS: &str = "Android"; #[cfg(target_os = "windows")] const HOST_OS: &str = "Windows NT"; #[cfg(target_os = "freebsd")] diff --git a/src/uu/wc/src/count_fast.rs b/src/uu/wc/src/count_fast.rs index 4515cd3d7..f0aa311a0 100644 --- a/src/uu/wc/src/count_fast.rs +++ b/src/uu/wc/src/count_fast.rs @@ -37,7 +37,7 @@ fn count_bytes_using_splice(fd: &impl AsRawFd) -> Result { let null_rdev = stat::fstat(null_file.as_raw_fd()) .map_err(|_| 0_usize)? .st_rdev; - if (stat::major(null_rdev), stat::minor(null_rdev)) != (1, 3) { + if unsafe { (libc::major(null_rdev), libc::minor(null_rdev)) } != (1, 3) { // This is not a proper /dev/null, writing to it is probably bad // Bit of an edge case, but it has been known to happen return Err(0); diff --git a/src/uu/who/src/who.rs b/src/uu/who/src/who.rs index 98ef06f47..6e21ac912 100644 --- a/src/uu/who/src/who.rs +++ b/src/uu/who/src/who.rs @@ -40,7 +40,7 @@ mod options { static ABOUT: &str = "Print information about users who are currently logged in."; const USAGE: &str = "{} [OPTION]... [ FILE | ARG1 ARG2 ]"; -#[cfg(any(target_os = "linux"))] +#[cfg(target_os = "linux")] static RUNLEVEL_HELP: &str = "print current runlevel"; #[cfg(not(target_os = "linux"))] static RUNLEVEL_HELP: &str = "print current runlevel (This is meaningless on non Linux)"; diff --git a/src/uucore/src/lib/features.rs b/src/uucore/src/lib/features.rs index b1b87a613..2e5aea1e2 100644 --- a/src/uucore/src/lib/features.rs +++ b/src/uucore/src/lib/features.rs @@ -34,6 +34,7 @@ pub mod process; pub mod signals; #[cfg(all( unix, + not(target_os = "android"), not(target_os = "fuchsia"), not(target_os = "redox"), not(target_env = "musl"), diff --git a/src/uucore/src/lib/features/fsext.rs b/src/uucore/src/lib/features/fsext.rs index 6845ca3ca..eeaf54061 100644 --- a/src/uucore/src/lib/features/fsext.rs +++ b/src/uucore/src/lib/features/fsext.rs @@ -15,9 +15,9 @@ extern crate time; pub use crate::*; // import macros from `../../macros.rs` -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] const LINUX_MTAB: &str = "/etc/mtab"; -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] const LINUX_MOUNTINFO: &str = "/proc/self/mountinfo"; static MOUNT_OPT_BIND: &str = "bind"; #[cfg(windows)] @@ -75,7 +75,8 @@ use std::convert::{AsRef, From}; target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", - target_os = "linux" + target_os = "linux", + target_os = "android", ))] use std::ffi::CStr; #[cfg(not(windows))] @@ -88,8 +89,8 @@ use std::time::UNIX_EPOCH; #[cfg(any( target_os = "linux", - target_vendor = "apple", target_os = "android", + target_vendor = "apple", target_os = "freebsd", target_os = "openbsd" ))] @@ -106,8 +107,8 @@ pub use libc::statvfs as StatFs; #[cfg(any( target_os = "linux", - target_vendor = "apple", target_os = "android", + target_vendor = "apple", target_os = "freebsd", target_os = "openbsd", target_os = "redox" @@ -208,7 +209,7 @@ impl MountInfo { } } - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] fn new(file_name: &str, raw: &[&str]) -> Option { match file_name { // spell-checker:ignore (word) noatime @@ -382,9 +383,9 @@ extern "C" { fn get_mount_info(mount_buffer_p: *mut *mut StatFs, flags: c_int) -> c_int; } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] use std::fs::File; -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] use std::io::{BufRead, BufReader}; #[cfg(any( target_vendor = "apple", @@ -403,7 +404,7 @@ use std::ptr; use std::slice; /// Read file system list. pub fn read_fs_list() -> Vec { - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] { let (file_name, f) = File::open(LINUX_MOUNTINFO) .map(|f| (LINUX_MOUNTINFO, f)) @@ -611,17 +612,27 @@ impl FsMeta for StatFs { fn free_file_nodes(&self) -> u64 { self.f_ffree as u64 } - #[cfg(any(target_os = "linux", target_vendor = "apple", target_os = "freebsd"))] + #[cfg(any( + target_os = "linux", + target_os = "android", + target_vendor = "apple", + target_os = "freebsd" + ))] fn fs_type(&self) -> i64 { self.f_type as i64 } - #[cfg(not(any(target_os = "linux", target_vendor = "apple", target_os = "freebsd")))] + #[cfg(not(any( + target_os = "linux", + target_os = "android", + target_vendor = "apple", + target_os = "freebsd" + )))] fn fs_type(&self) -> i64 { // FIXME: statvfs doesn't have an equivalent, so we need to do something else unimplemented!() } - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] fn io_size(&self) -> u64 { self.f_frsize as u64 } @@ -634,6 +645,7 @@ impl FsMeta for StatFs { target_vendor = "apple", target_os = "freebsd", target_os = "linux", + target_os = "android", target_os = "netbsd" )))] fn io_size(&self) -> u64 { @@ -650,24 +662,26 @@ impl FsMeta for StatFs { target_vendor = "apple", target_os = "freebsd", target_os = "linux", + target_os = "android", target_os = "openbsd" ))] fn fsid(&self) -> u64 { let f_fsid: &[u32; 2] = - unsafe { &*(&self.f_fsid as *const libc::fsid_t as *const [u32; 2]) }; + unsafe { &*(&self.f_fsid as *const nix::sys::statfs::fsid_t as *const [u32; 2]) }; (u64::from(f_fsid[0])) << 32 | u64::from(f_fsid[1]) } #[cfg(not(any( target_vendor = "apple", target_os = "freebsd", target_os = "linux", + target_os = "android", target_os = "openbsd" )))] fn fsid(&self) -> u64 { self.f_fsid as u64 } - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] fn namelen(&self) -> u64 { self.f_namelen as u64 } @@ -684,6 +698,7 @@ impl FsMeta for StatFs { target_vendor = "apple", target_os = "freebsd", target_os = "linux", + target_os = "android", target_os = "netbsd", target_os = "openbsd" )))] @@ -903,7 +918,7 @@ mod tests { } #[test] - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] fn test_mountinfo() { // spell-checker:ignore (word) relatime let info = MountInfo::new( diff --git a/src/uucore/src/lib/features/signals.rs b/src/uucore/src/lib/features/signals.rs index e6d2e7763..e7b20e7d8 100644 --- a/src/uucore/src/lib/features/signals.rs +++ b/src/uucore/src/lib/features/signals.rs @@ -23,7 +23,7 @@ Linux Programmer's Manual */ -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] pub static ALL_SIGNALS: [&str; 32] = [ "EXIT", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "BUS", "FPE", "KILL", "USR1", "SEGV", "USR2", "PIPE", "ALRM", "TERM", "STKFLT", "CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU", diff --git a/src/uucore/src/lib/features/utmpx.rs b/src/uucore/src/lib/features/utmpx.rs index 2a0e2810b..302d03d71 100644 --- a/src/uucore/src/lib/features/utmpx.rs +++ b/src/uucore/src/lib/features/utmpx.rs @@ -198,14 +198,14 @@ impl Utmpx { /// A.K.A. ut.ut_exit /// /// Return (e_termination, e_exit) - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(target_os = "linux")] pub fn exit_status(&self) -> (i16, i16) { (self.inner.ut_exit.e_termination, self.inner.ut_exit.e_exit) } /// A.K.A. ut.ut_exit /// /// Return (0, 0) on Non-Linux platform - #[cfg(not(any(target_os = "linux", target_os = "android")))] + #[cfg(not(target_os = "linux"))] pub fn exit_status(&self) -> (i16, i16) { (0, 0) } diff --git a/src/uucore/src/lib/lib.rs b/src/uucore/src/lib/lib.rs index 8f3d045eb..ad8f81259 100644 --- a/src/uucore/src/lib/lib.rs +++ b/src/uucore/src/lib/lib.rs @@ -62,6 +62,7 @@ pub use crate::features::process; pub use crate::features::signals; #[cfg(all( unix, + not(target_os = "android"), not(target_os = "fuchsia"), not(target_os = "redox"), not(target_env = "musl"), diff --git a/tests/by-util/test_cat.rs b/tests/by-util/test_cat.rs index 96c77a40e..d4541d690 100644 --- a/tests/by-util/test_cat.rs +++ b/tests/by-util/test_cat.rs @@ -5,7 +5,7 @@ use std::fs::OpenOptions; #[cfg(unix)] use std::io::Read; -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] use rlimit::Resource; #[test] @@ -93,7 +93,7 @@ fn test_fifo_symlink() { } #[test] -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] fn test_closes_file_descriptors() { // Each file creates a pipe, which has two file descriptors. // If they are not closed then five is certainly too many. @@ -396,10 +396,10 @@ fn test_squeeze_blank_before_numbering() { #[cfg(unix)] fn test_dev_random() { let mut buf = [0; 2048]; - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] const DEV_RANDOM: &str = "/dev/urandom"; - #[cfg(not(target_os = "linux"))] + #[cfg(not(any(target_os = "linux", target_os = "android")))] const DEV_RANDOM: &str = "/dev/random"; let mut proc = new_ucmd!().args(&[DEV_RANDOM]).run_no_wait(); diff --git a/tests/by-util/test_chgrp.rs b/tests/by-util/test_chgrp.rs index 1d89caca7..33ec2c6c9 100644 --- a/tests/by-util/test_chgrp.rs +++ b/tests/by-util/test_chgrp.rs @@ -8,7 +8,7 @@ fn test_invalid_option() { new_ucmd!().arg("-w").arg("/").fails(); } -static DIR: &str = "/tmp"; +static DIR: &str = "/dev"; // we should always get both arguments, regardless of whether --reference was used #[test] @@ -49,11 +49,13 @@ fn test_invalid_group() { #[test] fn test_1() { if get_effective_gid() != 0 { - new_ucmd!() - .arg("bin") - .arg(DIR) - .fails() - .stderr_is("chgrp: changing group of '/tmp': Operation not permitted (os error 1)"); + new_ucmd!().arg("bin").arg(DIR).fails().stderr_contains( + // linux fails with "Operation not permitted (os error 1)" + // because of insufficient permissions, + // android fails with "Permission denied (os error 13)" + // because it can't resolve /proc (even though it can resolve /proc/self/) + "chgrp: changing group of '/dev': ", + ); } } @@ -76,7 +78,7 @@ fn test_preserve_root() { // It's weird that on OS X, `realpath /etc/..` returns '/private' for d in [ "/", - "/////tmp///../../../../", + "/////dev///../../../../", "../../../../../../../../../../../../../../", "./../../../../../../../../../../../../../../", ] { @@ -94,7 +96,7 @@ fn test_preserve_root_symlink() { let file = "test_chgrp_symlink2root"; for d in [ "/", - "////tmp//../../../../", + "////dev//../../../../", "..//../../..//../..//../../../../../../../../", ".//../../../../../../..//../../../../../../../", ] { @@ -108,7 +110,7 @@ fn test_preserve_root_symlink() { } let (at, mut ucmd) = at_and_ucmd!(); - at.symlink_file("///usr", file); + at.symlink_file("///dev", file); ucmd.arg("--preserve-root") .arg("-HR") .arg("bin").arg(format!(".//{}/..//..//../../", file)) @@ -116,15 +118,12 @@ fn test_preserve_root_symlink() { .stderr_is("chgrp: it is dangerous to operate recursively on '/'\nchgrp: use --no-preserve-root to override this failsafe"); let (at, mut ucmd) = at_and_ucmd!(); - at.symlink_file("/", "/tmp/__root__"); + at.symlink_file("/", "__root__"); ucmd.arg("--preserve-root") .arg("-R") - .arg("bin").arg("/tmp/__root__/.") + .arg("bin").arg("__root__/.") .fails() .stderr_is("chgrp: it is dangerous to operate recursively on '/'\nchgrp: use --no-preserve-root to override this failsafe"); - - use std::fs; - fs::remove_file("/tmp/__root__").unwrap(); } #[test] @@ -156,7 +155,7 @@ fn test_reference() { } #[test] -#[cfg(any(target_os = "linux", target_vendor = "apple"))] +#[cfg(any(target_os = "linux", target_os = "android", target_vendor = "apple"))] fn test_reference_multi_no_equal() { new_ucmd!() .arg("-v") @@ -170,7 +169,7 @@ fn test_reference_multi_no_equal() { } #[test] -#[cfg(any(target_os = "linux", target_vendor = "apple"))] +#[cfg(any(target_os = "linux", target_os = "android", target_vendor = "apple"))] fn test_reference_last() { new_ucmd!() .arg("-v") @@ -212,7 +211,7 @@ fn test_big_p() { } #[test] -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] fn test_big_h() { if get_effective_gid() != 0 { assert!( diff --git a/tests/by-util/test_chown.rs b/tests/by-util/test_chown.rs index 0857e5659..4470260f4 100644 --- a/tests/by-util/test_chown.rs +++ b/tests/by-util/test_chown.rs @@ -1,7 +1,7 @@ // spell-checker:ignore (words) agroupthatdoesntexist auserthatdoesntexist cuuser groupname notexisting passgrp use crate::common::util::*; -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] use rust_users::get_effective_uid; extern crate chown; @@ -617,7 +617,7 @@ fn test_root_preserve() { result.stderr_contains(&"chown: it is dangerous to operate recursively"); } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] #[test] fn test_big_p() { if get_effective_uid() != 0 { @@ -627,7 +627,11 @@ fn test_big_p() { .arg("/proc/self/cwd") .fails() .stderr_contains( - "chown: changing ownership of '/proc/self/cwd': Operation not permitted (os error 1)", + // linux fails with "Operation not permitted (os error 1)" + // because of insufficient permissions, + // android fails with "Permission denied (os error 13)" + // because it can't resolve /proc (even though it can resolve /proc/self/) + "chown: changing ownership of '/proc/self/cwd': ", ); } } diff --git a/tests/by-util/test_chroot.rs b/tests/by-util/test_chroot.rs index 3e5c22679..6c9237ac3 100644 --- a/tests/by-util/test_chroot.rs +++ b/tests/by-util/test_chroot.rs @@ -14,6 +14,7 @@ fn test_missing_operand() { } #[test] +#[cfg(not(target_os = "android"))] fn test_enter_chroot_fails() { // NOTE: since #2689 this test also ensures that we don't regress #2687 let (at, mut ucmd) = at_and_ucmd!(); diff --git a/tests/by-util/test_cp.rs b/tests/by-util/test_cp.rs index 7bb11306d..079e966be 100644 --- a/tests/by-util/test_cp.rs +++ b/tests/by-util/test_cp.rs @@ -14,15 +14,15 @@ use std::os::unix::fs::PermissionsExt; #[cfg(windows)] use std::os::windows::fs::symlink_file; -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] use filetime::FileTime; -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] use rlimit::Resource; -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] use std::fs as std_fs; -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] use std::thread::sleep; -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] use std::time::Duration; static TEST_EXISTING_FILE: &str = "existing_file.txt"; @@ -38,11 +38,11 @@ static TEST_COPY_FROM_FOLDER: &str = "hello_dir_with_file/"; static TEST_COPY_FROM_FOLDER_FILE: &str = "hello_dir_with_file/hello_world.txt"; static TEST_COPY_TO_FOLDER_NEW: &str = "hello_dir_new"; static TEST_COPY_TO_FOLDER_NEW_FILE: &str = "hello_dir_new/hello_world.txt"; -#[cfg(any(target_os = "linux", target_os = "freebsd"))] +#[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd"))] static TEST_MOUNT_COPY_FROM_FOLDER: &str = "dir_with_mount"; -#[cfg(any(target_os = "linux", target_os = "freebsd"))] +#[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd"))] static TEST_MOUNT_MOUNTPOINT: &str = "mount"; -#[cfg(any(target_os = "linux", target_os = "freebsd"))] +#[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd"))] static TEST_MOUNT_OTHER_FILESYSTEM_FILE: &str = "mount/DO_NOT_copy_me.txt"; #[cfg(unix)] static TEST_NONEXISTENT_FILE: &str = "nonexistent_file.txt"; @@ -1062,7 +1062,7 @@ fn test_cp_archive() { } #[test] -#[cfg(unix)] +#[cfg(all(unix, not(target_os = "android")))] fn test_cp_archive_recursive() { let (at, mut ucmd) = at_and_ucmd!(); @@ -1132,7 +1132,7 @@ fn test_cp_archive_recursive() { } #[test] -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] fn test_cp_preserve_timestamps() { let (at, mut ucmd) = at_and_ucmd!(); let ts = time::now().to_timespec(); @@ -1165,7 +1165,7 @@ fn test_cp_preserve_timestamps() { } #[test] -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] fn test_cp_no_preserve_timestamps() { let (at, mut ucmd) = at_and_ucmd!(); let ts = time::now().to_timespec(); @@ -1206,7 +1206,7 @@ fn test_cp_no_preserve_timestamps() { } #[test] -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] fn test_cp_target_file_dev_null() { let (at, mut ucmd) = at_and_ucmd!(); let file1 = "/dev/null"; @@ -1219,7 +1219,7 @@ fn test_cp_target_file_dev_null() { } #[test] -#[cfg(any(target_os = "linux", target_os = "freebsd"))] +#[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd"))] fn test_cp_one_file_system() { use crate::common::util::AtPath; use walkdir::WalkDir; @@ -1283,7 +1283,7 @@ fn test_cp_one_file_system() { } #[test] -#[cfg(any(target_os = "linux", target_os = "macos"))] +#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos"))] fn test_cp_reflink_always() { let (at, mut ucmd) = at_and_ucmd!(); let result = ucmd @@ -1301,7 +1301,7 @@ fn test_cp_reflink_always() { } #[test] -#[cfg(any(target_os = "linux", target_os = "macos"))] +#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos"))] fn test_cp_reflink_auto() { let (at, mut ucmd) = at_and_ucmd!(); ucmd.arg("--reflink=auto") @@ -1314,7 +1314,7 @@ fn test_cp_reflink_auto() { } #[test] -#[cfg(any(target_os = "linux", target_os = "macos"))] +#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos"))] fn test_cp_reflink_never() { let (at, mut ucmd) = at_and_ucmd!(); ucmd.arg("--reflink=never") @@ -1327,7 +1327,7 @@ fn test_cp_reflink_never() { } #[test] -#[cfg(any(target_os = "linux", target_os = "macos"))] +#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos"))] fn test_cp_reflink_bad() { let (_, mut ucmd) = at_and_ucmd!(); let _result = ucmd @@ -1339,7 +1339,7 @@ fn test_cp_reflink_bad() { } #[test] -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] fn test_cp_reflink_insufficient_permission() { let (at, mut ucmd) = at_and_ucmd!(); @@ -1355,7 +1355,7 @@ fn test_cp_reflink_insufficient_permission() { .stderr_only("cp: 'unreadable' -> 'existing_file.txt': Permission denied (os error 13)"); } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] #[test] fn test_closes_file_descriptors() { new_ucmd!() @@ -1520,6 +1520,7 @@ fn test_cp_archive_on_nonexistent_file() { } #[test] +#[cfg(not(target_os = "android"))] fn test_cp_link_backup() { let (at, mut ucmd) = at_and_ucmd!(); at.touch("file2"); @@ -1613,6 +1614,7 @@ fn test_cp_overriding_arguments() { ("--force", "--remove-destination"), ("--interactive", "--no-clobber"), ("--link", "--symbolic-link"), + #[cfg(not(target_os = "android"))] ("--symbolic-link", "--link"), ("--dereference", "--no-dereference"), ("--no-dereference", "--dereference"), diff --git a/tests/by-util/test_date.rs b/tests/by-util/test_date.rs index a04de9b59..81b176ce9 100644 --- a/tests/by-util/test_date.rs +++ b/tests/by-util/test_date.rs @@ -149,7 +149,7 @@ fn test_date_set_invalid() { } #[test] -#[cfg(all(unix, not(target_os = "macos")))] +#[cfg(all(unix, not(any(target_os = "android", target_os = "macos"))))] fn test_date_set_permissions_error() { if !(get_effective_uid() == 0 || uucore::os::is_wsl_1()) { let result = new_ucmd!() diff --git a/tests/by-util/test_dd.rs b/tests/by-util/test_dd.rs index 71049a2af..3cc5346b7 100644 --- a/tests/by-util/test_dd.rs +++ b/tests/by-util/test_dd.rs @@ -32,7 +32,7 @@ macro_rules! assert_fixture_exists { }}; } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] macro_rules! assert_fixture_not_exists { ($fname:expr) => {{ let fpath = PathBuf::from(format!("./fixtures/dd/{}", $fname)); @@ -261,7 +261,7 @@ fn test_final_stats_unspec() { new_ucmd!().run().stderr_only(&output).success(); } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] #[test] fn test_excl_causes_failure_when_present() { let fname = "this-file-exists-excl.txt"; @@ -272,7 +272,7 @@ fn test_excl_causes_failure_when_present() { .fails(); } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] #[test] fn test_noatime_does_not_update_infile_atime() { // NOTE: Not all environments support tracking access time. If this @@ -292,7 +292,7 @@ fn test_noatime_does_not_update_infile_atime() { assert_eq!(pre_atime, post_atime); } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] #[test] fn test_noatime_does_not_update_ofile_atime() { // NOTE: Not all environments support tracking access time. If this @@ -312,7 +312,7 @@ fn test_noatime_does_not_update_ofile_atime() { assert_eq!(pre_atime, post_atime); } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] #[test] fn test_nocreat_causes_failure_when_outfile_not_present() { let fname = "this-file-does-not-exist.txt"; diff --git a/tests/by-util/test_du.rs b/tests/by-util/test_du.rs index 1deddb77f..254e75166 100644 --- a/tests/by-util/test_du.rs +++ b/tests/by-util/test_du.rs @@ -47,7 +47,7 @@ fn test_du_basics_subdir() { let result = ts.ucmd().arg(SUB_DIR).succeeds(); - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] { let result_reference = unwrap_or_return!(expected_result(&ts, &[SUB_DIR])); if result_reference.succeeded() { @@ -122,7 +122,7 @@ fn test_du_soft_link() { let result = ts.ucmd().arg(SUB_DIR_LINKS).succeeds(); - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] { let result_reference = unwrap_or_return!(expected_result(&ts, &[SUB_DIR_LINKS])); if result_reference.succeeded() { @@ -160,6 +160,7 @@ fn _du_soft_link(s: &str) { } } +#[cfg(not(target_os = "android"))] #[test] fn test_du_hard_link() { let ts = TestScenario::new(util_name!()); @@ -213,7 +214,7 @@ fn test_du_d_flag() { let result = ts.ucmd().arg("-d1").succeeds(); - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] { let result_reference = unwrap_or_return!(expected_result(&ts, &["-d1"])); if result_reference.succeeded() { @@ -259,7 +260,7 @@ fn test_du_dereference() { let result = ts.ucmd().arg("-L").arg(SUB_DIR_LINKS).succeeds(); - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] { let result_reference = unwrap_or_return!(expected_result(&ts, &["-L", SUB_DIR_LINKS])); @@ -303,13 +304,13 @@ fn test_du_inodes_basic() { let ts = TestScenario::new(util_name!()); let result = ts.ucmd().arg("--inodes").succeeds(); - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] { let result_reference = unwrap_or_return!(expected_result(&ts, &["--inodes"])); assert_eq!(result.stdout_str(), result_reference.stdout_str()); } - #[cfg(not(target_os = "linux"))] + #[cfg(not(any(target_os = "linux", target_os = "android")))] _du_inodes_basic(result.stdout_str()); } @@ -357,7 +358,7 @@ fn test_du_inodes() { result.stdout_contains("3\t./subdir/links\n"); result.stdout_contains("3\t.\n"); - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] { let result_reference = unwrap_or_return!(expected_result(&ts, &["--separate-dirs", "--inodes"])); @@ -438,7 +439,7 @@ fn test_du_no_permission() { "du: cannot read directory 'subdir/links': Permission denied (os error 13)", ); - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] { let result_reference = unwrap_or_return!(expected_result(&ts, &[SUB_DIR_LINKS])); if result_reference @@ -483,7 +484,7 @@ fn test_du_one_file_system() { let result = ts.ucmd().arg("-x").arg(SUB_DIR).succeeds(); - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] { let result_reference = unwrap_or_return!(expected_result(&ts, &["-x", SUB_DIR])); if result_reference.succeeded() { @@ -518,13 +519,13 @@ fn test_du_apparent_size() { let ts = TestScenario::new(util_name!()); let result = ts.ucmd().arg("--apparent-size").succeeds(); - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] { let result_reference = unwrap_or_return!(expected_result(&ts, &["--apparent-size"])); assert_eq!(result.stdout_str(), result_reference.stdout_str()); } - #[cfg(not(target_os = "linux"))] + #[cfg(not(any(target_os = "linux", target_os = "android")))] _du_apparent_size(result.stdout_str()); } @@ -586,7 +587,7 @@ fn test_du_bytes() { let ts = TestScenario::new(util_name!()); let result = ts.ucmd().arg("--bytes").succeeds(); - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] { let result_reference = unwrap_or_return!(expected_result(&ts, &["--bytes"])); assert_eq!(result.stdout_str(), result_reference.stdout_str()); @@ -602,7 +603,8 @@ fn test_du_bytes() { not(target_vendor = "apple"), not(target_os = "windows"), not(target_os = "freebsd"), - not(target_os = "linux") + not(target_os = "linux"), + not(target_os = "android"), ))] result.stdout_contains("21529\t./subdir\n"); } diff --git a/tests/by-util/test_id.rs b/tests/by-util/test_id.rs index 8606678e9..b791dbfd0 100644 --- a/tests/by-util/test_id.rs +++ b/tests/by-util/test_id.rs @@ -139,7 +139,7 @@ fn test_id_real() { } #[test] -#[cfg(all(unix, not(target_os = "linux")))] +#[cfg(all(unix, not(any(target_os = "linux", target_os = "android"))))] fn test_id_pretty_print() { // `-p` is BSD only and not supported on GNU's `id` let username = whoami(); @@ -159,7 +159,7 @@ fn test_id_pretty_print() { } #[test] -#[cfg(all(unix, not(target_os = "linux")))] +#[cfg(all(unix, not(any(target_os = "linux", target_os = "android"))))] fn test_id_password_style() { // `-P` is BSD only and not supported on GNU's `id` let username = whoami(); @@ -437,7 +437,10 @@ fn test_id_no_specified_user_posixly() { result.success(); } - #[cfg(all(target_os = "linux", feature = "feat_selinux"))] + #[cfg(all( + any(target_os = "linux", target_os = "android"), + feature = "feat_selinux" + ))] { use selinux::{self, KernelSupport}; if selinux::kernel_support() == KernelSupport::Unsupported { diff --git a/tests/by-util/test_install.rs b/tests/by-util/test_install.rs index a0e18c19a..dca04ac56 100644 --- a/tests/by-util/test_install.rs +++ b/tests/by-util/test_install.rs @@ -6,7 +6,7 @@ use rust_users::*; use std::os::unix::fs::PermissionsExt; #[cfg(not(any(windows, target_os = "freebsd")))] use std::process::Command; -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] use std::thread::sleep; #[test] @@ -98,7 +98,11 @@ fn test_install_ancestors_mode_directories() { let ancestor2 = "ancestor1/ancestor2"; let target_dir = "ancestor1/ancestor2/target_dir"; let directories_arg = "-d"; - let mode_arg = "--mode=700"; + let mode_arg = "--mode=200"; + let probe = "probe"; + + at.mkdir(probe); + let default_perms = at.metadata(probe).permissions().mode(); ucmd.args(&[mode_arg, directories_arg, target_dir]) .succeeds() @@ -108,11 +112,11 @@ fn test_install_ancestors_mode_directories() { assert!(at.dir_exists(ancestor2)); assert!(at.dir_exists(target_dir)); - assert_ne!(0o40_700_u32, at.metadata(ancestor1).permissions().mode()); - assert_ne!(0o40_700_u32, at.metadata(ancestor2).permissions().mode()); + assert_eq!(default_perms, at.metadata(ancestor1).permissions().mode()); + assert_eq!(default_perms, at.metadata(ancestor2).permissions().mode()); // Expected mode only on the target_dir. - assert_eq!(0o40_700_u32, at.metadata(target_dir).permissions().mode()); + assert_eq!(0o40_200_u32, at.metadata(target_dir).permissions().mode()); } #[test] @@ -386,7 +390,7 @@ fn test_install_copy_file() { } #[test] -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] fn test_install_target_file_dev_null() { let (at, mut ucmd) = at_and_ucmd!(); @@ -487,7 +491,7 @@ fn test_install_copy_then_compare_file() { } #[test] -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] fn test_install_copy_then_compare_file_with_extra_mode() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -549,6 +553,8 @@ const STRIP_SOURCE_FILE_SYMBOL: &str = "main"; fn strip_source_file() -> &'static str { if cfg!(target_os = "macos") { "helloworld_macos" + } else if cfg!(target_arch = "arm") || cfg!(target_arch = "aarch64") { + "helloworld_android" } else { "helloworld_linux" } diff --git a/tests/by-util/test_link.rs b/tests/by-util/test_link.rs index 6e98f1d64..9f6a2ee5f 100644 --- a/tests/by-util/test_link.rs +++ b/tests/by-util/test_link.rs @@ -1,5 +1,6 @@ use crate::common::util::*; +#[cfg(not(target_os = "android"))] #[test] fn test_link_existing_file() { let (at, mut ucmd) = at_and_ucmd!(); diff --git a/tests/by-util/test_ln.rs b/tests/by-util/test_ln.rs index 0dcde3b35..980225260 100644 --- a/tests/by-util/test_ln.rs +++ b/tests/by-util/test_ln.rs @@ -360,7 +360,7 @@ fn test_symlink_verbose() { scene .ucmd() - .args(&["-v", file_a, file_b]) + .args(&["-s", "-v", file_a, file_b]) .succeeds() .stdout_only(format!("'{}' -> '{}'\n", file_b, file_a)); @@ -368,7 +368,7 @@ fn test_symlink_verbose() { scene .ucmd() - .args(&["-v", "-b", file_a, file_b]) + .args(&["-s", "-v", "-b", file_a, file_b]) .succeeds() .stdout_only(format!( "'{}' -> '{}' (backup: '{}~')\n", @@ -639,7 +639,7 @@ fn test_backup_force() { assert!(at.file_exists("b~")); scene .ucmd() - .args(&["-f", "--b=simple", "a", "b"]) + .args(&["-s", "-f", "--b=simple", "a", "b"]) .succeeds() .no_stderr(); assert!(at.file_exists("a")); diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index f979d1e14..72217a403 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -314,7 +314,7 @@ fn test_ls_devices() { .stdout_matches(&Regex::new("[^ ] 3, 2 [^ ]").unwrap()); } - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] { scene .ucmd() @@ -327,11 +327,15 @@ fn test_ls_devices() { // Tests display alignment against a file (stdout is a link to a tty) #[cfg(unix)] { + #[cfg(not(target_os = "android"))] + let stdout = "/dev/stdout"; + #[cfg(target_os = "android")] + let stdout = "/proc/self/fd/1"; let res = scene .ucmd() .arg("-alL") .arg("/dev/null") - .arg("/dev/stdout") + .arg(stdout) .succeeds(); let null_len = String::from_utf8(res.stdout().to_owned()) @@ -350,7 +354,7 @@ fn test_ls_devices() { .lines() .nth(1) .unwrap() - .strip_suffix("/dev/stdout") + .strip_suffix(stdout) .unwrap() .len(); @@ -1546,9 +1550,9 @@ fn test_ls_order_time() { at.open("test-4").metadata().unwrap().accessed().unwrap(); // It seems to be dependent on the platform whether the access time is actually set - #[cfg(unix)] + #[cfg(all(unix, not(target_os = "android")))] result.stdout_only("test-3\ntest-4\ntest-2\ntest-1\n"); - #[cfg(windows)] + #[cfg(any(windows, target_os = "android"))] result.stdout_only("test-4\ntest-3\ntest-2\ntest-1\n"); } diff --git a/tests/by-util/test_mv.rs b/tests/by-util/test_mv.rs index 314fd3a7f..c4ec03d95 100644 --- a/tests/by-util/test_mv.rs +++ b/tests/by-util/test_mv.rs @@ -783,7 +783,7 @@ fn test_mv_verbose() { } #[test] -#[cfg(target_os = "linux")] // mkdir does not support -m on windows. Freebsd doesn't return a permission error either. +#[cfg(any(target_os = "linux", target_os = "android"))] // mkdir does not support -m on windows. Freebsd doesn't return a permission error either. fn test_mv_permission_error() { let scene = TestScenario::new("mkdir"); let folder1 = "bar"; diff --git a/tests/by-util/test_nice.rs b/tests/by-util/test_nice.rs index 4a77ae24e..2b53ed437 100644 --- a/tests/by-util/test_nice.rs +++ b/tests/by-util/test_nice.rs @@ -1,6 +1,7 @@ use crate::common::util::*; #[test] +#[cfg(not(target_os = "android"))] fn test_get_current_niceness() { // NOTE: this assumes the test suite is being run with a default niceness // of 0, which may not necessarily be true @@ -8,6 +9,7 @@ fn test_get_current_niceness() { } #[test] +#[cfg(not(target_os = "android"))] fn test_negative_adjustment() { // This assumes the test suite is run as a normal (non-root) user, and as // such attempting to set a negative niceness value will be rejected by diff --git a/tests/by-util/test_nohup.rs b/tests/by-util/test_nohup.rs index b98ae007c..8d848131c 100644 --- a/tests/by-util/test_nohup.rs +++ b/tests/by-util/test_nohup.rs @@ -6,7 +6,12 @@ use std::thread::sleep; // All that can be tested is the side-effects. #[test] -#[cfg(any(target_os = "linux", target_os = "freebsd", target_vendor = "apple"))] +#[cfg(any( + target_os = "linux", + target_os = "android", + target_os = "freebsd", + target_vendor = "apple" +))] fn test_nohup_multiple_args_and_flags() { let (at, mut ucmd) = at_and_ucmd!(); diff --git a/tests/by-util/test_sort.rs b/tests/by-util/test_sort.rs index 4975ceff4..24846d207 100644 --- a/tests/by-util/test_sort.rs +++ b/tests/by-util/test_sort.rs @@ -872,7 +872,7 @@ fn sort_empty_chunk() { } #[test] -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] fn test_compress() { new_ucmd!() .args(&[ @@ -888,7 +888,7 @@ fn test_compress() { } #[test] -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] fn test_compress_merge() { new_ucmd!() .args(&[ diff --git a/tests/by-util/test_stat.rs b/tests/by-util/test_stat.rs index b8445543f..90ad2d12a 100644 --- a/tests/by-util/test_stat.rs +++ b/tests/by-util/test_stat.rs @@ -113,14 +113,14 @@ fn test_invalid_option() { #[cfg(unix)] const NORMAL_FORMAT_STR: &str = "%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s %u %U %x %X %y %Y %z %Z"; // avoid "%w %W" (birth/creation) due to `stat` limitations and linux kernel & rust version capability variations -#[cfg(any(target_os = "linux"))] +#[cfg(any(target_os = "linux", target_os = "android"))] const DEV_FORMAT_STR: &str = "%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s (%t/%T) %u %U %w %W %x %X %y %Y %z %Z"; #[cfg(target_os = "linux")] const FS_FORMAT_STR: &str = "%b %c %i %l %n %s %S %t %T"; // avoid "%a %d %f" which can cause test failure due to race conditions #[test] -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] fn test_terse_fs_format() { let args = ["-f", "-t", "/proc"]; let ts = TestScenario::new(util_name!()); @@ -238,6 +238,7 @@ fn test_symlinks() { // arbitrarily chosen symlinks with hope that the CI environment provides at least one of them for file in [ "/bin/sh", + "/data/data/com.termux/files/usr/bin/sh", // spell-checker:disable-line "/bin/sudoedit", "/usr/bin/ex", "/etc/localtime", @@ -259,7 +260,7 @@ fn test_symlinks() { } } -#[cfg(any(target_os = "linux", target_vendor = "apple"))] +#[cfg(any(target_os = "linux", target_os = "android", target_vendor = "apple"))] #[test] fn test_char() { // TODO: "(%t) (%x) (%w)" deviate from GNU stat for `character special file` on macOS @@ -268,13 +269,13 @@ fn test_char() { // >"(f) (2021-05-20 23:08:03.455598000 +0200) (-)\n" let args = [ "-c", - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] DEV_FORMAT_STR, #[cfg(target_os = "linux")] "/dev/pts/ptmx", #[cfg(any(target_vendor = "apple"))] "%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s (/%T) %u %U %W %X %y %Y %z %Z", - #[cfg(any(target_vendor = "apple"))] + #[cfg(any(target_os = "android", target_vendor = "apple"))] "/dev/ptmx", ]; let ts = TestScenario::new(util_name!()); diff --git a/tests/by-util/test_uname.rs b/tests/by-util/test_uname.rs index adcaa1072..5e78ddc13 100644 --- a/tests/by-util/test_uname.rs +++ b/tests/by-util/test_uname.rs @@ -53,6 +53,11 @@ fn test_uname_kernel() { #[test] fn test_uname_operating_system() { + #[cfg(target_os = "android")] + new_ucmd!() + .arg("--operating-system") + .succeeds() + .stdout_is("Android\n"); #[cfg(target_vendor = "apple")] new_ucmd!() .arg("--operating-system") diff --git a/tests/by-util/test_wc.rs b/tests/by-util/test_wc.rs index 3537f902d..12ad3003b 100644 --- a/tests/by-util/test_wc.rs +++ b/tests/by-util/test_wc.rs @@ -262,10 +262,10 @@ fn test_read_from_nonexistent_file() { } #[test] -#[cfg(all(unix, not(target_os = "macos")))] +#[cfg(any(target_os = "linux", target_os = "android"))] fn test_files_from_pseudo_filesystem() { - let result = new_ucmd!().arg("-c").arg("/proc/version").succeeds(); - assert_ne!(result.stdout_str(), "0 /proc/version\n"); + let result = new_ucmd!().arg("-c").arg("/proc/cpuinfo").succeeds(); + assert_ne!(result.stdout_str(), "0 /proc/cpuinfo\n"); } #[test] diff --git a/tests/common/util.rs b/tests/common/util.rs index bf7143bb5..dc6aa78e7 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -892,7 +892,7 @@ pub struct UCommand { stdout: Option, stderr: Option, bytes_into_stdin: Option>, - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] limits: Vec<(rlimit::Resource, u64, u64)>, } @@ -938,7 +938,7 @@ impl UCommand { stdin: None, stdout: None, stderr: None, - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] limits: vec![], }; @@ -1042,7 +1042,7 @@ impl UCommand { self } - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "android"))] pub fn with_limit( &mut self, resource: rlimit::Resource, diff --git a/tests/fixtures/install/helloworld_android b/tests/fixtures/install/helloworld_android new file mode 100755 index 000000000..ffb3e6aeb Binary files /dev/null and b/tests/fixtures/install/helloworld_android differ diff --git a/tests/fixtures/install/helloworld_linux b/tests/fixtures/install/helloworld_linux index c1c6b9b37..4f0895df9 100755 Binary files a/tests/fixtures/install/helloworld_linux and b/tests/fixtures/install/helloworld_linux differ