Skip to content

Commit 01c671d

Browse files
Merge pull request #135 from yunwei37/test1
Add more time syscalls and fix `touch` command in busybox
2 parents f264052 + 9eaa3dc commit 01c671d

File tree

11 files changed

+420
-49
lines changed

11 files changed

+420
-49
lines changed

linux-loader/src/main.rs

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,76 +51,112 @@ fn init_logger() {
5151
#[cfg(test)]
5252
mod tests {
5353
use super::*;
54+
use std::fs;
55+
use zircon_object::object::task::*;
5456

5557
/// test with cmd line
56-
async fn test(cmdline: &str) {
58+
async fn test(cmdline: &str) -> i64 {
5759
kernel_hal_unix::init();
5860

5961
let args: Vec<String> = cmdline.split(' ').map(|s| s.into()).collect();
6062
let envs =
6163
vec!["PATH=/usr/sbin:/usr/bin:/sbin:/bin:/usr/x86_64-alpine-linux-musl/bin".into()]; // TODO
6264
let hostfs = HostFS::new("../rootfs");
6365
let proc = run(args, envs, hostfs);
64-
let proc: Arc<dyn KernelObject> = proc;
65-
proc.wait_signal(Signal::PROCESS_TERMINATED).await;
66+
let procobj: Arc<dyn KernelObject> = proc.clone();
67+
procobj.wait_signal(Signal::PROCESS_TERMINATED).await;
68+
if let Status::Exited(code) = proc.status() {
69+
return code;
70+
}
71+
-1
6672
}
6773

6874
// test using busybox
6975

7076
#[async_std::test]
7177
async fn test_busybox() {
72-
test("/bin/busybox").await;
78+
assert_eq!(test("/bin/busybox").await, 0);
7379
}
7480

7581
#[async_std::test]
7682
async fn test_uname() {
77-
test("/bin/busybox uname -a").await;
83+
assert_eq!(test("/bin/busybox uname -a").await, 0);
7884
}
7985

8086
#[async_std::test]
8187
async fn test_date() {
82-
test("/bin/busybox date").await;
88+
assert_eq!(test("/bin/busybox date").await, 0);
8389
}
8490

8591
#[async_std::test]
8692
async fn test_dir() {
87-
test("/bin/busybox pwd").await;
88-
test("/bin/busybox ls -a").await;
89-
test("/bin/busybox dirname /bin/busybox").await;
93+
assert_eq!(test("/bin/busybox pwd").await, 0);
94+
assert_eq!(test("/bin/busybox ls -a").await, 0);
95+
assert_eq!(test("/bin/busybox dirname /bin/busybox").await, 0);
96+
}
97+
98+
#[async_std::test]
99+
async fn test_create_remove_file() {
100+
test("/bin/busybox rm testfile").await; // can't remove
101+
fs::read("../rootfs/testfile").unwrap_err();
102+
test("/bin/busybox touch testfile").await;
103+
fs::read("../rootfs/testfile").unwrap();
104+
test("/bin/busybox touch testfile").await;
105+
fs::read("../rootfs/testfile").unwrap();
106+
test("/bin/busybox rm testfile").await;
107+
fs::read("../rootfs/testfile").unwrap_err();
90108
}
91109

92110
#[async_std::test]
93111
async fn test_create_remove_dir() {
112+
test("/bin/busybox rmdir test").await; // can't remove
113+
fs::read_dir("../rootfs/test").unwrap_err();
94114
test("/bin/busybox mkdir test").await;
115+
fs::read_dir("../rootfs/test").unwrap();
95116
test("/bin/busybox rmdir test").await;
117+
fs::read_dir("../rootfs/test").unwrap_err();
96118
}
97119

98120
#[async_std::test]
99121
async fn test_readfile() {
100-
test("/bin/busybox cat /etc/profile").await;
122+
assert_eq!(test("/bin/busybox cat /etc/profile").await, 0);
123+
assert_eq!(test("/bin/busybox cat /etc/profila").await, 1); // can't open
101124
}
102125

103126
#[async_std::test]
104127
async fn test_cp_mv() {
128+
test("/bin/busybox cp /etc/hostnama /etc/hostname.bak").await; // can't move
129+
fs::read("../rootfs/etc/hostname.bak").unwrap_err();
105130
test("/bin/busybox cp /etc/hostname /etc/hostname.bak").await;
131+
fs::read("../rootfs/etc/hostname.bak").unwrap();
106132
test("/bin/busybox mv /etc/hostname.bak /etc/hostname.mv").await;
133+
fs::read("../rootfs/etc/hostname.bak").unwrap_err();
107134
}
108135

109136
#[async_std::test]
110137
async fn test_link() {
138+
test("/bin/busybox ln /etc/hostnama /etc/hostname.ln").await; // can't ln
139+
fs::read("../rootfs/etc/hostname.ln").unwrap_err();
111140
test("/bin/busybox ln /etc/hostname /etc/hostname.ln").await;
141+
fs::read("../rootfs/etc/hostname.ln").unwrap();
112142
test("/bin/busybox unlink /etc/hostname.ln").await;
143+
fs::read("../rootfs/etc/hostname.ln").unwrap_err();
113144
}
114145

115146
#[async_std::test]
116147
async fn test_env() {
117-
test("/bin/busybox env").await;
148+
assert_eq!(test("/bin/busybox env").await, 0);
118149
}
119150

120151
// syscall unit test
121152

122153
#[async_std::test]
123154
async fn test_pipe() {
124-
test("/bin/testpipe1").await;
155+
assert_eq!(test("/bin/testpipe1").await, 0);
156+
}
157+
158+
#[async_std::test]
159+
async fn test_time() {
160+
assert_eq!(test("/bin/testtime").await, 0);
125161
}
126162
}

linux-object/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ description = "Linux kernel objects"
1111
log = "0.4"
1212
spin = "0.5"
1313
xmas-elf = "0.7"
14+
bitflags = "1.2"
1415
hashbrown = "0.7"
1516
zircon-object = { path = "../zircon-object", features = ["elf"] }
1617
kernel-hal = { path = "../kernel-hal" }

linux-object/src/fs/fcntl.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//! consts for fctnl
2+
//! currently support x86_64 only
3+
//! copy from fcntl.h (from rCore)
4+
#![allow(dead_code)]
5+
6+
use bitflags::bitflags;
7+
8+
const F_LINUX_SPECIFIC_BASE: usize = 1024;
9+
10+
bitflags! {
11+
pub struct FcntlFlags: usize {
12+
/// dup
13+
const F_DUPFD = 0;
14+
/// get close_on_exec
15+
const F_GETFD = 1;
16+
/// set/clear close_on_exec
17+
const F_SETFD = 2;
18+
/// get file->f_flags
19+
const F_GETFL = 3;
20+
/// set file->f_flags
21+
const F_SETFL = 4;
22+
/// Get record locking info.
23+
const F_GETLK = 5;
24+
/// Set record locking info (non-blocking).
25+
const F_SETLK = 6;
26+
/// Set record locking info (blocking).
27+
const F_SETLKW = 7;
28+
/// closed during a successful execve
29+
const FD_CLOEXEC = 1;
30+
/// like F_DUPFD, but additionally set the close-on-exec flag
31+
const F_DUPFD_CLOEXEC = F_LINUX_SPECIFIC_BASE + 6;
32+
}
33+
}
34+
35+
bitflags! {
36+
pub struct FileFlags: usize {
37+
/// not blocking
38+
const O_NONBLOCK = 0o4000;
39+
/// move the flag bit to the end of the file before each write
40+
const O_APPEND = 0o2000;
41+
/// set close_on_exec
42+
const O_CLOEXEC = 0o2000000;
43+
}
44+
}

linux-object/src/fs/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rcore_fs_mountfs::MountFS;
66
use rcore_fs_ramfs::RamFS;
77

88
pub use self::device::*;
9+
pub use self::fcntl::*;
910
pub use self::file::*;
1011
pub use self::pipe::*;
1112
pub use self::pseudo::*;
@@ -20,6 +21,7 @@ use downcast_rs::impl_downcast;
2021
use zircon_object::object::*;
2122

2223
mod device;
24+
mod fcntl;
2325
mod file;
2426
mod ioctl;
2527
mod pipe;

linux-syscall/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,6 @@ numeric-enum-macro = "0.2"
1515
zircon-object = { path = "../zircon-object" }
1616
linux-object = { path = "../linux-object" }
1717
kernel-hal = { path = "../kernel-hal" }
18+
rcore-fs = { git = "https://github.com/rcore-os/rcore-fs", rev = "e17b27b" }
19+
lazy_static = { version = "1.4", features = ["spin_no_std"] }
20+

linux-syscall/src/file/file.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//! - access, faccessat
1111
1212
use super::*;
13+
use crate::time::*;
1314

1415
impl Syscall<'_> {
1516
/// Reads from a specified file using a file descriptor. Before using this call,
@@ -329,4 +330,68 @@ impl Syscall<'_> {
329330
let _inode = proc.lookup_inode_at(dirfd, &path, follow)?;
330331
Ok(0)
331332
}
333+
334+
/// change file timestamps with nanosecond precision
335+
pub fn sys_utimensat(
336+
&mut self,
337+
dirfd: FileDesc,
338+
pathname: UserInPtr<u8>,
339+
times: UserInOutPtr<[TimeSpec; 2]>,
340+
flags: usize,
341+
) -> SysResult {
342+
info!(
343+
"utimensat(raw): dirfd: {:?}, pathname: {:?}, times: {:?}, flags: {:#x}",
344+
dirfd, pathname, times, flags
345+
);
346+
const UTIME_NOW: usize = 0x3fffffff;
347+
const UTIME_OMIT: usize = 0x3ffffffe;
348+
let proc = self.linux_process();
349+
let mut times = if times.is_null() {
350+
let epoch = TimeSpec::now();
351+
[epoch, epoch]
352+
} else {
353+
let times = times.read()?;
354+
[times[0], times[1]]
355+
};
356+
let inode = if pathname.is_null() {
357+
let fd = dirfd;
358+
info!("futimens: fd: {:?}, times: {:?}", fd, times);
359+
proc.get_file(fd)?.inode()
360+
} else {
361+
let pathname = pathname.read_cstring()?;
362+
info!(
363+
"utimensat: dirfd: {:?}, pathname: {:?}, times: {:?}, flags: {:#x}",
364+
dirfd, pathname, times, flags
365+
);
366+
let follow = if flags == 0 {
367+
true
368+
} else if flags == AtFlags::SYMLINK_NOFOLLOW.bits() {
369+
false
370+
} else {
371+
return Err(LxError::EINVAL);
372+
};
373+
proc.lookup_inode_at(dirfd, &pathname[..], follow)?
374+
};
375+
let mut metadata = inode.metadata()?;
376+
if times[0].nsec != UTIME_OMIT {
377+
if times[0].nsec == UTIME_NOW {
378+
times[0] = TimeSpec::now();
379+
}
380+
metadata.atime = rcore_fs::vfs::Timespec {
381+
sec: times[0].sec as i64,
382+
nsec: times[0].nsec as i32,
383+
};
384+
}
385+
if times[1].nsec != UTIME_OMIT {
386+
if times[1].nsec == UTIME_NOW {
387+
times[1] = TimeSpec::now();
388+
}
389+
metadata.mtime = rcore_fs::vfs::Timespec {
390+
sec: times[1].sec as i64,
391+
nsec: times[1].nsec as i32,
392+
};
393+
}
394+
inode.set_metadata(&metadata)?;
395+
Ok(0)
396+
}
332397
}

linux-syscall/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ impl Syscall<'_> {
113113
Sys::FACCESSAT => self.sys_faccessat(a0.into(), a1.into(), a2, a3),
114114
Sys::DUP3 => self.sys_dup2(a0.into(), a1.into()), // TODO: handle `flags`
115115
Sys::PIPE2 => self.sys_pipe(a0.into()), // TODO: handle `flags`
116-
Sys::UTIMENSAT => self.unimplemented("utimensat", Ok(0)),
116+
Sys::UTIMENSAT => self.sys_utimensat(a0.into(), a1.into(), a2.into(), a3),
117117
Sys::COPY_FILE_RANGE => {
118118
self.sys_copy_file_range(a0.into(), a1.into(), a2.into(), a3.into(), a4, a5)
119119
}
@@ -181,7 +181,7 @@ impl Syscall<'_> {
181181
// time
182182
// Sys::NANOSLEEP => self.sys_nanosleep(a0.into()),
183183
Sys::SETITIMER => self.unimplemented("setitimer", Ok(0)),
184-
// Sys::GETTIMEOFDAY => self.sys_gettimeofday(a0.into(), a1.into()),
184+
Sys::GETTIMEOFDAY => self.sys_gettimeofday(a0.into(), a1.into()),
185185
Sys::CLOCK_GETTIME => self.sys_clock_gettime(a0, a1.into()),
186186

187187
// sem
@@ -199,9 +199,9 @@ impl Syscall<'_> {
199199
Sys::UMASK => self.unimplemented("umask", Ok(0o777)),
200200
// Sys::GETRLIMIT => self.sys_getrlimit(),
201201
// Sys::SETRLIMIT => self.sys_setrlimit(),
202-
// Sys::GETRUSAGE => self.sys_getrusage(a0, a1.into()),
202+
Sys::GETRUSAGE => self.sys_getrusage(a0, a1.into()),
203203
// Sys::SYSINFO => self.sys_sysinfo(a0.into()),
204-
// Sys::TIMES => self.sys_times(a0.into()),
204+
Sys::TIMES => self.sys_times(a0.into()),
205205
Sys::GETUID => self.unimplemented("getuid", Ok(0)),
206206
Sys::GETGID => self.unimplemented("getgid", Ok(0)),
207207
Sys::SETUID => self.unimplemented("setuid", Ok(0)),
@@ -260,7 +260,7 @@ impl Syscall<'_> {
260260
// Sys::CHMOD => self.unimplemented("chmod", Ok(0)),
261261
// Sys::CHOWN => self.unimplemented("chown", Ok(0)),
262262
Sys::ARCH_PRCTL => self.sys_arch_prctl(a0 as _, a1),
263-
// Sys::TIME => self.sys_time(a0 as *mut u64),
263+
Sys::TIME => self.sys_time(a0.into()),
264264
// Sys::EPOLL_CREATE => self.sys_epoll_create(a0),
265265
// Sys::EPOLL_WAIT => self.sys_epoll_wait(a0, a1.into(), a2, a3),
266266
_ => self.unknown_syscall(sys_type),

0 commit comments

Comments
 (0)