1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-09-15 03:26:18 +00:00

Merge pull request #1165 from ids1024/test_redox

Build 'test' and 'shred' on Redox
This commit is contained in:
Alex Lyon 2018-03-16 21:51:27 -07:00 committed by GitHub
commit 711308d27a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 61 additions and 45 deletions

1
Cargo.lock generated
View file

@ -1499,6 +1499,7 @@ name = "test"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"uucore 0.0.1", "uucore 0.0.1",
] ]

View file

@ -68,10 +68,8 @@ generic = [
"hostname", "hostname",
"more", "more",
"nproc", "nproc",
"shred",
"sync", "sync",
"tail", "tail",
"test",
"whoami", "whoami",
"redox_generic" "redox_generic"
] ]
@ -124,6 +122,7 @@ redox_generic = [
"rm", "rm",
"rmdir", "rmdir",
"seq", "seq",
"shred",
"shuf", "shuf",
"sleep", "sleep",
"sort", "sort",
@ -131,6 +130,7 @@ redox_generic = [
"sum", "sum",
"tac", "tac",
"tee", "tee",
"test",
"tr", "tr",
"true", "true",
"truncate", "truncate",

View file

@ -12,6 +12,9 @@ path = "test.rs"
libc = "0.2.26" libc = "0.2.26"
uucore = { path="../uucore" } uucore = { path="../uucore" }
[target.'cfg(target_os = "redox")'.dependencies]
redox_syscall = "0.1"
[[bin]] [[bin]]
name = "test" name = "test"
path = "../../uumain.rs" path = "../../uumain.rs"

View file

@ -10,6 +10,8 @@
*/ */
extern crate libc; extern crate libc;
#[cfg(target_os = "redox")]
extern crate syscall;
use std::collections::HashMap; use std::collections::HashMap;
use std::ffi::OsString; use std::ffi::OsString;
@ -142,11 +144,15 @@ fn integers(a: &[u8], b: &[u8], cond: IntegerCondition) -> bool {
} }
fn isatty(fd: &[u8]) -> bool { fn isatty(fd: &[u8]) -> bool {
use libc::isatty;
from_utf8(fd) from_utf8(fd)
.ok() .ok()
.and_then(|s| s.parse().ok()) .and_then(|s| s.parse().ok())
.map_or(false, |i| unsafe { isatty(i) == 1 }) .map_or(false, |i| {
#[cfg(not(target_os = "redox"))]
unsafe { libc::isatty(i) == 1 }
#[cfg(target_os = "redox")]
syscall::dup(i, b"termios").map(syscall::close).is_ok()
})
} }
fn dispatch(args: &mut &[&[u8]], error: &mut bool) -> bool { fn dispatch(args: &mut &[&[u8]], error: &mut bool) -> bool {
@ -336,60 +342,66 @@ enum PathCondition {
#[cfg(not(windows))] #[cfg(not(windows))]
fn path(path: &[u8], cond: PathCondition) -> bool { fn path(path: &[u8], cond: PathCondition) -> bool {
use libc::{lstat, stat, S_IFBLK, S_IFCHR, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG}; use std::os::unix::fs::{MetadataExt, FileTypeExt};
use libc::{mode_t, S_IFIFO}; use std::os::unix::ffi::OsStrExt;
use std::ffi::CString; use std::fs::{self, Metadata};
use std::ffi::OsStr;
static S_ISUID: mode_t = 0o4000; let path = OsStr::from_bytes(path);
static S_ISGID: mode_t = 0o2000;
static S_IFSOCK: mode_t = 0o140000; const S_ISUID: u32 = 0o4000;
const S_ISGID: u32 = 0o2000;
enum Permission { enum Permission {
Read = 0o4, Read = 0o4,
Write = 0o2, Write = 0o2,
Execute = 0o1, Execute = 0o1,
} }
let perm = |stat: stat, p: Permission| {
use libc::{getgid, getuid}; let perm = |metadata: Metadata, p: Permission| {
let (uid, gid) = unsafe { (getuid(), getgid()) }; #[cfg(not(target_os = "redox"))]
if uid == stat.st_uid { let (uid, gid) = unsafe { (libc::getuid(), libc::getgid()) };
stat.st_mode & ((p as mode_t) << 6) != 0 #[cfg(target_os = "redox")]
} else if gid == stat.st_gid { let (uid, gid) = (syscall::getuid().unwrap() as u32,
stat.st_mode & ((p as mode_t) << 3) != 0 syscall::getgid().unwrap() as u32);
if uid == metadata.uid() {
metadata.mode() & ((p as u32) << 6) != 0
} else if gid == metadata.gid() {
metadata.mode() & ((p as u32) << 3) != 0
} else { } else {
stat.st_mode & ((p as mode_t)) != 0 metadata.mode() & ((p as u32)) != 0
} }
}; };
let path = CString::new(path).unwrap(); let metadata = if cond == PathCondition::SymLink {
let mut stat = unsafe { std::mem::zeroed() }; fs::symlink_metadata(path)
if cond == PathCondition::SymLink { } else {
if unsafe { lstat(path.as_ptr(), &mut stat) } == 0 { fs::metadata(path)
if stat.st_mode & S_IFMT == S_IFLNK { };
return true;
} let metadata = match metadata {
} Ok(metadata) => metadata,
return false; Err(_) => { return false; }
} };
if unsafe { libc::stat(path.as_ptr(), &mut stat) } != 0 {
return false; let file_type = metadata.file_type();
}
let file_type = stat.st_mode & S_IFMT;
match cond { match cond {
PathCondition::BlockSpecial => file_type == S_IFBLK, PathCondition::BlockSpecial => file_type.is_block_device(),
PathCondition::CharacterSpecial => file_type == S_IFCHR, PathCondition::CharacterSpecial => file_type.is_char_device(),
PathCondition::Directory => file_type == S_IFDIR, PathCondition::Directory => file_type.is_dir(),
PathCondition::Exists => true, PathCondition::Exists => true,
PathCondition::Regular => file_type == S_IFREG, PathCondition::Regular => file_type.is_file(),
PathCondition::GroupIDFlag => stat.st_mode & S_ISGID != 0, PathCondition::GroupIDFlag => metadata.mode() & S_ISGID != 0,
PathCondition::SymLink => true, PathCondition::SymLink => metadata.file_type().is_symlink(),
PathCondition::FIFO => file_type == S_IFIFO, PathCondition::FIFO => file_type.is_fifo(),
PathCondition::Readable => perm(stat, Permission::Read), PathCondition::Readable => perm(metadata, Permission::Read),
PathCondition::Socket => file_type == S_IFSOCK, PathCondition::Socket => file_type.is_socket(),
PathCondition::NonEmpty => stat.st_size > 0, PathCondition::NonEmpty => metadata.size() > 0,
PathCondition::UserIDFlag => stat.st_mode & S_ISUID != 0, PathCondition::UserIDFlag => metadata.mode() & S_ISUID != 0,
PathCondition::Writable => perm(stat, Permission::Write), PathCondition::Writable => perm(metadata, Permission::Write),
PathCondition::Executable => perm(stat, Permission::Execute), PathCondition::Executable => perm(metadata, Permission::Execute),
} }
} }