mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-15 08:16:47 +00:00
Add support for getdents64 syscall
This commit is contained in:
parent
44904f00c8
commit
02731914dc
@ -57,11 +57,11 @@ impl InodeHandle<Rights> {
|
|||||||
self.0.write(buf)
|
self.0.write(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readdir(&self, writer: &mut dyn DirentWriter) -> Result<usize> {
|
pub fn readdir(&self, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
||||||
if !self.1.contains(Rights::READ) {
|
if !self.1.contains(Rights::READ) {
|
||||||
return_errno_with_message!(Errno::EBADF, "File is not readable");
|
return_errno_with_message!(Errno::EBADF, "File is not readable");
|
||||||
}
|
}
|
||||||
self.0.readdir(writer)
|
self.0.readdir(visitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,9 +3,7 @@
|
|||||||
mod dyn_cap;
|
mod dyn_cap;
|
||||||
mod static_cap;
|
mod static_cap;
|
||||||
|
|
||||||
use crate::fs::utils::{
|
use crate::fs::utils::{AccessMode, Dentry, DirentVisitor, InodeType, SeekFrom, StatusFlags};
|
||||||
AccessMode, Dentry, DirentWriter, DirentWriterContext, InodeType, SeekFrom, StatusFlags,
|
|
||||||
};
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::rights::Rights;
|
use crate::rights::Rights;
|
||||||
|
|
||||||
@ -113,12 +111,11 @@ impl InodeHandle_ {
|
|||||||
status_flags.insert(new_status_flags & valid_flags_mask);
|
status_flags.insert(new_status_flags & valid_flags_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readdir(&self, writer: &mut dyn DirentWriter) -> Result<usize> {
|
pub fn readdir(&self, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
||||||
let mut offset = self.offset.lock();
|
let mut offset = self.offset.lock();
|
||||||
let mut dir_writer_ctx = DirentWriterContext::new(*offset, writer);
|
let read_cnt = self.dentry.vnode().readdir_at(*offset, visitor)?;
|
||||||
let written_size = self.dentry.vnode().readdir(&mut dir_writer_ctx)?;
|
*offset += read_cnt;
|
||||||
*offset = dir_writer_ctx.pos();
|
Ok(read_cnt)
|
||||||
Ok(written_size)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ impl<R: TRights> InodeHandle<R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[require(R > Read)]
|
#[require(R > Read)]
|
||||||
pub fn readdir(&self, writer: &mut dyn DirentWriter) -> Result<usize> {
|
pub fn readdir(&self, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
||||||
self.0.readdir(writer)
|
self.0.readdir(visitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ use spin::{RwLock, RwLockWriteGuard};
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::fs::utils::{
|
use crate::fs::utils::{
|
||||||
DirentWriterContext, FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata, SuperBlock,
|
DirentVisitor, FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata, SuperBlock,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct RamFS {
|
pub struct RamFS {
|
||||||
@ -144,32 +144,6 @@ struct DirEntry {
|
|||||||
parent: Weak<RamInode>,
|
parent: Weak<RamInode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! write_inode_entry {
|
|
||||||
($ctx:expr, $name:expr, $inode:expr, $total_written:expr) => {
|
|
||||||
let ctx = $ctx;
|
|
||||||
let name = $name;
|
|
||||||
let inode = $inode;
|
|
||||||
let total_written = $total_written;
|
|
||||||
|
|
||||||
match ctx.write_entry(
|
|
||||||
name.as_ref(),
|
|
||||||
inode.metadata().ino as u64,
|
|
||||||
inode.metadata().type_,
|
|
||||||
) {
|
|
||||||
Ok(written_len) => {
|
|
||||||
*total_written += written_len;
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
if *total_written == 0 {
|
|
||||||
return Err(e);
|
|
||||||
} else {
|
|
||||||
return Ok(*total_written);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DirEntry {
|
impl DirEntry {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -228,24 +202,47 @@ impl DirEntry {
|
|||||||
*name = Str256::from(new_name);
|
*name = Str256::from(new_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iterate_entries(&self, mut ctx: &mut DirentWriterContext) -> Result<usize> {
|
fn visit_entry(&self, mut idx: usize, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
||||||
let mut total_written_len = 0;
|
let try_visit = |idx: &mut usize, visitor: &mut dyn DirentVisitor| -> Result<()> {
|
||||||
let idx = ctx.pos();
|
// Read the two special entries("." and "..").
|
||||||
// Write the two special entries
|
if *idx == 0 {
|
||||||
if idx == 0 {
|
let this_inode = self.this.upgrade().unwrap();
|
||||||
let this_inode = self.this.upgrade().unwrap();
|
visitor.visit(
|
||||||
write_inode_entry!(&mut ctx, ".", &this_inode, &mut total_written_len);
|
".",
|
||||||
|
this_inode.metadata().ino as u64,
|
||||||
|
this_inode.metadata().type_,
|
||||||
|
*idx,
|
||||||
|
)?;
|
||||||
|
*idx += 1;
|
||||||
|
}
|
||||||
|
if *idx == 1 {
|
||||||
|
let parent_inode = self.parent.upgrade().unwrap();
|
||||||
|
visitor.visit(
|
||||||
|
"..",
|
||||||
|
parent_inode.metadata().ino as u64,
|
||||||
|
parent_inode.metadata().type_,
|
||||||
|
*idx,
|
||||||
|
)?;
|
||||||
|
*idx += 1;
|
||||||
|
}
|
||||||
|
// Read the normal child entries.
|
||||||
|
for (name, child) in self.children.iter().skip(*idx - 2) {
|
||||||
|
visitor.visit(
|
||||||
|
name.as_ref(),
|
||||||
|
child.metadata().ino as u64,
|
||||||
|
child.metadata().type_,
|
||||||
|
*idx,
|
||||||
|
)?;
|
||||||
|
*idx += 1;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
let initial_idx = idx;
|
||||||
|
match try_visit(&mut idx, visitor) {
|
||||||
|
Err(e) if idx == initial_idx => Err(e),
|
||||||
|
_ => Ok(idx - initial_idx),
|
||||||
}
|
}
|
||||||
if idx <= 1 {
|
|
||||||
let parent_inode = self.parent.upgrade().unwrap();
|
|
||||||
write_inode_entry!(&mut ctx, "..", &parent_inode, &mut total_written_len);
|
|
||||||
}
|
|
||||||
// Write the normal entries
|
|
||||||
let skipped_children = if idx < 2 { 0 } else { idx - 2 };
|
|
||||||
for (name, child) in self.children.iter().skip(skipped_children) {
|
|
||||||
write_inode_entry!(&mut ctx, name, child, &mut total_written_len);
|
|
||||||
}
|
|
||||||
Ok(total_written_len)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_empty_children(&self) -> bool {
|
fn is_empty_children(&self) -> bool {
|
||||||
@ -382,17 +379,17 @@ impl Inode for RamInode {
|
|||||||
Ok(new_inode)
|
Ok(new_inode)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readdir(&self, ctx: &mut DirentWriterContext) -> Result<usize> {
|
fn readdir_at(&self, offset: usize, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
||||||
if self.0.read().metadata.type_ != InodeType::Dir {
|
if self.0.read().metadata.type_ != InodeType::Dir {
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
||||||
}
|
}
|
||||||
let self_inode = self.0.read();
|
let self_inode = self.0.read();
|
||||||
let total_written_len = self_inode
|
let cnt = self_inode
|
||||||
.inner
|
.inner
|
||||||
.as_direntry()
|
.as_direntry()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.iterate_entries(ctx)?;
|
.visit_entry(offset, visitor)?;
|
||||||
Ok(total_written_len)
|
Ok(cnt)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn link(&self, old: &Arc<dyn Inode>, name: &str) -> Result<()> {
|
fn link(&self, old: &Arc<dyn Inode>, name: &str) -> Result<()> {
|
||||||
|
32
src/services/libs/jinux-std/src/fs/utils/dirent_visitor.rs
Normal file
32
src/services/libs/jinux-std/src/fs/utils/dirent_visitor.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
use super::InodeType;
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
/// A visitor for dir entries.
|
||||||
|
pub trait DirentVisitor {
|
||||||
|
/// Visit a dir entry.
|
||||||
|
///
|
||||||
|
/// If the visitor succeeds in visiting the given inode, an `Ok(())` is returned;
|
||||||
|
/// Otherwise, an error is returned. Different implementations for `DirentVisitor`
|
||||||
|
/// may choose to report errors for different reasons. Regardless of the exact
|
||||||
|
/// errors and reasons, `readdir`-family methods shall stop feeding the visitor
|
||||||
|
/// with the next inode as long as an error is returned by the visitor.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// `Vec<String>` is implemented as `DirentVisitor` so that the file names
|
||||||
|
/// under a dir can be easily collected, which is convenient for testing purposes.
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// let mut all_dirents = Vec::new();
|
||||||
|
/// let dir_inode = todo!("create an inode");
|
||||||
|
/// dir_inode.readdir_at(0, &mut all_dirents).unwrap();
|
||||||
|
/// ```
|
||||||
|
fn visit(&mut self, name: &str, ino: u64, type_: InodeType, offset: usize) -> Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DirentVisitor for Vec<String> {
|
||||||
|
fn visit(&mut self, name: &str, ino: u64, type_: InodeType, offset: usize) -> Result<()> {
|
||||||
|
self.push(name.into());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
@ -1,31 +0,0 @@
|
|||||||
use super::InodeType;
|
|
||||||
use crate::prelude::*;
|
|
||||||
|
|
||||||
/// DirentWriterContext is a wrapper of DirentWriter with directory position
|
|
||||||
/// After a successful write, the position increases correspondingly
|
|
||||||
pub struct DirentWriterContext<'a> {
|
|
||||||
pos: usize,
|
|
||||||
writer: &'a mut dyn DirentWriter,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> DirentWriterContext<'a> {
|
|
||||||
pub fn new(pos: usize, writer: &'a mut dyn DirentWriter) -> Self {
|
|
||||||
Self { pos, writer }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write_entry(&mut self, name: &str, ino: u64, type_: InodeType) -> Result<usize> {
|
|
||||||
let written_len = self.writer.write_entry(name, ino, type_)?;
|
|
||||||
self.pos += 1;
|
|
||||||
Ok(written_len)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pos(&self) -> usize {
|
|
||||||
self.pos
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// DirentWriter is used to write directory entry,
|
|
||||||
/// the object which implements it can decide how to format the data
|
|
||||||
pub trait DirentWriter: Sync + Send {
|
|
||||||
fn write_entry(&mut self, name: &str, ino: u64, type_: InodeType) -> Result<usize>;
|
|
||||||
}
|
|
@ -5,7 +5,7 @@ use core::any::Any;
|
|||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use jinux_frame::vm::VmFrame;
|
use jinux_frame::vm::VmFrame;
|
||||||
|
|
||||||
use super::{DirentWriterContext, FileSystem, IoctlCmd, SuperBlock};
|
use super::{DirentVisitor, FileSystem, IoctlCmd, SuperBlock};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
@ -177,7 +177,7 @@ pub trait Inode: Any + Sync + Send {
|
|||||||
|
|
||||||
fn mknod(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<dyn Inode>>;
|
fn mknod(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<dyn Inode>>;
|
||||||
|
|
||||||
fn readdir(&self, ctx: &mut DirentWriterContext) -> Result<usize>;
|
fn readdir_at(&self, offset: usize, visitor: &mut dyn DirentVisitor) -> Result<usize>;
|
||||||
|
|
||||||
fn link(&self, old: &Arc<dyn Inode>, name: &str) -> Result<()>;
|
fn link(&self, old: &Arc<dyn Inode>, name: &str) -> Result<()>;
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
pub use access_mode::AccessMode;
|
pub use access_mode::AccessMode;
|
||||||
pub use creation_flags::CreationFlags;
|
pub use creation_flags::CreationFlags;
|
||||||
pub use dentry_cache::Dentry;
|
pub use dentry_cache::Dentry;
|
||||||
pub use dirent_writer::{DirentWriter, DirentWriterContext};
|
pub use dirent_visitor::DirentVisitor;
|
||||||
pub use events::IoEvents;
|
pub use events::IoEvents;
|
||||||
pub use fcntl::FcntlCmd;
|
pub use fcntl::FcntlCmd;
|
||||||
pub use file_creation_mask::FileCreationMask;
|
pub use file_creation_mask::FileCreationMask;
|
||||||
@ -18,7 +18,7 @@ pub use vnode::Vnode;
|
|||||||
mod access_mode;
|
mod access_mode;
|
||||||
mod creation_flags;
|
mod creation_flags;
|
||||||
mod dentry_cache;
|
mod dentry_cache;
|
||||||
mod dirent_writer;
|
mod dirent_visitor;
|
||||||
mod events;
|
mod events;
|
||||||
mod fcntl;
|
mod fcntl;
|
||||||
mod file_creation_mask;
|
mod file_creation_mask;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use super::{DirentWriterContext, Inode, InodeMode, InodeType, Metadata, PageCacheManager};
|
use super::{DirentVisitor, Inode, InodeMode, InodeType, Metadata, PageCacheManager};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::rights::Rights;
|
use crate::rights::Rights;
|
||||||
use crate::vm::vmo::{Vmo, VmoFlags, VmoOptions};
|
use crate::vm::vmo::{Vmo, VmoFlags, VmoOptions};
|
||||||
@ -164,8 +164,8 @@ impl Vnode {
|
|||||||
self.inner.write().inode.write_link(target)
|
self.inner.write().inode.write_link(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readdir(&self, ctx: &mut DirentWriterContext) -> Result<usize> {
|
pub fn readdir_at(&self, offset: usize, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
||||||
self.inner.read().inode.readdir(ctx)
|
self.inner.read().inode.readdir_at(offset, visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn metadata(&self) -> Metadata {
|
pub fn metadata(&self) -> Metadata {
|
||||||
|
179
src/services/libs/jinux-std/src/syscall/getdents64.rs
Normal file
179
src/services/libs/jinux-std/src/syscall/getdents64.rs
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
use crate::fs::{
|
||||||
|
file_table::FileDescripter,
|
||||||
|
utils::{DirentVisitor, InodeType},
|
||||||
|
};
|
||||||
|
use crate::log_syscall_entry;
|
||||||
|
use crate::prelude::*;
|
||||||
|
use crate::util::write_bytes_to_user;
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
|
use super::SyscallReturn;
|
||||||
|
use super::SYS_GETDENTS64;
|
||||||
|
|
||||||
|
pub fn sys_getdents64(
|
||||||
|
fd: FileDescripter,
|
||||||
|
buf_addr: Vaddr,
|
||||||
|
buf_len: usize,
|
||||||
|
) -> Result<SyscallReturn> {
|
||||||
|
log_syscall_entry!(SYS_GETDENTS64);
|
||||||
|
debug!(
|
||||||
|
"fd = {}, buf_addr = 0x{:x}, buf_len = 0x{:x}",
|
||||||
|
fd, buf_addr, buf_len
|
||||||
|
);
|
||||||
|
|
||||||
|
let current = current!();
|
||||||
|
let file_table = current.file_table().lock();
|
||||||
|
let file = file_table.get_file(fd)?;
|
||||||
|
let inode_handle = file
|
||||||
|
.as_inode_handle()
|
||||||
|
.ok_or(Error::with_message(Errno::EBADE, "not inode"))?;
|
||||||
|
if inode_handle.dentry().inode_type() != InodeType::Dir {
|
||||||
|
return_errno!(Errno::ENOTDIR);
|
||||||
|
}
|
||||||
|
let mut buffer = vec![0u8; buf_len];
|
||||||
|
let mut reader = DirentBufferReader::<Dirent64>::new(&mut buffer);
|
||||||
|
let _ = inode_handle.readdir(&mut reader)?;
|
||||||
|
let read_len = reader.read_len();
|
||||||
|
write_bytes_to_user(buf_addr, &buffer[..read_len])?;
|
||||||
|
Ok(SyscallReturn::Return(read_len as _))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The Buffered DirentReader to visit the dir entry.
|
||||||
|
/// The DirentSerializer T decides how to serialize the data.
|
||||||
|
struct DirentBufferReader<'a, T: DirentSerializer> {
|
||||||
|
buffer: &'a mut [u8],
|
||||||
|
read_len: usize,
|
||||||
|
phantom: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: DirentSerializer> DirentBufferReader<'a, T> {
|
||||||
|
pub fn new(buffer: &'a mut [u8]) -> Self {
|
||||||
|
Self {
|
||||||
|
buffer,
|
||||||
|
read_len: 0,
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_len(&self) -> usize {
|
||||||
|
self.read_len
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: DirentSerializer> DirentVisitor for DirentBufferReader<'a, T> {
|
||||||
|
fn visit(&mut self, name: &str, ino: u64, type_: InodeType, offset: usize) -> Result<()> {
|
||||||
|
let dirent_serializer = T::new(ino, offset as u64, type_, CString::new(name)?);
|
||||||
|
if self.read_len >= self.buffer.len() {
|
||||||
|
return_errno_with_message!(Errno::EINVAL, "buffer is too small");
|
||||||
|
}
|
||||||
|
dirent_serializer.serialize(&mut self.buffer[self.read_len..])?;
|
||||||
|
self.read_len += dirent_serializer.len();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The DirentSerializer can decide how to serialize the data.
|
||||||
|
trait DirentSerializer {
|
||||||
|
/// Create a DirentSerializer.
|
||||||
|
fn new(ino: u64, offset: u64, type_: InodeType, name: CString) -> Self;
|
||||||
|
/// Get the length of a directory entry.
|
||||||
|
fn len(&self) -> usize;
|
||||||
|
/// Try to serialize a directory entry into buffer.
|
||||||
|
fn serialize(&self, buf: &mut [u8]) -> Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Dirent64 {
|
||||||
|
inner: Dirent64Inner,
|
||||||
|
name: CString,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(packed)]
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct Dirent64Inner {
|
||||||
|
d_ino: u64,
|
||||||
|
d_off: u64,
|
||||||
|
d_reclen: u16,
|
||||||
|
d_type: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DirentSerializer for Dirent64 {
|
||||||
|
fn new(ino: u64, offset: u64, type_: InodeType, name: CString) -> Self {
|
||||||
|
let d_reclen = {
|
||||||
|
let len =
|
||||||
|
core::mem::size_of::<Dirent64Inner>() + name.as_c_str().to_bytes_with_nul().len();
|
||||||
|
align_up(len, 8) as u16
|
||||||
|
};
|
||||||
|
let d_type = DirentType::from(type_) as u8;
|
||||||
|
Self {
|
||||||
|
inner: Dirent64Inner {
|
||||||
|
d_ino: ino,
|
||||||
|
d_off: offset,
|
||||||
|
d_reclen,
|
||||||
|
d_type,
|
||||||
|
},
|
||||||
|
name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn len(&self) -> usize {
|
||||||
|
self.inner.d_reclen as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize(&self, buf: &mut [u8]) -> Result<()> {
|
||||||
|
if self.len() > buf.len() {
|
||||||
|
return_errno_with_message!(Errno::EINVAL, "buffer is too small");
|
||||||
|
}
|
||||||
|
|
||||||
|
let d_ino = self.inner.d_ino;
|
||||||
|
let d_off = self.inner.d_off;
|
||||||
|
let d_reclen = self.inner.d_reclen;
|
||||||
|
let d_type = self.inner.d_type;
|
||||||
|
let items: [&[u8]; 5] = [
|
||||||
|
d_ino.as_bytes(),
|
||||||
|
d_off.as_bytes(),
|
||||||
|
d_reclen.as_bytes(),
|
||||||
|
d_type.as_bytes(),
|
||||||
|
self.name.as_c_str().to_bytes_with_nul(),
|
||||||
|
];
|
||||||
|
let mut offset = 0;
|
||||||
|
for item in items {
|
||||||
|
buf[offset..offset + item.len()].copy_from_slice(item);
|
||||||
|
offset += item.len();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
enum DirentType {
|
||||||
|
DT_UNKNOWN = 0,
|
||||||
|
DT_FIFO = 1,
|
||||||
|
DT_CHR = 2,
|
||||||
|
DT_DIR = 4,
|
||||||
|
DT_BLK = 6,
|
||||||
|
DT_REG = 8,
|
||||||
|
DT_LNK = 10,
|
||||||
|
DT_SOCK = 12,
|
||||||
|
DT_WHT = 14,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<InodeType> for DirentType {
|
||||||
|
fn from(type_: InodeType) -> Self {
|
||||||
|
match type_ {
|
||||||
|
InodeType::File => DirentType::DT_REG,
|
||||||
|
InodeType::Dir => DirentType::DT_DIR,
|
||||||
|
InodeType::SymLink => DirentType::DT_LNK,
|
||||||
|
InodeType::CharDevice => DirentType::DT_CHR,
|
||||||
|
InodeType::BlockDevice => DirentType::DT_BLK,
|
||||||
|
InodeType::Socket => DirentType::DT_SOCK,
|
||||||
|
InodeType::NamedPipe => DirentType::DT_FIFO,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn align_up(size: usize, align: usize) -> usize {
|
||||||
|
(size + align - 1) & !(align - 1)
|
||||||
|
}
|
@ -16,6 +16,7 @@ use crate::syscall::fcntl::sys_fcntl;
|
|||||||
use crate::syscall::fork::sys_fork;
|
use crate::syscall::fork::sys_fork;
|
||||||
use crate::syscall::futex::sys_futex;
|
use crate::syscall::futex::sys_futex;
|
||||||
use crate::syscall::getcwd::sys_getcwd;
|
use crate::syscall::getcwd::sys_getcwd;
|
||||||
|
use crate::syscall::getdents64::sys_getdents64;
|
||||||
use crate::syscall::getegid::sys_getegid;
|
use crate::syscall::getegid::sys_getegid;
|
||||||
use crate::syscall::geteuid::sys_geteuid;
|
use crate::syscall::geteuid::sys_geteuid;
|
||||||
use crate::syscall::getgid::sys_getgid;
|
use crate::syscall::getgid::sys_getgid;
|
||||||
@ -79,6 +80,7 @@ mod fcntl;
|
|||||||
mod fork;
|
mod fork;
|
||||||
mod futex;
|
mod futex;
|
||||||
mod getcwd;
|
mod getcwd;
|
||||||
|
mod getdents64;
|
||||||
mod getegid;
|
mod getegid;
|
||||||
mod geteuid;
|
mod geteuid;
|
||||||
mod getgid;
|
mod getgid;
|
||||||
@ -212,6 +214,7 @@ define_syscall_nums!(
|
|||||||
SYS_GETTID = 186,
|
SYS_GETTID = 186,
|
||||||
SYS_TIME = 201,
|
SYS_TIME = 201,
|
||||||
SYS_FUTEX = 202,
|
SYS_FUTEX = 202,
|
||||||
|
SYS_GETDENTS64 = 217,
|
||||||
SYS_SET_TID_ADDRESS = 218,
|
SYS_SET_TID_ADDRESS = 218,
|
||||||
SYS_CLOCK_NANOSLEEP = 230,
|
SYS_CLOCK_NANOSLEEP = 230,
|
||||||
SYS_EXIT_GROUP = 231,
|
SYS_EXIT_GROUP = 231,
|
||||||
@ -342,6 +345,7 @@ pub fn syscall_dispatch(
|
|||||||
SYS_GETTID => syscall_handler!(0, sys_gettid),
|
SYS_GETTID => syscall_handler!(0, sys_gettid),
|
||||||
SYS_TIME => syscall_handler!(1, sys_time, args),
|
SYS_TIME => syscall_handler!(1, sys_time, args),
|
||||||
SYS_FUTEX => syscall_handler!(6, sys_futex, args),
|
SYS_FUTEX => syscall_handler!(6, sys_futex, args),
|
||||||
|
SYS_GETDENTS64 => syscall_handler!(3, sys_getdents64, args),
|
||||||
SYS_SET_TID_ADDRESS => syscall_handler!(1, sys_set_tid_address, args),
|
SYS_SET_TID_ADDRESS => syscall_handler!(1, sys_set_tid_address, args),
|
||||||
SYS_CLOCK_NANOSLEEP => syscall_handler!(4, sys_clock_nanosleep, args),
|
SYS_CLOCK_NANOSLEEP => syscall_handler!(4, sys_clock_nanosleep, args),
|
||||||
SYS_EXIT_GROUP => syscall_handler!(1, sys_exit_group, args),
|
SYS_EXIT_GROUP => syscall_handler!(1, sys_exit_group, args),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user