Skip to content

Commit

Permalink
Merge pull request #142 from yunwei37/master
Browse files Browse the repository at this point in the history
Improve doc in `linux-object` and migrate some simple syscalls
  • Loading branch information
wangrunji0408 authored Aug 12, 2020
2 parents a0cc7dd + fe92881 commit 37e7ae1
Show file tree
Hide file tree
Showing 21 changed files with 275 additions and 16 deletions.
24 changes: 23 additions & 1 deletion linux-loader/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@ mod tests {
}

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

#[async_std::test]
Expand Down Expand Up @@ -148,6 +149,22 @@ mod tests {
assert_eq!(test("/bin/busybox env").await, 0);
}

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

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

#[async_std::test]
async fn test_truncate() {
assert_eq!(test("/bin/busybox truncate -s 12 testtruncate").await, 0);
fs::read("../rootfs/testtruncate").unwrap();
}

// syscall unit test

#[async_std::test]
Expand All @@ -159,4 +176,9 @@ mod tests {
async fn test_time() {
assert_eq!(test("/bin/testtime").await, 0);
}

#[async_std::test]
async fn test_random() {
assert_eq!(test("/bin/testrandom").await, 0);
}
}
55 changes: 54 additions & 1 deletion linux-object/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,62 +1,115 @@
//! Linux error codes
use core::fmt;
use rcore_fs::vfs::FsError;
use zircon_object::ZxError;

/// Linux Result defination
pub type LxResult<T = ()> = Result<T, LxError>;
/// SysResult Result defination (same as Linux Result)
pub type SysResult = LxResult<usize>;

/// Linux error codes defination
#[allow(dead_code)]
#[repr(isize)]
#[derive(Debug)]
pub enum LxError {
/// Undefined
EUNDEF = 0,
/// Operation not permitted
EPERM = 1,
/// No such file or directory
ENOENT = 2,
/// No such process
ESRCH = 3,
/// Interrupted system call
EINTR = 4,
/// I/O error
EIO = 5,
/// No such device or address
ENXIO = 6,
/// Arg list too long
E2BIG = 7,
/// Exec format error
ENOEXEC = 8,
/// Bad file number
EBADF = 9,
/// No child processes
ECHILD = 10,
/// Try again
EAGAIN = 11,
/// Out of memory
ENOMEM = 12,
/// Permission denied
EACCES = 13,
/// Bad address
EFAULT = 14,
/// Block device required
ENOTBLK = 15,
/// Device or resource busy
EBUSY = 16,
/// File exists
EEXIST = 17,
/// Cross-device link
EXDEV = 18,
/// No such device
ENODEV = 19,
/// Not a directory
ENOTDIR = 20,
/// Is a directory
EISDIR = 21,
/// Invalid argument
EINVAL = 22,
/// File table overflow
ENFILE = 23,
/// Too many open files
EMFILE = 24,
/// Not a tty device
ENOTTY = 25,
/// Text file busy
ETXTBSY = 26,
/// File too large
EFBIG = 27,
/// No space left on device
ENOSPC = 28,
/// Illegal seek
ESPIPE = 29,
/// Read-only file system
EROFS = 30,
/// Too many links
EMLINK = 31,
/// Broken pipe
EPIPE = 32,
/// Math argument out of domain
EDOM = 33,
/// Math result not representable
ERANGE = 34,
/// Resource deadlock would occur
EDEADLK = 35,
/// Filename too long
ENAMETOOLONG = 36,
/// No record locks available
ENOLCK = 37,
/// Function not implemented
ENOSYS = 38,
/// Directory not empty
ENOTEMPTY = 39,
/// Too many symbolic links encountered
ELOOP = 40,
ENOTSOCK = 80,
/// Socket operation on non-socket
ENOTSOCK = 88,
/// Protocol not available
ENOPROTOOPT = 92,
/// Protocol family not supported
EPFNOSUPPORT = 96,
/// Address family not supported by protocol
EAFNOSUPPORT = 97,
/// No buffer space available
ENOBUFS = 105,
/// Transport endpoint is already connected
EISCONN = 106,
/// Transport endpoint is not connected
ENOTCONN = 107,
/// Connection refused
ECONNREFUSED = 111,
}

Expand Down
2 changes: 2 additions & 0 deletions linux-object/src/fs/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
use rcore_fs::dev::*;
use spin::RwLock;

/// memory buffer for device
pub struct MemBuf(RwLock<&'static mut [u8]>);

impl MemBuf {
/// create a MemBuf struct
pub fn new(buf: &'static mut [u8]) -> Self {
MemBuf(RwLock::new(buf))
}
Expand Down
2 changes: 2 additions & 0 deletions linux-object/src/fs/fcntl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use bitflags::bitflags;
const F_LINUX_SPECIFIC_BASE: usize = 1024;

bitflags! {
/// fcntl flags
pub struct FcntlFlags: usize {
/// dup
const F_DUPFD = 0;
Expand All @@ -33,6 +34,7 @@ bitflags! {
}

bitflags! {
/// file operate flags
pub struct FileFlags: usize {
/// not blocking
const O_NONBLOCK = 0o4000;
Expand Down
33 changes: 33 additions & 0 deletions linux-object/src/fs/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,54 @@ use rcore_fs::vfs::{FsError, INode, Metadata, PollStatus};
use spin::Mutex;
use zircon_object::object::*;

/// file implement struct
pub struct File {
/// object base
base: KObjectBase,
/// file INode
inode: Arc<dyn INode>,
/// file open options
options: OpenOptions,
/// file path
pub path: String,
/// file inner mut data
inner: Mutex<FileInner>,
}

impl_kobject!(File);

/// file inner mut data struct
#[derive(Default)]
struct FileInner {
offset: u64,
}

/// file open options struct
#[derive(Debug)]
pub struct OpenOptions {
/// open as readable
pub read: bool,
/// open as writeable
pub write: bool,
/// Before each write, the file offset is positioned at the end of the file.
pub append: bool,
/// non block open
pub nonblock: bool,
}

/// file seek type
#[derive(Debug)]
pub enum SeekFrom {
/// seek from start point
Start(u64),
/// seek from end
End(i64),
/// seek from current
Current(i64),
}

impl File {
/// create a file struct
pub fn new(inode: Arc<dyn INode>, options: OpenOptions, path: String) -> Arc<Self> {
Arc::new(File {
base: KObjectBase::new(),
Expand All @@ -53,13 +69,15 @@ impl File {
})
}

/// read from file
pub fn read(&self, buf: &mut [u8]) -> LxResult<usize> {
let mut inner = self.inner.lock();
let len = self.read_at(inner.offset, buf)?;
inner.offset += len as u64;
Ok(len)
}

/// read from file at given offset
pub fn read_at(&self, offset: u64, buf: &mut [u8]) -> LxResult<usize> {
if !self.options.read {
return Err(LxError::EBADF);
Expand All @@ -82,6 +100,7 @@ impl File {
Ok(len)
}

/// write to file
pub fn write(&self, buf: &[u8]) -> LxResult<usize> {
let mut inner = self.inner.lock();
let offset = if self.options.append {
Expand All @@ -94,6 +113,7 @@ impl File {
Ok(len)
}

/// write to file at given offset
pub fn write_at(&self, offset: u64, buf: &[u8]) -> LxResult<usize> {
if !self.options.write {
return Err(LxError::EBADF);
Expand All @@ -102,6 +122,7 @@ impl File {
Ok(len)
}

/// seek from given type and offset
pub fn seek(&self, pos: SeekFrom) -> LxResult<u64> {
let mut inner = self.inner.lock();
inner.offset = match pos {
Expand All @@ -112,6 +133,7 @@ impl File {
Ok(inner.offset)
}

/// resize the file
pub fn set_len(&self, len: u64) -> LxResult {
if !self.options.write {
return Err(LxError::EBADF);
Expand All @@ -120,26 +142,31 @@ impl File {
Ok(())
}

/// Sync all data and metadata
pub fn sync_all(&self) -> LxResult {
self.inode.sync_all()?;
Ok(())
}

/// Sync data (not include metadata)
pub fn sync_data(&self) -> LxResult {
self.inode.sync_data()?;
Ok(())
}

/// get metadata of file
pub fn metadata(&self) -> LxResult<Metadata> {
let metadata = self.inode.metadata()?;
Ok(metadata)
}

/// lookup the file following the link
pub fn lookup_follow(&self, path: &str, max_follow: usize) -> LxResult<Arc<dyn INode>> {
let inode = self.inode.lookup_follow(path, max_follow)?;
Ok(inode)
}

/// get the name of dir entry
pub fn read_entry(&self) -> LxResult<String> {
if !self.options.read {
return Err(LxError::EBADF);
Expand All @@ -150,24 +177,30 @@ impl File {
Ok(name)
}

/// wait for some event on a file
pub fn poll(&self) -> LxResult<PollStatus> {
let status = self.inode.poll()?;
Ok(status)
}

/// wait for some event on a file using async
pub async fn async_poll(&self) -> LxResult<PollStatus> {
Ok(self.inode.async_poll().await?)
}

/// manipulates the underlying device parameters of special files
pub fn io_control(&self, cmd: u32, arg: usize) -> LxResult<usize> {
self.inode.io_control(cmd, arg)?;
Ok(0)
}

/// get INode of this file
pub fn inode(&self) -> Arc<dyn INode> {
self.inode.clone()
}

/// manipulate file descriptor
/// unimplemented
pub fn fcntl(&self, cmd: usize, arg: usize) -> LxResult<usize> {
if arg & 0x800 > 0 && cmd == 4 {
unimplemented!()
Expand Down
Loading

0 comments on commit 37e7ae1

Please sign in to comment.