mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-21 16:33:24 +00:00
Enable read and write operations of the attribute to handle offset
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
3b1248ba7c
commit
1dd1c8c775
@ -76,6 +76,8 @@ pub enum Error {
|
|||||||
PermissionDenied,
|
PermissionDenied,
|
||||||
/// Other internal error
|
/// Other internal error
|
||||||
InternalError(&'static str),
|
InternalError(&'static str),
|
||||||
|
/// Arithmetic overflow occurred
|
||||||
|
Overflow,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core::fmt::Display for Error {
|
impl core::fmt::Display for Error {
|
||||||
@ -88,6 +90,7 @@ impl core::fmt::Display for Error {
|
|||||||
Error::AttributeError => write!(f, "Attribute error"),
|
Error::AttributeError => write!(f, "Attribute error"),
|
||||||
Error::PermissionDenied => write!(f, "Permission denied for operation"),
|
Error::PermissionDenied => write!(f, "Permission denied for operation"),
|
||||||
Error::InternalError(msg) => write!(f, "Internal error: {}", msg),
|
Error::InternalError(msg) => write!(f, "Internal error: {}", msg),
|
||||||
|
Error::Overflow => write!(f, "Numerical overflow occurred"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,6 +118,33 @@ pub trait SysNode: SysObj {
|
|||||||
/// Writes the value of an attribute.
|
/// Writes the value of an attribute.
|
||||||
fn write_attr(&self, name: &str, reader: &mut VmReader) -> Result<usize>;
|
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.
|
/// Shows the string value of an attribute.
|
||||||
///
|
///
|
||||||
/// Most attributes are textual, rather binary (see `SysAttrFlags::IS_BINARY`).
|
/// Most attributes are textual, rather binary (see `SysAttrFlags::IS_BINARY`).
|
||||||
|
@ -339,6 +339,7 @@ impl From<aster_systree::Error> for Error {
|
|||||||
AttributeError => Error::new(Errno::EIO),
|
AttributeError => Error::new(Errno::EIO),
|
||||||
PermissionDenied => Error::new(Errno::EACCES),
|
PermissionDenied => Error::new(Errno::EACCES),
|
||||||
InternalError(msg) => Error::with_message(Errno::EIO, msg),
|
InternalError(msg) => Error::with_message(Errno::EIO, msg),
|
||||||
|
Overflow => Error::new(Errno::EOVERFLOW),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -376,29 +376,38 @@ impl Inode for SysFsInode {
|
|||||||
self.read_direct_at(offset, buf)
|
self.read_direct_at(offset, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_direct_at(&self, _offset: usize, buf: &mut VmWriter) -> Result<usize> {
|
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.
|
|
||||||
|
|
||||||
let InnerNode::Attr(attr, leaf) = &self.inner_node else {
|
let InnerNode::Attr(attr, leaf) = &self.inner_node else {
|
||||||
return Err(Error::new(Errno::EINVAL));
|
return Err(Error::new(Errno::EINVAL));
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: check read permission
|
let len = if offset == 0 {
|
||||||
Ok(leaf.read_attr(attr.name(), buf)?)
|
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> {
|
fn write_at(&self, offset: usize, buf: &mut VmReader) -> Result<usize> {
|
||||||
self.write_direct_at(offset, buf)
|
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 {
|
let InnerNode::Attr(attr, leaf) = &self.inner_node else {
|
||||||
return Err(Error::new(Errno::EINVAL));
|
return Err(Error::new(Errno::EINVAL));
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: check write permission
|
let len = if offset == 0 {
|
||||||
Ok(leaf.write_attr(attr.name(), buf)?)
|
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>> {
|
fn create(&self, _name: &str, _type_: InodeType, _mode: InodeMode) -> Result<Arc<dyn Inode>> {
|
||||||
|
Reference in New Issue
Block a user