Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve docs for linux-syscall and fix "uname" command #125

Merged
merged 8 commits into from
Aug 6, 2020
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
Comment on lines +162 to +163
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: this feature is not correctly implemented.

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