Skip to content

Commit

Permalink
Merge pull request rcore-os#135 from yunwei37/test1
Browse files Browse the repository at this point in the history
Add more time syscalls and fix `touch` command in busybox
  • Loading branch information
wangrunji0408 authored Aug 11, 2020
2 parents adfb987 + 3f311d3 commit a9f9090
Show file tree
Hide file tree
Showing 11 changed files with 420 additions and 49 deletions.
60 changes: 48 additions & 12 deletions linux-loader/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,76 +51,112 @@ fn init_logger() {
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
use zircon_object::object::task::*;

/// test with cmd line
async fn test(cmdline: &str) {
async fn test(cmdline: &str) -> i64 {
kernel_hal_unix::init();

let args: Vec<String> = cmdline.split(' ').map(|s| s.into()).collect();
let envs =
vec!["PATH=/usr/sbin:/usr/bin:/sbin:/bin:/usr/x86_64-alpine-linux-musl/bin".into()]; // TODO
let hostfs = HostFS::new("../rootfs");
let proc = run(args, envs, hostfs);
let proc: Arc<dyn KernelObject> = proc;
proc.wait_signal(Signal::PROCESS_TERMINATED).await;
let procobj: Arc<dyn KernelObject> = proc.clone();
procobj.wait_signal(Signal::PROCESS_TERMINATED).await;
if let Status::Exited(code) = proc.status() {
return code;
}
-1
}

// test using busybox

#[async_std::test]
async fn test_busybox() {
test("/bin/busybox").await;
assert_eq!(test("/bin/busybox").await, 0);
}

#[async_std::test]
async fn test_uname() {
test("/bin/busybox uname -a").await;
assert_eq!(test("/bin/busybox uname -a").await, 0);
}

#[async_std::test]
async fn test_date() {
test("/bin/busybox date").await;
assert_eq!(test("/bin/busybox date").await, 0);
}

#[async_std::test]
async fn test_dir() {
test("/bin/busybox pwd").await;
test("/bin/busybox ls -a").await;
test("/bin/busybox dirname /bin/busybox").await;
assert_eq!(test("/bin/busybox pwd").await, 0);
assert_eq!(test("/bin/busybox ls -a").await, 0);
assert_eq!(test("/bin/busybox dirname /bin/busybox").await, 0);
}

#[async_std::test]
async fn test_create_remove_file() {
test("/bin/busybox rm testfile").await; // can't remove
fs::read("../rootfs/testfile").unwrap_err();
test("/bin/busybox touch testfile").await;
fs::read("../rootfs/testfile").unwrap();
test("/bin/busybox touch testfile").await;
fs::read("../rootfs/testfile").unwrap();
test("/bin/busybox rm testfile").await;
fs::read("../rootfs/testfile").unwrap_err();
}

#[async_std::test]
async fn test_create_remove_dir() {
test("/bin/busybox rmdir test").await; // can't remove
fs::read_dir("../rootfs/test").unwrap_err();
test("/bin/busybox mkdir test").await;
fs::read_dir("../rootfs/test").unwrap();
test("/bin/busybox rmdir test").await;
fs::read_dir("../rootfs/test").unwrap_err();
}

#[async_std::test]
async fn test_readfile() {
test("/bin/busybox cat /etc/profile").await;
assert_eq!(test("/bin/busybox cat /etc/profile").await, 0);
assert_eq!(test("/bin/busybox cat /etc/profila").await, 1); // can't open
}

#[async_std::test]
async fn test_cp_mv() {
test("/bin/busybox cp /etc/hostnama /etc/hostname.bak").await; // can't move
fs::read("../rootfs/etc/hostname.bak").unwrap_err();
test("/bin/busybox cp /etc/hostname /etc/hostname.bak").await;
fs::read("../rootfs/etc/hostname.bak").unwrap();
test("/bin/busybox mv /etc/hostname.bak /etc/hostname.mv").await;
fs::read("../rootfs/etc/hostname.bak").unwrap_err();
}

#[async_std::test]
async fn test_link() {
test("/bin/busybox ln /etc/hostnama /etc/hostname.ln").await; // can't ln
fs::read("../rootfs/etc/hostname.ln").unwrap_err();
test("/bin/busybox ln /etc/hostname /etc/hostname.ln").await;
fs::read("../rootfs/etc/hostname.ln").unwrap();
test("/bin/busybox unlink /etc/hostname.ln").await;
fs::read("../rootfs/etc/hostname.ln").unwrap_err();
}

#[async_std::test]
async fn test_env() {
test("/bin/busybox env").await;
assert_eq!(test("/bin/busybox env").await, 0);
}

// syscall unit test

#[async_std::test]
async fn test_pipe() {
test("/bin/testpipe1").await;
assert_eq!(test("/bin/testpipe1").await, 0);
}

#[async_std::test]
async fn test_time() {
assert_eq!(test("/bin/testtime").await, 0);
}
}
1 change: 1 addition & 0 deletions linux-object/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ description = "Linux kernel objects"
log = "0.4"
spin = "0.5"
xmas-elf = "0.7"
bitflags = "1.2"
hashbrown = "0.7"
zircon-object = { path = "../zircon-object", features = ["elf"] }
kernel-hal = { path = "../kernel-hal" }
Expand Down
44 changes: 44 additions & 0 deletions linux-object/src/fs/fcntl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//! consts for fctnl
//! currently support x86_64 only
//! copy from fcntl.h (from rCore)
#![allow(dead_code)]

use bitflags::bitflags;

const F_LINUX_SPECIFIC_BASE: usize = 1024;

bitflags! {
pub struct FcntlFlags: usize {
/// dup
const F_DUPFD = 0;
/// get close_on_exec
const F_GETFD = 1;
/// set/clear close_on_exec
const F_SETFD = 2;
/// get file->f_flags
const F_GETFL = 3;
/// set file->f_flags
const F_SETFL = 4;
/// Get record locking info.
const F_GETLK = 5;
/// Set record locking info (non-blocking).
const F_SETLK = 6;
/// Set record locking info (blocking).
const F_SETLKW = 7;
/// closed during a successful execve
const FD_CLOEXEC = 1;
/// like F_DUPFD, but additionally set the close-on-exec flag
const F_DUPFD_CLOEXEC = F_LINUX_SPECIFIC_BASE + 6;
}
}

bitflags! {
pub struct FileFlags: usize {
/// not blocking
const O_NONBLOCK = 0o4000;
/// move the flag bit to the end of the file before each write
const O_APPEND = 0o2000;
/// set close_on_exec
const O_CLOEXEC = 0o2000000;
}
}
2 changes: 2 additions & 0 deletions linux-object/src/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use rcore_fs_mountfs::MountFS;
use rcore_fs_ramfs::RamFS;

pub use self::device::*;
pub use self::fcntl::*;
pub use self::file::*;
pub use self::pipe::*;
pub use self::pseudo::*;
Expand All @@ -20,6 +21,7 @@ use downcast_rs::impl_downcast;
use zircon_object::object::*;

mod device;
mod fcntl;
mod file;
mod ioctl;
mod pipe;
Expand Down
3 changes: 3 additions & 0 deletions linux-syscall/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ numeric-enum-macro = "0.2"
zircon-object = { path = "../zircon-object" }
linux-object = { path = "../linux-object" }
kernel-hal = { path = "../kernel-hal" }
rcore-fs = { git = "https://github.com/rcore-os/rcore-fs", rev = "e17b27b" }
lazy_static = { version = "1.4", features = ["spin_no_std"] }

65 changes: 65 additions & 0 deletions linux-syscall/src/file/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
//! - access, faccessat
use super::*;
use crate::time::*;

impl Syscall<'_> {
/// Reads from a specified file using a file descriptor. Before using this call,
Expand Down Expand Up @@ -329,4 +330,68 @@ impl Syscall<'_> {
let _inode = proc.lookup_inode_at(dirfd, &path, follow)?;
Ok(0)
}

/// change file timestamps with nanosecond precision
pub fn sys_utimensat(
&mut self,
dirfd: FileDesc,
pathname: UserInPtr<u8>,
times: UserInOutPtr<[TimeSpec; 2]>,
flags: usize,
) -> SysResult {
info!(
"utimensat(raw): dirfd: {:?}, pathname: {:?}, times: {:?}, flags: {:#x}",
dirfd, pathname, times, flags
);
const UTIME_NOW: usize = 0x3fffffff;
const UTIME_OMIT: usize = 0x3ffffffe;
let proc = self.linux_process();
let mut times = if times.is_null() {
let epoch = TimeSpec::now();
[epoch, epoch]
} else {
let times = times.read()?;
[times[0], times[1]]
};
let inode = if pathname.is_null() {
let fd = dirfd;
info!("futimens: fd: {:?}, times: {:?}", fd, times);
proc.get_file(fd)?.inode()
} else {
let pathname = pathname.read_cstring()?;
info!(
"utimensat: dirfd: {:?}, pathname: {:?}, times: {:?}, flags: {:#x}",
dirfd, pathname, times, flags
);
let follow = if flags == 0 {
true
} else if flags == AtFlags::SYMLINK_NOFOLLOW.bits() {
false
} else {
return Err(LxError::EINVAL);
};
proc.lookup_inode_at(dirfd, &pathname[..], follow)?
};
let mut metadata = inode.metadata()?;
if times[0].nsec != UTIME_OMIT {
if times[0].nsec == UTIME_NOW {
times[0] = TimeSpec::now();
}
metadata.atime = rcore_fs::vfs::Timespec {
sec: times[0].sec as i64,
nsec: times[0].nsec as i32,
};
}
if times[1].nsec != UTIME_OMIT {
if times[1].nsec == UTIME_NOW {
times[1] = TimeSpec::now();
}
metadata.mtime = rcore_fs::vfs::Timespec {
sec: times[1].sec as i64,
nsec: times[1].nsec as i32,
};
}
inode.set_metadata(&metadata)?;
Ok(0)
}
}
10 changes: 5 additions & 5 deletions linux-syscall/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ impl Syscall<'_> {
Sys::FACCESSAT => self.sys_faccessat(a0.into(), a1.into(), a2, a3),
Sys::DUP3 => self.sys_dup2(a0.into(), a1.into()), // TODO: handle `flags`
Sys::PIPE2 => self.sys_pipe(a0.into()), // TODO: handle `flags`
Sys::UTIMENSAT => self.unimplemented("utimensat", Ok(0)),
Sys::UTIMENSAT => self.sys_utimensat(a0.into(), a1.into(), a2.into(), a3),
Sys::COPY_FILE_RANGE => {
self.sys_copy_file_range(a0.into(), a1.into(), a2.into(), a3.into(), a4, a5)
}
Expand Down Expand Up @@ -181,7 +181,7 @@ impl Syscall<'_> {
// time
// Sys::NANOSLEEP => self.sys_nanosleep(a0.into()),
Sys::SETITIMER => self.unimplemented("setitimer", Ok(0)),
// Sys::GETTIMEOFDAY => self.sys_gettimeofday(a0.into(), a1.into()),
Sys::GETTIMEOFDAY => self.sys_gettimeofday(a0.into(), a1.into()),
Sys::CLOCK_GETTIME => self.sys_clock_gettime(a0, a1.into()),

// sem
Expand All @@ -199,9 +199,9 @@ impl Syscall<'_> {
Sys::UMASK => self.unimplemented("umask", Ok(0o777)),
// Sys::GETRLIMIT => self.sys_getrlimit(),
// Sys::SETRLIMIT => self.sys_setrlimit(),
// Sys::GETRUSAGE => self.sys_getrusage(a0, a1.into()),
Sys::GETRUSAGE => self.sys_getrusage(a0, a1.into()),
// Sys::SYSINFO => self.sys_sysinfo(a0.into()),
// Sys::TIMES => self.sys_times(a0.into()),
Sys::TIMES => self.sys_times(a0.into()),
Sys::GETUID => self.unimplemented("getuid", Ok(0)),
Sys::GETGID => self.unimplemented("getgid", Ok(0)),
Sys::SETUID => self.unimplemented("setuid", Ok(0)),
Expand Down Expand Up @@ -260,7 +260,7 @@ impl Syscall<'_> {
// Sys::CHMOD => self.unimplemented("chmod", Ok(0)),
// Sys::CHOWN => self.unimplemented("chown", Ok(0)),
Sys::ARCH_PRCTL => self.sys_arch_prctl(a0 as _, a1),
// Sys::TIME => self.sys_time(a0 as *mut u64),
Sys::TIME => self.sys_time(a0.into()),
// Sys::EPOLL_CREATE => self.sys_epoll_create(a0),
// Sys::EPOLL_WAIT => self.sys_epoll_wait(a0, a1.into(), a2, a3),
_ => self.unknown_syscall(sys_type),
Expand Down
Loading

0 comments on commit a9f9090

Please sign in to comment.