From c0e2dbd660d2c4c988c2b5e8f0a7e943b4da76db Mon Sep 17 00:00:00 2001 From: myub <1067852565@qq.com> Date: Mon, 3 Aug 2020 06:22:26 -0700 Subject: [PATCH 1/7] fix uname --- linux-syscall/src/misc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-syscall/src/misc.rs b/linux-syscall/src/misc.rs index 0ccc89df5..dec08982b 100644 --- a/linux-syscall/src/misc.rs +++ b/linux-syscall/src/misc.rs @@ -19,7 +19,7 @@ impl Syscall<'_> { pub fn sys_uname(&self, buf: UserOutPtr) -> SysResult { info!("uname: buf={:?}", buf); - let strings = ["rCore", "orz", "0.1.0", "1", "machine", "domain"]; + let strings = ["zCore", "orz", "0.1.0", "1", "machine", "domain"]; for (i, &s) in strings.iter().enumerate() { const OFFSET: usize = 65; buf.add(i * OFFSET).write_cstring(s)?; From 36dc3f35e6676b8f3a2d97295a2a7c2f9a4bf39a Mon Sep 17 00:00:00 2001 From: myub <1067852565@qq.com> Date: Tue, 4 Aug 2020 19:22:17 -0700 Subject: [PATCH 2/7] Improve docs for `linux-syscall::file` --- linux-syscall/src/file/dir.rs | 36 ++++++++++++++++++++++++++++++- linux-syscall/src/file/fd.rs | 7 ++++++ linux-syscall/src/file/file.rs | 39 ++++++++++++++++++++++++++++++++++ linux-syscall/src/file/mod.rs | 1 + linux-syscall/src/file/stat.rs | 11 ++++++++++ 5 files changed, 93 insertions(+), 1 deletion(-) diff --git a/linux-syscall/src/file/dir.rs b/linux-syscall/src/file/dir.rs index a46847a9e..da6abff92 100644 --- a/linux-syscall/src/file/dir.rs +++ b/linux-syscall/src/file/dir.rs @@ -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, len: usize) -> SysResult { info!("getcwd: buf={:?}, len={:#x}", buf, len); let proc = self.linux_process(); @@ -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) -> SysResult { let path = path.read_cstring()?; info!("chdir: path={:?}", path); @@ -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, 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, mode: usize) -> SysResult { let path = path.read_cstring()?; // TODO: check pathname @@ -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) -> SysResult { let path = path.read_cstring()?; info!("rmdir: path={:?}", path); @@ -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, @@ -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, newpath: UserInPtr) -> 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, @@ -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) -> 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, flags: usize) -> SysResult { let path = path.read_cstring()?; let flags = AtFlags::from_bits_truncate(flags); @@ -162,10 +186,12 @@ impl Syscall<'_> { Ok(0) } + /// change name/location of file pub fn sys_rename(&self, oldpath: UserInPtr, newpath: UserInPtr) -> SysResult { self.sys_renameat(FileDesc::CWD, oldpath, FileDesc::CWD, newpath) } + /// rename file relative to directory file descriptors pub fn sys_renameat( &self, olddirfd: FileDesc, @@ -189,10 +215,14 @@ impl Syscall<'_> { Ok(0) } + /// read value of symbolic link pub fn sys_readlink(&self, path: UserInPtr, base: UserOutPtr, 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, @@ -234,6 +264,7 @@ pub struct LinuxDirent64 { name: [u8; 0], } +/// directory entry buffer writer struct DirentBufWriter<'a> { buf: &'a mut [u8], rest_size: usize, @@ -241,6 +272,7 @@ struct DirentBufWriter<'a> { } impl<'a> DirentBufWriter<'a> { + /// create a buffer writer fn new(buf: &'a mut [u8]) -> Self { DirentBufWriter { rest_size: buf.len(), @@ -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::() + name.len() + 1; let len = (len + 7) / 8 * 8; // align up @@ -275,6 +308,7 @@ impl<'a> DirentBufWriter<'a> { true } + /// to slice fn as_slice(&self) -> &[u8] { &self.buf[..self.written_size] } diff --git a/linux-syscall/src/file/fd.rs b/linux-syscall/src/file/fd.rs index 5252a2cea..d51666f6b 100644 --- a/linux-syscall/src/file/fd.rs +++ b/linux-syscall/src/file/fd.rs @@ -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, 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, @@ -52,6 +54,7 @@ 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(); @@ -59,6 +62,7 @@ impl Syscall<'_> { 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(); @@ -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(), diff --git a/linux-syscall/src/file/file.rs b/linux-syscall/src/file/file.rs index 870ddac57..0a95081ef 100644 --- a/linux-syscall/src/file/file.rs +++ b/linux-syscall/src/file/file.rs @@ -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, len: usize) -> SysResult { info!("read: fd={:?}, base={:?}, len={:#x}", fd, base, len); let proc = self.linux_process(); @@ -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, len: usize) -> SysResult { info!("write: fd={:?}, base={:?}, len={:#x}", fd, base, len); let proc = self.linux_process(); @@ -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, @@ -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, @@ -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, @@ -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, @@ -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; @@ -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, len: usize) -> SysResult { let path = path.read_cstring()?; info!("truncate: path={:?}, len={}", path, len); @@ -129,6 +153,7 @@ 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(); @@ -136,6 +161,7 @@ impl Syscall<'_> { Ok(0) } + /// copies data between one file descriptor and another. pub fn sys_sendfile( &self, out_fd: FileDesc, @@ -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, @@ -223,6 +250,7 @@ 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(); @@ -230,6 +258,8 @@ impl Syscall<'_> { 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(); @@ -237,12 +267,15 @@ impl Syscall<'_> { 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, @@ -260,6 +293,9 @@ 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(); @@ -267,10 +303,13 @@ impl Syscall<'_> { file_like.fcntl(cmd, arg) } + /// Checks whether the calling process can access the file pathname pub fn sys_access(&self, path: UserInPtr, 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, diff --git a/linux-syscall/src/file/mod.rs b/linux-syscall/src/file/mod.rs index abba8edf6..a147ee4e4 100644 --- a/linux-syscall/src/file/mod.rs +++ b/linux-syscall/src/file/mod.rs @@ -1,3 +1,4 @@ +#![deny(missing_docs)] use super::*; use bitflags::bitflags; use linux_object::fs::vfs::{FileType, FsError}; diff --git a/linux-syscall/src/file/stat.rs b/linux-syscall/src/file/stat.rs index e5757a652..7ea803c28 100644 --- a/linux-syscall/src/file/stat.rs +++ b/linux-syscall/src/file/stat.rs @@ -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, stat_ptr: UserOutPtr) -> SysResult { self.sys_fstatat( FileDesc::CWD, @@ -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) -> SysResult { info!("fstat: fd={:?}, stat_ptr={:?}", fd, stat_ptr); let proc = self.linux_process(); @@ -26,6 +33,7 @@ impl Syscall<'_> { Ok(0) } + /// get file status relative to a directory file descriptor pub fn sys_fstatat( &self, dirfd: FileDesc, @@ -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, stat_ptr: UserOutPtr) -> SysResult { self.sys_fstatat(FileDesc::CWD, path, stat_ptr, 0) } From 627a8c47aa7cd5d97d54166a0558db81b69e6809 Mon Sep 17 00:00:00 2001 From: myub <1067852565@qq.com> Date: Tue, 4 Aug 2020 20:07:07 -0700 Subject: [PATCH 3/7] update document for task.rs and time.rs, with cargo fmt --- linux-syscall/src/file/dir.rs | 22 ++++++++++----------- linux-syscall/src/file/fd.rs | 4 ++-- linux-syscall/src/file/file.rs | 32 +++++++++++++++---------------- linux-syscall/src/file/stat.rs | 4 ++-- linux-syscall/src/task.rs | 35 ++++++++++++++++++++++++++++++++++ linux-syscall/src/time.rs | 5 ++++- 6 files changed, 70 insertions(+), 32 deletions(-) diff --git a/linux-syscall/src/file/dir.rs b/linux-syscall/src/file/dir.rs index da6abff92..2870c51b3 100644 --- a/linux-syscall/src/file/dir.rs +++ b/linux-syscall/src/file/dir.rs @@ -16,7 +16,7 @@ use kernel_hal::user::UserOutPtr; use linux_object::fs::vfs::FileType; impl Syscall<'_> { - /// return a null-terminated string containing an absolute pathname + /// 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 @@ -54,7 +54,7 @@ impl Syscall<'_> { self.sys_mkdirat(FileDesc::CWD, path, mode) } - /// create directory relative to directory file descriptor + /// create directory relative to directory file descriptor pub fn sys_mkdirat(&self, dirfd: FileDesc, path: UserInPtr, mode: usize) -> SysResult { let path = path.read_cstring()?; // TODO: check pathname @@ -89,7 +89,7 @@ impl Syscall<'_> { Ok(0) } - /// get directory entries + /// get directory entries /// TODO: get ino from dirent /// - fd – file describe pub fn sys_getdents64( @@ -125,13 +125,13 @@ impl Syscall<'_> { Ok(writer.written_size) } - /// creates a new link (also known as a hard link) to an existing file. + /// creates a new link (also known as a hard link) to an existing file. pub fn sys_link(&self, oldpath: UserInPtr, newpath: UserInPtr) -> 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, + /// 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, @@ -157,7 +157,7 @@ impl Syscall<'_> { Ok(0) } - /// delete name/possibly file it refers to + /// 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. @@ -165,7 +165,7 @@ impl Syscall<'_> { self.sys_unlinkat(FileDesc::CWD, path, 0) } - /// remove directory entry relative to directory file descriptor + /// 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, flags: usize) -> SysResult { let path = path.read_cstring()?; @@ -191,7 +191,7 @@ impl Syscall<'_> { self.sys_renameat(FileDesc::CWD, oldpath, FileDesc::CWD, newpath) } - /// rename file relative to directory file descriptors + /// rename file relative to directory file descriptors pub fn sys_renameat( &self, olddirfd: FileDesc, @@ -215,12 +215,12 @@ impl Syscall<'_> { Ok(0) } - /// read value of symbolic link + /// read value of symbolic link pub fn sys_readlink(&self, path: UserInPtr, base: UserOutPtr, len: usize) -> SysResult { self.sys_readlinkat(FileDesc::CWD, path, base, len) } - /// read value of symbolic link relative to directory file descriptor + /// 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( diff --git a/linux-syscall/src/file/fd.rs b/linux-syscall/src/file/fd.rs index d51666f6b..34a06a901 100644 --- a/linux-syscall/src/file/fd.rs +++ b/linux-syscall/src/file/fd.rs @@ -13,7 +13,7 @@ impl Syscall<'_> { self.sys_openat(FileDesc::CWD, path, flags, mode) } - /// open file relative to directory file descriptor + /// open file relative to directory file descriptor pub fn sys_openat( &self, dir_fd: FileDesc, @@ -62,7 +62,7 @@ impl Syscall<'_> { Ok(0) } - /// create a copy of the file descriptor oldfd. + /// 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(); diff --git a/linux-syscall/src/file/file.rs b/linux-syscall/src/file/file.rs index 0a95081ef..82f090e5a 100644 --- a/linux-syscall/src/file/file.rs +++ b/linux-syscall/src/file/file.rs @@ -12,7 +12,7 @@ use super::*; impl Syscall<'_> { - /// Reads from a specified file using a file descriptor. Before using this call, + /// 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 @@ -27,7 +27,7 @@ impl Syscall<'_> { Ok(len) } - /// Writes to a specified file using a file descriptor. Before using this call, + /// 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 @@ -41,8 +41,8 @@ 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 + /// 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, @@ -63,8 +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. + /// 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, @@ -83,8 +83,8 @@ impl Syscall<'_> { Ok(len) } - /// works just like read except that multiple buffers are filled. - /// reads iov_count buffers from the file + /// 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, @@ -103,8 +103,8 @@ impl Syscall<'_> { } /// 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"). + /// 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, @@ -123,7 +123,7 @@ impl Syscall<'_> { Ok(len) } - /// repositions the offset of the open file associated with the file descriptor fd + /// 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; @@ -144,7 +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. + /// cause the regular file named by path to be truncated to a size of precisely length bytes. pub fn sys_truncate(&self, path: UserInPtr, len: usize) -> SysResult { let path = path.read_cstring()?; info!("truncate: path={:?}, len={}", path, len); @@ -153,7 +153,7 @@ impl Syscall<'_> { Ok(0) } - /// cause the regular file referenced by fd to be truncated to a size of precisely length bytes. + /// 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(); @@ -250,7 +250,7 @@ impl Syscall<'_> { Ok(total_written) } - /// causes all buffered modifications to file metadata and data to be written to the underlying file systems. + /// 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(); @@ -258,7 +258,7 @@ impl Syscall<'_> { Ok(0) } - /// transfers ("flushes") all modified in-core data of (i.e., modified buffer cache pages for) the file + /// 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); @@ -308,7 +308,7 @@ impl Syscall<'_> { self.sys_faccessat(FileDesc::CWD, path, mode, 0) } - /// Check user's permissions of a file relative to a directory file descriptor + /// 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, diff --git a/linux-syscall/src/file/stat.rs b/linux-syscall/src/file/stat.rs index 7ea803c28..baf090f05 100644 --- a/linux-syscall/src/file/stat.rs +++ b/linux-syscall/src/file/stat.rs @@ -8,7 +8,7 @@ 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, + /// 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 @@ -33,7 +33,7 @@ impl Syscall<'_> { Ok(0) } - /// get file status relative to a directory file descriptor + /// get file status relative to a directory file descriptor pub fn sys_fstatat( &self, dirfd: FileDesc, diff --git a/linux-syscall/src/task.rs b/linux-syscall/src/task.rs index 4f1ebc4d6..20c816e1d 100644 --- a/linux-syscall/src/task.rs +++ b/linux-syscall/src/task.rs @@ -1,4 +1,13 @@ //! Syscalls for process +//! +//! - fork +//! - vfork +//! - clone +//! - wait4 +//! - execve +//! - gettid +//! - getpid +//! - getppid use super::*; use bitflags::bitflags; @@ -255,6 +264,8 @@ impl Syscall<'_> { // Ok(0) // } + /// set pointer to thread ID + /// returns the caller's thread ID pub fn sys_set_tid_address(&self, tidptr: UserOutPtr) -> SysResult { info!("set_tid_address: {:?}", tidptr); self.thread.set_tid_address(tidptr); @@ -265,29 +276,53 @@ impl Syscall<'_> { bitflags! { pub struct CloneFlags: usize { + /// const CSIGNAL = 0xff; + /// the calling process and the child process run in the same memory space const VM = 1 << 8; + /// the caller and the child process share the same filesystem information const FS = 1 << 9; + /// the calling process and the child process share the same file descriptor table const FILES = 1 << 10; + /// the calling process and the child process share the same table of signal handlers. const SIGHAND = 1 << 11; + /// the calling process is being traced const PTRACE = 1 << 13; + /// the execution of the calling process is suspended until the child releases its virtual memory resources const VFORK = 1 << 14; + /// the parent of the new child will be the same as that of the call‐ing process. const PARENT = 1 << 15; + /// the child is placed in the same thread group as the calling process. const THREAD = 1 << 16; + /// cloned child is started in a new mount namespace const NEWNS = 1 << 17; + /// the child and the calling process share a single list of System V semaphore adjustment values. const SYSVSEM = 1 << 18; + /// architecture dependent, The TLS (Thread Local Storage) descriptor is set to tls. const SETTLS = 1 << 19; + /// Store the child thread ID at the location in the parent's memory. const PARENT_SETTID = 1 << 20; + /// Clear (zero) the child thread ID const CHILD_CLEARTID = 1 << 21; + /// the parent not to receive a signal when the child terminated const DETACHED = 1 << 22; + /// a tracing process cannot force CLONE_PTRACE on this child process. const UNTRACED = 1 << 23; + /// Store the child thread ID const CHILD_SETTID = 1 << 24; + /// Create the process in a new cgroup namespace. const NEWCGROUP = 1 << 25; + /// create the process in a new UTS namespace const NEWUTS = 1 << 26; + /// create the process in a new IPC namespace. const NEWIPC = 1 << 27; + /// create the process in a new user namespace const NEWUSER = 1 << 28; + /// create the process in a new PID namespace const NEWPID = 1 << 29; + /// create the process in a new net‐work namespace. const NEWNET = 1 << 30; + /// the new process shares an I/O context with the calling process. const IO = 1 << 31; } } diff --git a/linux-syscall/src/time.rs b/linux-syscall/src/time.rs index 8a54ded66..0a7661f87 100644 --- a/linux-syscall/src/time.rs +++ b/linux-syscall/src/time.rs @@ -1,4 +1,5 @@ -//use super::*; +//! Syscalls for time +//! - clock_gettime use crate::Syscall; use kernel_hal::{timer_now, user::UserOutPtr}; @@ -7,7 +8,9 @@ use linux_object::error::SysResult; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct TimeSpec { + /// second sec: usize, + /// nano second nsec: usize, } From c66e68cb7d11eec9f41f0a733bf2e7a2e15880ad Mon Sep 17 00:00:00 2001 From: myub <1067852565@qq.com> Date: Tue, 4 Aug 2020 22:06:00 -0700 Subject: [PATCH 4/7] linux-syscall pass `#![deny(missing_docs)]` --- linux-syscall/src/file/dir.rs | 4 ++-- linux-syscall/src/file/mod.rs | 1 + linux-syscall/src/lib.rs | 35 ++++++++++++++++++++++++++++++++++- linux-syscall/src/misc.rs | 30 +++++++++++++++++++++++------- linux-syscall/src/task.rs | 1 + linux-syscall/src/time.rs | 6 ++++-- linux-syscall/src/vm.rs | 17 +++++++++++++++++ 7 files changed, 82 insertions(+), 12 deletions(-) diff --git a/linux-syscall/src/file/dir.rs b/linux-syscall/src/file/dir.rs index 2870c51b3..ef2008010 100644 --- a/linux-syscall/src/file/dir.rs +++ b/linux-syscall/src/file/dir.rs @@ -18,8 +18,8 @@ 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 + /// - `buf` – pointer to buffer to receive path + /// - `len` – size of buf pub fn sys_getcwd(&self, mut buf: UserOutPtr, len: usize) -> SysResult { info!("getcwd: buf={:?}, len={:#x}", buf, len); let proc = self.linux_process(); diff --git a/linux-syscall/src/file/mod.rs b/linux-syscall/src/file/mod.rs index a147ee4e4..1f3380b0a 100644 --- a/linux-syscall/src/file/mod.rs +++ b/linux-syscall/src/file/mod.rs @@ -1,3 +1,4 @@ +//! Syscalls for files #![deny(missing_docs)] use super::*; use bitflags::bitflags; diff --git a/linux-syscall/src/lib.rs b/linux-syscall/src/lib.rs index 76b8151af..bb53c38b5 100644 --- a/linux-syscall/src/lib.rs +++ b/linux-syscall/src/lib.rs @@ -1,7 +1,13 @@ //! Linux syscall implementations #![no_std] -#![deny(warnings, unsafe_code, unused_must_use, unreachable_patterns)] +#![deny( + warnings, + unsafe_code, + unused_must_use, + unreachable_patterns, + missing_docs +)] #![feature(bool_to_option)] #[macro_use] @@ -26,16 +32,38 @@ mod task; mod time; mod vm; +/// The struct of Syscall which stores the information about making a syscall +/// the syscall is called like this in the linux-loader: +/// ``` +/// let num = regs.rax as u32; +/// let args = [regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9]; +/// let mut syscall = Syscall { +/// thread, +/// #[cfg(feature = "std")] +/// syscall_entry: kernel_hal_unix::syscall_entry as usize, +/// #[cfg(not(feature = "std"))] +/// syscall_entry: 0, +/// spawn_fn: spawn, +/// regs, +/// exit: false, +/// }; +/// let ret = syscall.syscall(num, args).await; +/// ``` pub struct Syscall<'a> { + /// the thread making a syscall pub thread: &'a Arc, + /// the entry of current syscall pub syscall_entry: VirtAddr, + /// store the regs statues pub regs: &'a mut GeneralRegs, + /// the spawn function in linux-loader pub spawn_fn: fn(thread: Arc), /// Set `true` to exit current task. pub exit: bool, } impl Syscall<'_> { + /// syscall entry function pub async fn syscall(&mut self, num: u32, args: [usize; 6]) -> isize { debug!("syscall: num={}, args={:x?}", num, args); let sys_type = match Sys::try_from(num) { @@ -205,6 +233,7 @@ impl Syscall<'_> { } #[cfg(target_arch = "x86_64")] + /// syscall specified for x86_64 async fn x86_64_syscall(&mut self, sys_type: Sys, args: [usize; 6]) -> SysResult { let [a0, a1, a2, _a3, _a4, _a5] = args; match sys_type { @@ -235,6 +264,7 @@ impl Syscall<'_> { } } + /// unkown syscalls, currently is similar to unimplemented syscalls but emit an error fn unknown_syscall(&mut self, sys_type: Sys) -> SysResult { error!("unknown syscall: {:?}. exit...", sys_type); let proc = self.zircon_process(); @@ -243,15 +273,18 @@ impl Syscall<'_> { Err(LxError::ENOSYS) } + /// unimplemented syscalls fn unimplemented(&self, name: &str, ret: SysResult) -> SysResult { warn!("{}: unimplemented", name); ret } + /// get zircon process fn zircon_process(&self) -> &Arc { self.thread.proc() } + /// get linux process fn linux_process(&self) -> &LinuxProcess { self.zircon_process().linux() } diff --git a/linux-syscall/src/misc.rs b/linux-syscall/src/misc.rs index dec08982b..ef687a2ab 100644 --- a/linux-syscall/src/misc.rs +++ b/linux-syscall/src/misc.rs @@ -4,6 +4,8 @@ use bitflags::bitflags; impl Syscall<'_> { #[cfg(target_arch = "x86_64")] + /// set architecture-specific thread state + /// for x86_64 currently pub fn sys_arch_prctl(&mut self, code: i32, addr: usize) -> SysResult { const ARCH_SET_FS: i32 = 0x1002; match code { @@ -16,6 +18,7 @@ impl Syscall<'_> { } } + /// get name and information about current kernel pub fn sys_uname(&self, buf: UserOutPtr) -> SysResult { info!("uname: buf={:?}", buf); @@ -27,6 +30,12 @@ impl Syscall<'_> { Ok(0) } + /// provides a method for waiting until a certain condition becomes true. + /// - `uaddr` - points to the futex word. + /// - `op` - the operation to perform on the futex + /// - `val` - a value whose meaning and purpose depends on op + /// - `timeout` - not support now + /// TODO: support timeout pub async fn sys_futex( &self, uaddr: usize, @@ -34,13 +43,6 @@ impl Syscall<'_> { val: i32, timeout: UserInPtr, ) -> SysResult { - bitflags! { - struct FutexFlags: u32 { - const WAIT = 0; - const WAKE = 1; - const PRIVATE = 0x80; - } - } let op = FutexFlags::from_bits_truncate(op); info!( "futex: uaddr: {:#x}, op: {:?}, val: {}, timeout_ptr: {:?}", @@ -71,3 +73,17 @@ impl Syscall<'_> { } } } + +bitflags! { + /// for op argument in futex() + struct FutexFlags: u32 { + /// tests that the value at the futex word pointed + /// to by the address uaddr still contains the expected value val, + /// and if so, then sleeps waiting for a FUTEX_WAKE operation on the futex word. + const WAIT = 0; + /// wakes at most val of the waiters that are waiting on the futex word at the address uaddr. + const WAKE = 1; + /// can be employed with all futex operations, tells the kernel that the futex is process-private and not shared with another process + const PRIVATE = 0x80; + } +} diff --git a/linux-syscall/src/task.rs b/linux-syscall/src/task.rs index 20c816e1d..6cf8f9a3d 100644 --- a/linux-syscall/src/task.rs +++ b/linux-syscall/src/task.rs @@ -27,6 +27,7 @@ impl Syscall<'_> { Ok(new_proc.id() as usize) } + /// creates a child process of the calling process, similar to fork but wait for execve pub async fn sys_vfork(&self) -> SysResult { info!("vfork:"); let new_proc = Process::fork_from(self.zircon_process(), true)?; diff --git a/linux-syscall/src/time.rs b/linux-syscall/src/time.rs index 0a7661f87..26a73dbe2 100644 --- a/linux-syscall/src/time.rs +++ b/linux-syscall/src/time.rs @@ -8,13 +8,15 @@ use linux_object::error::SysResult; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct TimeSpec { - /// second + /// seconds sec: usize, - /// nano second + /// nano seconds nsec: usize, } impl Syscall<'_> { + /// finds the resolution (precision) of the specified clock clockid, and, + /// if buffer is non-NULL, stores it in the struct timespec pointed to by buffer pub fn sys_clock_gettime(&self, clock: usize, mut buf: UserOutPtr) -> SysResult { info!("clock_gettime: id={:?} buf={:?}", clock, buf); diff --git a/linux-syscall/src/vm.rs b/linux-syscall/src/vm.rs index 344f58609..1d9b6f689 100644 --- a/linux-syscall/src/vm.rs +++ b/linux-syscall/src/vm.rs @@ -3,6 +3,14 @@ use bitflags::bitflags; use zircon_object::vm::*; impl Syscall<'_> { + /// creates a new mapping in the virtual address space of the calling process. + /// - `addr` - The starting address for the new mapping + /// - `len` - specifies the length of the mapping + /// - `prot ` - describes the desired memory protection of the mapping + /// - `flags` - determines whether updates to the mapping are visible to other processes mapping the same region, + /// and whether updates are carried through to the underlying file. + /// - `fd` - mapping file descriptor + /// - `offset` - offset in the file pub fn sys_mmap( &self, addr: usize, @@ -45,6 +53,9 @@ impl Syscall<'_> { } } + /// changes the access protections for the calling process's memory pages + /// containing any part of the address range in the interval [addr, addr+len-1] + /// TODO: unimplemented pub fn sys_mprotect(&self, addr: usize, len: usize, prot: usize) -> SysResult { let prot = MmapProt::from_bits_truncate(prot); info!( @@ -55,6 +66,8 @@ impl Syscall<'_> { Ok(0) } + /// Deletes the mappings for the specified address range, and causes further references to addresses + /// within the range to generate invalid memory references. pub fn sys_munmap(&self, addr: usize, len: usize) -> SysResult { info!("munmap: addr={:#x}, size={:#x}", addr, len); let proc = self.thread.proc(); @@ -65,6 +78,7 @@ impl Syscall<'_> { } bitflags! { + /// for the flag argument in mmap() pub struct MmapFlags: usize { #[allow(clippy::identity_op)] /// Changes are shared. @@ -78,12 +92,14 @@ bitflags! { } } +/// MmapFlags `MMAP_ANONYMOUS` depends on arch #[cfg(target_arch = "mips")] const MMAP_ANONYMOUS: usize = 0x800; #[cfg(not(target_arch = "mips"))] const MMAP_ANONYMOUS: usize = 1 << 5; bitflags! { + /// for the prot argument in mmap() pub struct MmapProt: usize { #[allow(clippy::identity_op)] /// Data can be read @@ -96,6 +112,7 @@ bitflags! { } impl MmapProt { + /// convert MmapProt to MMUFlags fn to_flags(self) -> MMUFlags { let mut flags = MMUFlags::USER; if self.contains(MmapProt::READ) { From 10e0fb633ea152f6617f1735a52428ac2921349b Mon Sep 17 00:00:00 2001 From: myub <1067852565@qq.com> Date: Tue, 4 Aug 2020 22:32:50 -0700 Subject: [PATCH 5/7] fix doc test --- linux-syscall/src/lib.rs | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/linux-syscall/src/lib.rs b/linux-syscall/src/lib.rs index bb53c38b5..cd32da4f5 100644 --- a/linux-syscall/src/lib.rs +++ b/linux-syscall/src/lib.rs @@ -1,4 +1,23 @@ //! Linux syscall implementations +//! +//! ## Example +//! the syscall is called like this in the linux-loader: +//! ``` +//! // let num = regs.rax as u32; +//! // let args = [regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9]; +//! // let mut syscall = Syscall { +//! // thread, +//! // #[cfg(feature = "std")] +//! // syscall_entry: kernel_hal_unix::syscall_entry as usize, +//! // #[cfg(not(feature = "std"))] +//! // syscall_entry: 0, +//! // spawn_fn: spawn, +//! // regs, +//! // exit: false, +//! // }; +//! // let ret = syscall.syscall(num, args).await; +//! ``` +//! #![no_std] #![deny( @@ -33,22 +52,6 @@ mod time; mod vm; /// The struct of Syscall which stores the information about making a syscall -/// the syscall is called like this in the linux-loader: -/// ``` -/// let num = regs.rax as u32; -/// let args = [regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9]; -/// let mut syscall = Syscall { -/// thread, -/// #[cfg(feature = "std")] -/// syscall_entry: kernel_hal_unix::syscall_entry as usize, -/// #[cfg(not(feature = "std"))] -/// syscall_entry: 0, -/// spawn_fn: spawn, -/// regs, -/// exit: false, -/// }; -/// let ret = syscall.syscall(num, args).await; -/// ``` pub struct Syscall<'a> { /// the thread making a syscall pub thread: &'a Arc, From 0d1348c819683984841fc933f23c9013e3d1440b Mon Sep 17 00:00:00 2001 From: myub <1067852565@qq.com> Date: Wed, 5 Aug 2020 03:49:44 -0700 Subject: [PATCH 6/7] refix uname --- linux-syscall/src/misc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-syscall/src/misc.rs b/linux-syscall/src/misc.rs index ef687a2ab..9dd4e08f1 100644 --- a/linux-syscall/src/misc.rs +++ b/linux-syscall/src/misc.rs @@ -22,7 +22,7 @@ impl Syscall<'_> { pub fn sys_uname(&self, buf: UserOutPtr) -> SysResult { info!("uname: buf={:?}", buf); - let strings = ["zCore", "orz", "0.1.0", "1", "machine", "domain"]; + let strings = ["Linux", "orz", "0.1.0", "1", "machine", "domain"]; for (i, &s) in strings.iter().enumerate() { const OFFSET: usize = 65; buf.add(i * OFFSET).write_cstring(s)?; From 228c1f98c7eeca7983a5a76ae7ef08675aece686 Mon Sep 17 00:00:00 2001 From: Runji Wang Date: Thu, 6 Aug 2020 11:19:11 +0800 Subject: [PATCH 7/7] update code doc in linux-syscall --- linux-syscall/src/lib.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/linux-syscall/src/lib.rs b/linux-syscall/src/lib.rs index cd32da4f5..be72e1be0 100644 --- a/linux-syscall/src/lib.rs +++ b/linux-syscall/src/lib.rs @@ -2,20 +2,20 @@ //! //! ## Example //! the syscall is called like this in the linux-loader: -//! ``` -//! // let num = regs.rax as u32; -//! // let args = [regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9]; -//! // let mut syscall = Syscall { -//! // thread, -//! // #[cfg(feature = "std")] -//! // syscall_entry: kernel_hal_unix::syscall_entry as usize, -//! // #[cfg(not(feature = "std"))] -//! // syscall_entry: 0, -//! // spawn_fn: spawn, -//! // regs, -//! // exit: false, -//! // }; -//! // let ret = syscall.syscall(num, args).await; +//! ```ignore +//! let num = regs.rax as u32; +//! let args = [regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9]; +//! let mut syscall = Syscall { +//! thread, +//! #[cfg(feature = "std")] +//! syscall_entry: kernel_hal_unix::syscall_entry as usize, +//! #[cfg(not(feature = "std"))] +//! syscall_entry: 0, +//! spawn_fn: spawn, +//! regs, +//! exit: false, +//! }; +//! let ret = syscall.syscall(num, args).await; //! ``` //!