Enable read and write operations of the attribute to handle offset

This commit is contained in:
Chen Chengjun
2025-06-06 07:16:01 +00:00
committed by Tate, Hongliang Tian
parent 3b1248ba7c
commit 1dd1c8c775
4 changed files with 49 additions and 9 deletions

View File

@ -76,6 +76,8 @@ pub enum Error {
PermissionDenied,
/// Other internal error
InternalError(&'static str),
/// Arithmetic overflow occurred
Overflow,
}
impl core::fmt::Display for Error {
@ -88,6 +90,7 @@ impl core::fmt::Display for Error {
Error::AttributeError => write!(f, "Attribute error"),
Error::PermissionDenied => write!(f, "Permission denied for operation"),
Error::InternalError(msg) => write!(f, "Internal error: {}", msg),
Error::Overflow => write!(f, "Numerical overflow occurred"),
}
}
}

View File

@ -118,6 +118,33 @@ pub trait SysNode: SysObj {
/// Writes the value of an attribute.
fn write_attr(&self, name: &str, reader: &mut VmReader) -> Result<usize>;
/// Reads the value of an attribute from the specified `offset`.
fn read_attr_at(&self, name: &str, offset: usize, writer: &mut VmWriter) -> Result<usize> {
let (attr_buffer, attr_len) = {
let attr_buffer_len = writer.avail().checked_add(offset).ok_or(Error::Overflow)?;
let mut buffer = vec![0; attr_buffer_len];
let len = self.read_attr(
name,
&mut VmWriter::from(buffer.as_mut_slice()).to_fallible(),
)?;
(buffer, len)
};
if attr_len <= offset {
return Ok(0);
}
writer
.write_fallible(VmReader::from(attr_buffer.as_slice()).skip(offset))
.map_err(|_| Error::AttributeError)
}
/// Writes the value of an attribute at the specified `offset`.
fn write_attr_at(&self, name: &str, _offset: usize, reader: &mut VmReader) -> Result<usize> {
// In general, the `offset` for attribute write operations is ignored directly.
self.write_attr(name, reader)
}
/// Shows the string value of an attribute.
///
/// Most attributes are textual, rather binary (see `SysAttrFlags::IS_BINARY`).

View File

@ -339,6 +339,7 @@ impl From<aster_systree::Error> for Error {
AttributeError => Error::new(Errno::EIO),
PermissionDenied => Error::new(Errno::EACCES),
InternalError(msg) => Error::with_message(Errno::EIO, msg),
Overflow => Error::new(Errno::EOVERFLOW),
}
}
}

View File

@ -376,29 +376,38 @@ impl Inode for SysFsInode {
self.read_direct_at(offset, buf)
}
fn read_direct_at(&self, _offset: usize, buf: &mut VmWriter) -> Result<usize> {
// TODO: it is unclear whether we should simply ignore the offset
// or report errors if it is non-zero.
fn read_direct_at(&self, offset: usize, buf: &mut VmWriter) -> Result<usize> {
let InnerNode::Attr(attr, leaf) = &self.inner_node else {
return Err(Error::new(Errno::EINVAL));
};
// TODO: check read permission
Ok(leaf.read_attr(attr.name(), buf)?)
let len = if offset == 0 {
leaf.read_attr(attr.name(), buf)?
} else {
// The `read_attr_at` method is more general than `read_attr`,
// but it could be less efficient. So we only use the more general form when necessary.
leaf.read_attr_at(attr.name(), offset, buf)?
};
Ok(len)
}
fn write_at(&self, offset: usize, buf: &mut VmReader) -> Result<usize> {
self.write_direct_at(offset, buf)
}
fn write_direct_at(&self, _offset: usize, buf: &mut VmReader) -> Result<usize> {
fn write_direct_at(&self, offset: usize, buf: &mut VmReader) -> Result<usize> {
let InnerNode::Attr(attr, leaf) = &self.inner_node else {
return Err(Error::new(Errno::EINVAL));
};
// TODO: check write permission
Ok(leaf.write_attr(attr.name(), buf)?)
let len = if offset == 0 {
leaf.write_attr(attr.name(), buf)?
} else {
leaf.write_attr_at(attr.name(), offset, buf)?
};
Ok(len)
}
fn create(&self, _name: &str, _type_: InodeType, _mode: InodeMode) -> Result<Arc<dyn Inode>> {