mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
commit
48a521224e
54 changed files with 523 additions and 203 deletions
55
.github/workflows/CICD.yml
vendored
55
.github/workflows/CICD.yml
vendored
|
@ -844,6 +844,61 @@ jobs:
|
|||
n_fails=$(echo "$output" | grep "^FAIL:\s" | wc --lines)
|
||||
if [ $n_fails -gt 0 ] ; then echo "::warning ::${n_fails}+ test failures" ; fi
|
||||
|
||||
test_android:
|
||||
name: Test Android builds
|
||||
needs: [ min_version, deps ]
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
api-level: [28]
|
||||
target: [default]
|
||||
arch: [x86] # , arm64-v8a
|
||||
env:
|
||||
TERMUX: v0.118.0
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: AVD cache
|
||||
uses: actions/cache@v2
|
||||
id: avd-cache
|
||||
with:
|
||||
path: |
|
||||
~/.android/avd/*
|
||||
~/.android/avd/*/snapshots/*
|
||||
~/.android/adb*
|
||||
key: avd-${{ matrix.api-level }}-${{ matrix.arch }}+termux-${{ env.TERMUX }}
|
||||
- name: Create and cache emulator image
|
||||
if: steps.avd-cache.outputs.cache-hit != 'true'
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
target: ${{ matrix.target }}
|
||||
arch: ${{ matrix.arch }}
|
||||
ram-size: 2048M
|
||||
disk-size: 5120M
|
||||
force-avd-creation: true
|
||||
emulator-options: -no-snapshot-load -noaudio -no-boot-anim -camera-back none
|
||||
script: |
|
||||
wget https://github.com/termux/termux-app/releases/download/${{ env.TERMUX }}/termux-app_${{ env.TERMUX }}+github-debug_${{ matrix.arch }}.apk
|
||||
util/android-commands.sh snapshot termux-app_${{ env.TERMUX }}+github-debug_${{ matrix.arch }}.apk
|
||||
adb -s emulator-5554 emu avd snapshot save ${{ matrix.api-level }}-${{ matrix.arch }}+termux-${{ env.TERMUX }}
|
||||
echo "Emulator image created."
|
||||
pkill -9 qemu-system-x86_64
|
||||
- name: Build and Test on Android
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
target: ${{ matrix.target }}
|
||||
arch: ${{ matrix.arch }}
|
||||
ram-size: 2048M
|
||||
disk-size: 5120M
|
||||
force-avd-creation: false
|
||||
emulator-options: -no-snapshot-save -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -snapshot ${{ matrix.api-level }}-${{ matrix.arch }}+termux-${{ env.TERMUX }}
|
||||
script: |
|
||||
util/android-commands.sh sync
|
||||
util/android-commands.sh build
|
||||
util/android-commands.sh tests
|
||||
|
||||
test_freebsd:
|
||||
name: Tests/FreeBSD test suite
|
||||
needs: [ min_version, deps ]
|
||||
|
|
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -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",
|
||||
|
|
17
Cargo.toml
17
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: <https://musl.libc.org/about.html>)
|
||||
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]
|
||||
|
|
|
@ -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()) }
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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]]
|
||||
|
|
|
@ -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<io::Stdin> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
fn make_linux_iflags(iflags: &IFlags) -> Option<libc::c_int> {
|
||||
let mut flag = 0;
|
||||
|
||||
|
@ -140,7 +140,7 @@ impl Input<File> {
|
|||
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<libc::c_int> {
|
||||
let mut flag = 0;
|
||||
|
||||
|
@ -504,7 +504,7 @@ impl OutputTrait for Output<File> {
|
|||
.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);
|
||||
}
|
||||
|
|
|
@ -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()))
|
||||
|
|
|
@ -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![
|
||||
|
|
|
@ -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);
|
||||
|
@ -508,33 +508,39 @@ fn pline(possible_uid: Option<uid_t>) {
|
|||
println!(
|
||||
"{}:{}:{}:{}:{}:{}:{}:{}:{}:{}",
|
||||
pw.name,
|
||||
pw.user_passwd,
|
||||
pw.user_passwd.unwrap_or_default(),
|
||||
pw.uid,
|
||||
pw.gid,
|
||||
pw.user_access_class,
|
||||
pw.user_access_class.unwrap_or_default(),
|
||||
pw.passwd_change_time,
|
||||
pw.expiration,
|
||||
pw.user_info,
|
||||
pw.user_dir,
|
||||
pw.user_shell
|
||||
pw.user_info.unwrap_or_default(),
|
||||
pw.user_dir.unwrap_or_default(),
|
||||
pw.user_shell.unwrap_or_default()
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
fn pline(possible_uid: Option<uid_t>) {
|
||||
let uid = possible_uid.unwrap_or_else(getuid);
|
||||
let pw = Passwd::locate(uid).unwrap();
|
||||
|
||||
println!(
|
||||
"{}:{}:{}:{}:{}:{}:{}",
|
||||
pw.name, pw.user_passwd, pw.uid, pw.gid, pw.user_info, pw.user_dir, pw.user_shell
|
||||
pw.name,
|
||||
pw.user_passwd.unwrap_or_default(),
|
||||
pw.uid,
|
||||
pw.gid,
|
||||
pw.user_info.unwrap_or_default(),
|
||||
pw.user_dir.unwrap_or_default(),
|
||||
pw.user_shell.unwrap_or_default()
|
||||
);
|
||||
}
|
||||
|
||||
#[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() };
|
||||
|
@ -614,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()
|
||||
|
@ -627,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};
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -245,12 +245,16 @@ fn time_string(ut: &Utmpx) -> String {
|
|||
time::strftime("%b %e %H:%M", &ut.login_time()).unwrap() // LC_ALL=C
|
||||
}
|
||||
|
||||
fn gecos_to_fullname(pw: &Passwd) -> String {
|
||||
let mut gecos = pw.user_info.clone();
|
||||
fn gecos_to_fullname(pw: &Passwd) -> Option<String> {
|
||||
let mut gecos = if let Some(gecos) = &pw.user_info {
|
||||
gecos.clone()
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
if let Some(n) = gecos.find(',') {
|
||||
gecos.truncate(n);
|
||||
}
|
||||
gecos.replace('&', &pw.name.capitalize())
|
||||
Some(gecos.replace('&', &pw.name.capitalize()))
|
||||
}
|
||||
|
||||
impl Pinky {
|
||||
|
@ -278,8 +282,13 @@ impl Pinky {
|
|||
print!("{1:<8.0$}", utmpx::UT_NAMESIZE, ut.user());
|
||||
|
||||
if self.include_fullname {
|
||||
if let Ok(pw) = Passwd::locate(ut.user().as_ref()) {
|
||||
print!(" {:<19.19}", gecos_to_fullname(&pw));
|
||||
let fullname = if let Ok(pw) = Passwd::locate(ut.user().as_ref()) {
|
||||
gecos_to_fullname(&pw)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(fullname) = fullname {
|
||||
print!(" {:<19.19}", fullname);
|
||||
} else {
|
||||
print!(" {:19}", " ???");
|
||||
}
|
||||
|
@ -341,13 +350,16 @@ impl Pinky {
|
|||
for u in &self.names {
|
||||
print!("Login name: {:<28}In real life: ", u);
|
||||
if let Ok(pw) = Passwd::locate(u.as_str()) {
|
||||
println!(" {}", gecos_to_fullname(&pw));
|
||||
let fullname = gecos_to_fullname(&pw).unwrap_or_default();
|
||||
let user_dir = pw.user_dir.unwrap_or_default();
|
||||
let user_shell = pw.user_shell.unwrap_or_default();
|
||||
println!(" {}", fullname);
|
||||
if self.include_home_and_shell {
|
||||
print!("Directory: {:<29}", pw.user_dir);
|
||||
println!("Shell: {}", pw.user_shell);
|
||||
print!("Directory: {:<29}", user_dir);
|
||||
println!("Shell: {}", user_shell);
|
||||
}
|
||||
if self.include_project {
|
||||
let mut p = PathBuf::from(&pw.user_dir);
|
||||
let mut p = PathBuf::from(&user_dir);
|
||||
p.push(".project");
|
||||
if let Ok(f) = File::open(p) {
|
||||
print!("Project: ");
|
||||
|
@ -355,7 +367,7 @@ impl Pinky {
|
|||
}
|
||||
}
|
||||
if self.include_plan {
|
||||
let mut p = PathBuf::from(&pw.user_dir);
|
||||
let mut p = PathBuf::from(&user_dir);
|
||||
p.push(".plan");
|
||||
if let Ok(f) = File::open(p) {
|
||||
println!("Plan:");
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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<String>) -> 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<String>) -> 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<String>) -> isize {
|
||||
unsafe { platform::do_syncfs(files) }
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
fn fdatasync(files: Vec<String>) -> isize {
|
||||
unsafe { platform::do_fdatasync(files) }
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ pub fn stdin_is_pipe_or_fifo() -> bool {
|
|||
fd >= 0 // GNU tail checks fd >= 0
|
||||
&& match fstat(fd) {
|
||||
Ok(stat) => {
|
||||
let mode = stat.st_mode;
|
||||
let mode = stat.st_mode as libc::mode_t;
|
||||
// NOTE: This is probably not the most correct way to check this
|
||||
(mode & S_IFIFO != 0) || (mode & S_IFSOCK != 0)
|
||||
}
|
||||
|
|
|
@ -320,10 +320,14 @@ fn parse_timestamp(s: &str) -> UResult<FileTime> {
|
|||
/// On Windows, uses GetFinalPathNameByHandleW to attempt to get the path
|
||||
/// from the stdout handle.
|
||||
fn pathbuf_from_stdout() -> UResult<PathBuf> {
|
||||
#[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;
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -36,8 +36,8 @@ fn count_bytes_using_splice(fd: &impl AsRawFd) -> Result<usize, usize> {
|
|||
.map_err(|_| 0_usize)?;
|
||||
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) {
|
||||
.st_rdev as libc::dev_t;
|
||||
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);
|
||||
|
@ -86,14 +86,14 @@ pub(crate) fn count_bytes_fast<T: WordCountable>(handle: &mut T) -> (usize, Opti
|
|||
// The second case happens for files in pseudo-filesystems. For
|
||||
// example with /proc/version and /sys/kernel/profiling. So,
|
||||
// if it is 0 we don't report that and instead do a full read.
|
||||
if (stat.st_mode & S_IFREG) != 0 && stat.st_size > 0 {
|
||||
if (stat.st_mode as libc::mode_t & S_IFREG) != 0 && stat.st_size > 0 {
|
||||
return (stat.st_size as usize, None);
|
||||
}
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
{
|
||||
// Else, if we're on Linux and our file is a FIFO pipe
|
||||
// (or stdin), we use splice to count the number of bytes.
|
||||
if (stat.st_mode & S_IFIFO) != 0 {
|
||||
if (stat.st_mode as libc::mode_t & S_IFIFO) != 0 {
|
||||
match count_bytes_using_splice(handle) {
|
||||
Ok(n) => return (n, None),
|
||||
Err(n) => byte_count = n,
|
||||
|
|
|
@ -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)";
|
||||
|
|
|
@ -23,7 +23,7 @@ use nix::{errno::Errno, libc::S_IFIFO, sys::stat::fstat};
|
|||
use uucore::pipes::{pipe, splice_exact, vmsplice};
|
||||
|
||||
pub(crate) fn splice_data(bytes: &[u8], out: &impl AsRawFd) -> Result<()> {
|
||||
let is_pipe = fstat(out.as_raw_fd())?.st_mode & S_IFIFO != 0;
|
||||
let is_pipe = fstat(out.as_raw_fd())?.st_mode as nix::libc::mode_t & S_IFIFO != 0;
|
||||
|
||||
if is_pipe {
|
||||
loop {
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -147,16 +147,16 @@ pub struct Passwd {
|
|||
/// AKA passwd.pw_gid
|
||||
pub gid: gid_t,
|
||||
/// AKA passwd.pw_gecos
|
||||
pub user_info: String,
|
||||
pub user_info: Option<String>,
|
||||
/// AKA passwd.pw_shell
|
||||
pub user_shell: String,
|
||||
pub user_shell: Option<String>,
|
||||
/// AKA passwd.pw_dir
|
||||
pub user_dir: String,
|
||||
pub user_dir: Option<String>,
|
||||
/// AKA passwd.pw_passwd
|
||||
pub user_passwd: String,
|
||||
pub user_passwd: Option<String>,
|
||||
/// AKA passwd.pw_class
|
||||
#[cfg(any(target_os = "freebsd", target_vendor = "apple"))]
|
||||
pub user_access_class: String,
|
||||
pub user_access_class: Option<String>,
|
||||
/// AKA passwd.pw_change
|
||||
#[cfg(any(target_os = "freebsd", target_vendor = "apple"))]
|
||||
pub passwd_change_time: time_t,
|
||||
|
@ -166,8 +166,13 @@ pub struct Passwd {
|
|||
}
|
||||
|
||||
/// SAFETY: ptr must point to a valid C string.
|
||||
unsafe fn cstr2string(ptr: *const c_char) -> String {
|
||||
CStr::from_ptr(ptr).to_string_lossy().into_owned()
|
||||
/// Returns None if ptr is null.
|
||||
unsafe fn cstr2string(ptr: *const c_char) -> Option<String> {
|
||||
if !ptr.is_null() {
|
||||
Some(CStr::from_ptr(ptr).to_string_lossy().into_owned())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Passwd {
|
||||
|
@ -175,10 +180,16 @@ impl Passwd {
|
|||
/// the function runs. That means PW_LOCK must be held.
|
||||
unsafe fn from_raw(raw: passwd) -> Self {
|
||||
Self {
|
||||
name: cstr2string(raw.pw_name),
|
||||
name: cstr2string(raw.pw_name).expect("passwd without name"),
|
||||
uid: raw.pw_uid,
|
||||
gid: raw.pw_gid,
|
||||
#[cfg(not(all(
|
||||
target_os = "android",
|
||||
any(target_arch = "x86", target_arch = "arm")
|
||||
)))]
|
||||
user_info: cstr2string(raw.pw_gecos),
|
||||
#[cfg(all(target_os = "android", any(target_arch = "x86", target_arch = "arm")))]
|
||||
user_info: None,
|
||||
user_shell: cstr2string(raw.pw_shell),
|
||||
user_dir: cstr2string(raw.pw_dir),
|
||||
user_passwd: cstr2string(raw.pw_passwd),
|
||||
|
@ -243,7 +254,7 @@ impl Group {
|
|||
/// the function runs. That means PW_LOCK must be held.
|
||||
unsafe fn from_raw(raw: group) -> Self {
|
||||
Self {
|
||||
name: cstr2string(raw.gr_name),
|
||||
name: cstr2string(raw.gr_name).expect("group without name"),
|
||||
gid: raw.gr_gid,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Self> {
|
||||
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<MountInfo> {
|
||||
#[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(
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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': ",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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!();
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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!()
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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!();
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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!();
|
||||
|
||||
|
|
|
@ -24,11 +24,14 @@ fn test_capitalize() {
|
|||
fn test_long_format() {
|
||||
let login = "root";
|
||||
let pw: Passwd = Passwd::locate(login).unwrap();
|
||||
let real_name = pw.user_info.replace('&', &pw.name.capitalize());
|
||||
let user_info = pw.user_info.unwrap_or_default();
|
||||
let user_dir = pw.user_dir.unwrap_or_default();
|
||||
let user_shell = pw.user_shell.unwrap_or_default();
|
||||
let real_name = user_info.replace('&', &pw.name.capitalize());
|
||||
let ts = TestScenario::new(util_name!());
|
||||
ts.ucmd().arg("-l").arg(login).succeeds().stdout_is(format!(
|
||||
"Login name: {:<28}In real life: {}\nDirectory: {:<29}Shell: {}\n\n",
|
||||
login, real_name, pw.user_dir, pw.user_shell
|
||||
login, real_name, user_dir, user_shell
|
||||
));
|
||||
|
||||
ts.ucmd()
|
||||
|
|
|
@ -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(&[
|
||||
|
|
|
@ -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!());
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -670,7 +670,7 @@ impl AtPath {
|
|||
let name = CString::new(self.plus_as_string(fifo)).unwrap();
|
||||
let mut stat: libc::stat = std::mem::zeroed();
|
||||
if libc::stat(name.as_ptr(), &mut stat) >= 0 {
|
||||
libc::S_IFIFO & stat.st_mode != 0
|
||||
libc::S_IFIFO & stat.st_mode as libc::mode_t != 0
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
@ -892,7 +892,7 @@ pub struct UCommand {
|
|||
stdout: Option<Stdio>,
|
||||
stderr: Option<Stdio>,
|
||||
bytes_into_stdin: Option<Vec<u8>>,
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
limits: Vec<(rlimit::Resource, u64, u64)>,
|
||||
}
|
||||
|
||||
|
@ -913,19 +913,21 @@ impl UCommand {
|
|||
let mut cmd = Command::new(bin_path);
|
||||
cmd.current_dir(curdir.as_ref());
|
||||
if env_clear {
|
||||
cmd.env_clear();
|
||||
if cfg!(windows) {
|
||||
// spell-checker:ignore (dll) rsaenh
|
||||
// %SYSTEMROOT% is required on Windows to initialize crypto provider
|
||||
// ... and crypto provider is required for std::rand
|
||||
// From `procmon`: RegQueryValue HKLM\SOFTWARE\Microsoft\Cryptography\Defaults\Provider\Microsoft Strong Cryptographic Provider\Image Path
|
||||
// SUCCESS Type: REG_SZ, Length: 66, Data: %SystemRoot%\system32\rsaenh.dll"
|
||||
for (key, _) in env::vars_os() {
|
||||
if key.as_os_str() != "SYSTEMROOT" {
|
||||
cmd.env_remove(key);
|
||||
}
|
||||
if let Some(systemroot) = env::var_os("SYSTEMROOT") {
|
||||
cmd.env("SYSTEMROOT", systemroot);
|
||||
}
|
||||
} else {
|
||||
cmd.env_clear();
|
||||
// if someone is setting LD_PRELOAD, there's probably a good reason for it
|
||||
if let Some(ld_preload) = env::var_os("LD_PRELOAD") {
|
||||
cmd.env("LD_PRELOAD", ld_preload);
|
||||
}
|
||||
}
|
||||
}
|
||||
cmd
|
||||
|
@ -938,7 +940,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 +1044,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,
|
||||
|
|
BIN
tests/fixtures/install/helloworld_android
vendored
Executable file
BIN
tests/fixtures/install/helloworld_android
vendored
Executable file
Binary file not shown.
BIN
tests/fixtures/install/helloworld_linux
vendored
BIN
tests/fixtures/install/helloworld_linux
vendored
Binary file not shown.
152
util/android-commands.sh
Executable file
152
util/android-commands.sh
Executable file
|
@ -0,0 +1,152 @@
|
|||
# spell-checker:ignore termux keyevent sdcard binutils unmatch adb's dumpsys logcat pkill
|
||||
|
||||
# There are three shells: the host's, adb, and termux. Only adb lets us run
|
||||
# commands directly on the emulated device, only termux provides a GNU
|
||||
# environment on the emulated device (to e.g. run cargo). So we use adb to
|
||||
# launch termux, then to send keystrokes to it while it's running.
|
||||
# This means that the commands sent to termux are first parsed as arguments in
|
||||
# this shell, then as arguments in the adb shell, before finally being used as
|
||||
# text inputs to the app. Hence, the "'wrapping'" on those commands.
|
||||
# There's no way to get any feedback from termux, so every time we run a
|
||||
# command on it, we make sure it ends by creating a unique *.probe file at the
|
||||
# end of the command. The contents of the file are used as a return code: 0 on
|
||||
# success, some other number for errors (an empty file is basically the same as
|
||||
# 0). Note that the return codes are text, not raw bytes.
|
||||
|
||||
|
||||
this_repo="$(dirname $(dirname -- "$(readlink -- "${0}")"))"
|
||||
|
||||
help () {
|
||||
echo \
|
||||
"Usage: $0 COMMAND [ARG]
|
||||
|
||||
where COMMAND is one of:
|
||||
snapshot APK install APK and dependencies on an emulator to prep a snapshot
|
||||
(you can, but probably don't want to, run this for physical
|
||||
devices -- just set up termux and the dependencies yourself)
|
||||
sync [REPO] push the repo at REPO to the device, deleting and restoring all
|
||||
symlinks (locally) in the process; by default, REPO is:
|
||||
$this_repo
|
||||
build run \`cargo build --features feat_os_unix_android\` on the
|
||||
device, then pull the output as build.log
|
||||
tests run \`cargo test --features feat_os_unix_android\` on the
|
||||
device, then pull the output as tests.log
|
||||
|
||||
If you have multiple devices, use the ANDROID_SERIAL environment variable to
|
||||
specify which to connect to."
|
||||
}
|
||||
|
||||
hit_enter() {
|
||||
adb shell input keyevent 66
|
||||
}
|
||||
|
||||
launch_termux() {
|
||||
echo "launching termux"
|
||||
if ! adb shell 'am start -n com.termux/.HomeActivity' ; then
|
||||
echo "failed to launch termux"
|
||||
exit 1
|
||||
fi
|
||||
# the emulator can sometimes be a little slow to launch the app
|
||||
while ! adb shell 'ls /sdcard/launch.probe' 2>/dev/null; do
|
||||
echo "waiting for launch.probe"
|
||||
sleep 5
|
||||
adb shell input text 'touch\ /sdcard/launch.probe' && hit_enter
|
||||
done
|
||||
echo "found launch.probe"
|
||||
adb shell 'rm /sdcard/launch.probe' && echo "removed launch.probe"
|
||||
}
|
||||
|
||||
run_termux_command() {
|
||||
command="$1" # text of the escaped command, including creating the probe!
|
||||
probe="$2" # unique file that indicates the command is complete
|
||||
launch_termux
|
||||
adb shell input text "$command" && hit_enter
|
||||
while ! adb shell "ls $probe" 2>/dev/null; do echo "waiting for $probe"; sleep 30; done
|
||||
return_code=$(adb shell "cat $probe")
|
||||
adb shell "rm $probe"
|
||||
echo "return code: $return_code"
|
||||
return $return_code
|
||||
}
|
||||
|
||||
snapshot () {
|
||||
apk="$1"
|
||||
echo "running snapshot"
|
||||
adb install -g "$apk"
|
||||
probe='/sdcard/pkg.probe'
|
||||
command="'yes | pkg install rust binutils openssl -y; touch $probe'"
|
||||
run_termux_command "$command" "$probe"
|
||||
echo "snapshot complete"
|
||||
adb shell input text "exit" && hit_enter && hit_enter
|
||||
}
|
||||
|
||||
sync () {
|
||||
repo="$1"
|
||||
echo "running sync $1"
|
||||
# android doesn't allow symlinks on shared dirs, and adb can't selectively push files
|
||||
symlinks=$(find "$repo" -type l)
|
||||
# dash doesn't support process substitution :(
|
||||
echo $symlinks | sort >symlinks
|
||||
git -C "$repo" diff --name-status | cut -f 2 >modified
|
||||
modified_links=$(join symlinks modified)
|
||||
if [ ! -z "$modified_links" ]; then
|
||||
echo "You have modified symlinks. Either stash or commit them, then try again: $modified_links"
|
||||
exit 1
|
||||
fi
|
||||
if ! git ls-files --error-unmatch $symlinks >/dev/null; then
|
||||
echo "You have untracked symlinks. Either remove or commit them, then try again."
|
||||
exit 1
|
||||
fi
|
||||
rm $symlinks
|
||||
# adb's shell user only has access to shared dirs...
|
||||
adb push "$repo" /sdcard/coreutils
|
||||
git -C "$repo" checkout $symlinks
|
||||
# ...but shared dirs can't build, so move it home as termux
|
||||
probe='/sdcard/mv.probe'
|
||||
command="'cp -r /sdcard/coreutils ~/; touch $probe'"
|
||||
run_termux_command "$command" "$probe"
|
||||
}
|
||||
|
||||
build () {
|
||||
probe='/sdcard/build.probe'
|
||||
command="'cd ~/coreutils && cargo build --features feat_os_unix_android 2>/sdcard/build.log; echo \$? >$probe'"
|
||||
echo "running build"
|
||||
run_termux_command "$command" "$probe"
|
||||
return_code=$?
|
||||
adb pull /sdcard/build.log .
|
||||
cat build.log
|
||||
return $return_code
|
||||
}
|
||||
|
||||
tests () {
|
||||
probe='/sdcard/tests.probe'
|
||||
command="'cd ~/coreutils && cargo test --features feat_os_unix_android --no-fail-fast >/sdcard/tests.log 2>&1; echo \$? >$probe'"
|
||||
run_termux_command "$command" "$probe"
|
||||
return_code=$?
|
||||
adb pull /sdcard/tests.log .
|
||||
cat tests.log
|
||||
return $return_code
|
||||
}
|
||||
|
||||
#adb logcat &
|
||||
exit_code=0
|
||||
|
||||
if [ $# -eq 1 ]; then
|
||||
case "$1" in
|
||||
sync) sync "$this_repo"; exit_code=$?;;
|
||||
build) build; exit_code=$?;;
|
||||
tests) tests; exit_code=$?;;
|
||||
*) help;;
|
||||
esac
|
||||
elif [ $# -eq 2 ]; then
|
||||
case "$1" in
|
||||
snapshot) snapshot "$2"; exit_code=$?;;
|
||||
sync) sync "$2"; exit_code=$?;;
|
||||
*) help; exit 1;;
|
||||
esac
|
||||
else
|
||||
help
|
||||
exit_code=1
|
||||
fi
|
||||
|
||||
#pkill adb
|
||||
exit $exit_code
|
Loading…
Add table
Add a link
Reference in a new issue