Skip to content

Commit

Permalink
Merge pull request #125 from yunwei37/master
Browse files Browse the repository at this point in the history
Improve docs for `linux-syscall` and fix "uname" command
  • Loading branch information
wangrunji0408 authored Aug 6, 2020
2 parents 50d8acd + 228c1f9 commit 40ecaf0
Show file tree
Hide file tree
Showing 10 changed files with 214 additions and 11 deletions.
36 changes: 35 additions & 1 deletion linux-syscall/src/file/dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ use kernel_hal::user::UserOutPtr;
use linux_object::fs::vfs::FileType;

impl Syscall<'_> {
/// return a null-terminated string containing an absolute pathname
/// that is the current working directory of the calling process.
/// - `buf` – pointer to buffer to receive path
/// - `len` – size of buf
pub fn sys_getcwd(&self, mut buf: UserOutPtr<u8>, len: usize) -> SysResult {
info!("getcwd: buf={:?}, len={:#x}", buf, len);
let proc = self.linux_process();
Expand All @@ -27,6 +31,8 @@ impl Syscall<'_> {
Ok(buf.as_ptr() as usize)
}

/// Change the current directory.
/// - `path` – pointer to string with name of path
pub fn sys_chdir(&self, path: UserInPtr<u8>) -> SysResult {
let path = path.read_cstring()?;
info!("chdir: path={:?}", path);
Expand All @@ -41,10 +47,14 @@ impl Syscall<'_> {
Ok(0)
}

/// Make a directory.
/// - path – pointer to string with directory name
/// - mode – file system permissions mode
pub fn sys_mkdir(&self, path: UserInPtr<u8>, mode: usize) -> SysResult {
self.sys_mkdirat(FileDesc::CWD, path, mode)
}

/// create directory relative to directory file descriptor
pub fn sys_mkdirat(&self, dirfd: FileDesc, path: UserInPtr<u8>, mode: usize) -> SysResult {
let path = path.read_cstring()?;
// TODO: check pathname
Expand All @@ -62,7 +72,8 @@ impl Syscall<'_> {
inode.create(file_name, FileType::Dir, mode as u32)?;
Ok(0)
}

/// Remove a directory.
/// - path – pointer to string with directory name
pub fn sys_rmdir(&self, path: UserInPtr<u8>) -> SysResult {
let path = path.read_cstring()?;
info!("rmdir: path={:?}", path);
Expand All @@ -78,6 +89,9 @@ impl Syscall<'_> {
Ok(0)
}

/// get directory entries
/// TODO: get ino from dirent
/// - fd – file describe
pub fn sys_getdents64(
&self,
fd: FileDesc,
Expand Down Expand Up @@ -111,10 +125,14 @@ impl Syscall<'_> {
Ok(writer.written_size)
}

/// creates a new link (also known as a hard link) to an existing file.
pub fn sys_link(&self, oldpath: UserInPtr<u8>, newpath: UserInPtr<u8>) -> SysResult {
self.sys_linkat(FileDesc::CWD, oldpath, FileDesc::CWD, newpath, 0)
}

/// create file link relative to directory file descriptors
/// If the pathname given in oldpath is relative,
/// then it is interpreted relative to the directory referred to by the file descriptor olddirfd
pub fn sys_linkat(
&self,
olddirfd: FileDesc,
Expand All @@ -139,10 +157,16 @@ impl Syscall<'_> {
Ok(0)
}

/// delete name/possibly file it refers to
/// If that name was the last link to a file and no processes have the file open, the file is deleted.
/// If the name was the last link to a file but any processes still have the file open,
/// the file will remain in existence until the last file descriptor referring to it is closed.
pub fn sys_unlink(&self, path: UserInPtr<u8>) -> SysResult {
self.sys_unlinkat(FileDesc::CWD, path, 0)
}

/// remove directory entry relative to directory file descriptor
/// The unlinkat() system call operates in exactly the same way as either unlink or rmdir.
pub fn sys_unlinkat(&self, dirfd: FileDesc, path: UserInPtr<u8>, flags: usize) -> SysResult {
let path = path.read_cstring()?;
let flags = AtFlags::from_bits_truncate(flags);
Expand All @@ -162,10 +186,12 @@ impl Syscall<'_> {
Ok(0)
}

/// change name/location of file
pub fn sys_rename(&self, oldpath: UserInPtr<u8>, newpath: UserInPtr<u8>) -> SysResult {
self.sys_renameat(FileDesc::CWD, oldpath, FileDesc::CWD, newpath)
}

/// rename file relative to directory file descriptors
pub fn sys_renameat(
&self,
olddirfd: FileDesc,
Expand All @@ -189,10 +215,14 @@ impl Syscall<'_> {
Ok(0)
}

/// read value of symbolic link
pub fn sys_readlink(&self, path: UserInPtr<u8>, base: UserOutPtr<u8>, len: usize) -> SysResult {
self.sys_readlinkat(FileDesc::CWD, path, base, len)
}

/// read value of symbolic link relative to directory file descriptor
/// readlink() places the contents of the symbolic link path in the buffer base, which has size len
/// TODO: recursive link resolution and loop detection
pub fn sys_readlinkat(
&self,
dirfd: FileDesc,
Expand Down Expand Up @@ -234,13 +264,15 @@ pub struct LinuxDirent64 {
name: [u8; 0],
}

/// directory entry buffer writer
struct DirentBufWriter<'a> {
buf: &'a mut [u8],
rest_size: usize,
written_size: usize,
}

impl<'a> DirentBufWriter<'a> {
/// create a buffer writer
fn new(buf: &'a mut [u8]) -> Self {
DirentBufWriter {
rest_size: buf.len(),
Expand All @@ -249,6 +281,7 @@ impl<'a> DirentBufWriter<'a> {
}
}

/// write data
fn try_write(&mut self, inode: u64, type_: u8, name: &str) -> bool {
let len = core::mem::size_of::<LinuxDirent64>() + name.len() + 1;
let len = (len + 7) / 8 * 8; // align up
Expand All @@ -275,6 +308,7 @@ impl<'a> DirentBufWriter<'a> {
true
}

/// to slice
fn as_slice(&self) -> &[u8] {
&self.buf[..self.written_size]
}
Expand Down
7 changes: 7 additions & 0 deletions linux-syscall/src/file/fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
use super::*;

impl Syscall<'_> {
/// Opens or creates a file, depending on the flags passed to the call. Returns an integer with the file descriptor.
pub fn sys_open(&self, path: UserInPtr<u8>, flags: usize, mode: usize) -> SysResult {
self.sys_openat(FileDesc::CWD, path, flags, mode)
}

/// open file relative to directory file descriptor
pub fn sys_openat(
&self,
dir_fd: FileDesc,
Expand Down Expand Up @@ -52,13 +54,15 @@ impl Syscall<'_> {
Ok(fd.into())
}

/// Closes a file descriptor, so that it no longer refers to any file and may be reused.
pub fn sys_close(&self, fd: FileDesc) -> SysResult {
info!("close: fd={:?}", fd);
let proc = self.linux_process();
proc.close_file(fd)?;
Ok(0)
}

/// create a copy of the file descriptor oldfd.
pub fn sys_dup2(&self, fd1: FileDesc, fd2: FileDesc) -> SysResult {
info!("dup2: from {:?} to {:?}", fd1, fd2);
let proc = self.linux_process();
Expand Down Expand Up @@ -127,14 +131,17 @@ bitflags! {
}

impl OpenFlags {
/// check if the OpenFlags is readable
fn readable(self) -> bool {
let b = self.bits() & 0b11;
b == Self::RDONLY.bits() || b == Self::RDWR.bits()
}
/// check if the OpenFlags is writable
fn writable(self) -> bool {
let b = self.bits() & 0b11;
b == Self::WRONLY.bits() || b == Self::RDWR.bits()
}
/// convert OpenFlags to OpenOptions
fn to_options(self) -> OpenOptions {
OpenOptions {
read: self.readable(),
Expand Down
39 changes: 39 additions & 0 deletions linux-syscall/src/file/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
use super::*;

impl Syscall<'_> {
/// Reads from a specified file using a file descriptor. Before using this call,
/// you must first obtain a file descriptor using the opensyscall. Returns bytes read successfully.
/// - fd – file descriptor
/// - base – pointer to the buffer to fill with read contents
/// - len – number of bytes to read
pub fn sys_read(&self, fd: FileDesc, mut base: UserOutPtr<u8>, len: usize) -> SysResult {
info!("read: fd={:?}, base={:?}, len={:#x}", fd, base, len);
let proc = self.linux_process();
Expand All @@ -22,6 +27,11 @@ impl Syscall<'_> {
Ok(len)
}

/// Writes to a specified file using a file descriptor. Before using this call,
/// you must first obtain a file descriptor using the open syscall. Returns bytes written successfully.
/// - fd – file descriptor
/// - base – pointer to the buffer write
/// - len – number of bytes to write
pub fn sys_write(&self, fd: FileDesc, base: UserInPtr<u8>, len: usize) -> SysResult {
info!("write: fd={:?}, base={:?}, len={:#x}", fd, base, len);
let proc = self.linux_process();
Expand All @@ -31,6 +41,9 @@ impl Syscall<'_> {
Ok(len)
}

/// read from or write to a file descriptor at a given offset
/// reads up to count bytes from file descriptor fd at offset offset
/// (from the start of the file) into the buffer starting at buf. The file offset is not changed.
pub fn sys_pread(
&self,
fd: FileDesc,
Expand All @@ -50,6 +63,8 @@ impl Syscall<'_> {
Ok(len)
}

/// writes up to count bytes from the buffer
/// starting at buf to the file descriptor fd at offset offset. The file offset is not changed.
pub fn sys_pwrite(
&self,
fd: FileDesc,
Expand All @@ -68,6 +83,9 @@ impl Syscall<'_> {
Ok(len)
}

/// works just like read except that multiple buffers are filled.
/// reads iov_count buffers from the file
/// associated with the file descriptor fd into the buffers described by iov ("scatter input")
pub fn sys_readv(
&self,
fd: FileDesc,
Expand All @@ -84,6 +102,9 @@ impl Syscall<'_> {
Ok(len)
}

/// works just like write except that multiple buffers are written out.
/// writes iov_count buffers of data described
/// by iov to the file associated with the file descriptor fd ("gather output").
pub fn sys_writev(
&self,
fd: FileDesc,
Expand All @@ -102,6 +123,8 @@ impl Syscall<'_> {
Ok(len)
}

/// repositions the offset of the open file associated with the file descriptor fd
/// to the argument offset according to the directive whence
pub fn sys_lseek(&self, fd: FileDesc, offset: i64, whence: u8) -> SysResult {
const SEEK_SET: u8 = 0;
const SEEK_CUR: u8 = 1;
Expand All @@ -121,6 +144,7 @@ impl Syscall<'_> {
Ok(offset as usize)
}

/// cause the regular file named by path to be truncated to a size of precisely length bytes.
pub fn sys_truncate(&self, path: UserInPtr<u8>, len: usize) -> SysResult {
let path = path.read_cstring()?;
info!("truncate: path={:?}, len={}", path, len);
Expand All @@ -129,13 +153,15 @@ impl Syscall<'_> {
Ok(0)
}

/// cause the regular file referenced by fd to be truncated to a size of precisely length bytes.
pub fn sys_ftruncate(&self, fd: FileDesc, len: usize) -> SysResult {
info!("ftruncate: fd={:?}, len={}", fd, len);
let proc = self.linux_process();
proc.get_file(fd)?.set_len(len as u64)?;
Ok(0)
}

/// copies data between one file descriptor and another.
pub fn sys_sendfile(
&self,
out_fd: FileDesc,
Expand All @@ -146,6 +172,7 @@ impl Syscall<'_> {
self.sys_copy_file_range(in_fd, offset_ptr, out_fd, 0.into(), count, 0)
}

/// copies data between one file descriptor and anothe, read from specified offset and write new offset back
pub fn sys_copy_file_range(
&self,
in_fd: FileDesc,
Expand Down Expand Up @@ -223,26 +250,32 @@ impl Syscall<'_> {
Ok(total_written)
}

/// causes all buffered modifications to file metadata and data to be written to the underlying file systems.
pub fn sys_sync(&self) -> SysResult {
info!("sync:");
let proc = self.linux_process();
proc.root_inode().fs().sync()?;
Ok(0)
}

/// transfers ("flushes") all modified in-core data of (i.e., modified buffer cache pages for) the file
/// referred to by the file descriptor fd to the disk device
pub fn sys_fsync(&self, fd: FileDesc) -> SysResult {
info!("fsync: fd={:?}", fd);
let proc = self.linux_process();
proc.get_file(fd)?.sync_all()?;
Ok(0)
}

/// is similar to fsync(), but does not flush modified metadata unless that metadata is needed
pub fn sys_fdatasync(&self, fd: FileDesc) -> SysResult {
info!("fdatasync: fd={:?}", fd);
let proc = self.linux_process();
proc.get_file(fd)?.sync_data()?;
Ok(0)
}

/// Set parameters of device files.
pub fn sys_ioctl(
&self,
fd: FileDesc,
Expand All @@ -260,17 +293,23 @@ impl Syscall<'_> {
file_like.ioctl(request, arg1, arg2, arg3)
}

/// Manipulate a file descriptor.
/// - cmd – cmd flag
/// - arg – additional parameters based on cmd
pub fn sys_fcntl(&self, fd: FileDesc, cmd: usize, arg: usize) -> SysResult {
info!("fcntl: fd={:?}, cmd={:x}, arg={}", fd, cmd, arg);
let proc = self.linux_process();
let file_like = proc.get_file_like(fd)?;
file_like.fcntl(cmd, arg)
}

/// Checks whether the calling process can access the file pathname
pub fn sys_access(&self, path: UserInPtr<u8>, mode: usize) -> SysResult {
self.sys_faccessat(FileDesc::CWD, path, mode, 0)
}

/// Check user's permissions of a file relative to a directory file descriptor
/// TODO: check permissions based on uid/gid
pub fn sys_faccessat(
&self,
dirfd: FileDesc,
Expand Down
2 changes: 2 additions & 0 deletions linux-syscall/src/file/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Syscalls for files
#![deny(missing_docs)]
use super::*;
use bitflags::bitflags;
use linux_object::fs::vfs::{FileType, FsError};
Expand Down
11 changes: 11 additions & 0 deletions linux-syscall/src/file/stat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ use super::*;
use linux_object::fs::vfs::{FileType, Metadata};

impl Syscall<'_> {
/// Works exactly like the stat syscall, but if the file in question is a symbolic link,
/// information on the link is returned rather than its target.
/// - `path` – full path to file
/// - `stat_ptr` – pointer to stat buffer
pub fn sys_lstat(&self, path: UserInPtr<u8>, stat_ptr: UserOutPtr<Stat>) -> SysResult {
self.sys_fstatat(
FileDesc::CWD,
Expand All @@ -17,6 +21,9 @@ impl Syscall<'_> {
)
}

/// Works exactly like the stat syscall except a file descriptor (fd) is provided instead of a path.
/// - `fd` – file descriptor
/// - `stat_ptr` – pointer to stat buffer
pub fn sys_fstat(&self, fd: FileDesc, mut stat_ptr: UserOutPtr<Stat>) -> SysResult {
info!("fstat: fd={:?}, stat_ptr={:?}", fd, stat_ptr);
let proc = self.linux_process();
Expand All @@ -26,6 +33,7 @@ impl Syscall<'_> {
Ok(0)
}

/// get file status relative to a directory file descriptor
pub fn sys_fstatat(
&self,
dirfd: FileDesc,
Expand All @@ -48,6 +56,9 @@ impl Syscall<'_> {
Ok(0)
}

/// Returns information about a file in a structure named stat.
/// - `path` – pointer to the name of the file
/// - `stat_ptr` – pointer to the structure to receive file information
pub fn sys_stat(&self, path: UserInPtr<u8>, stat_ptr: UserOutPtr<Stat>) -> SysResult {
self.sys_fstatat(FileDesc::CWD, path, stat_ptr, 0)
}
Expand Down
Loading

0 comments on commit 40ecaf0

Please sign in to comment.