pub struct DynamicFile<Source: SequenceFileSource> { /* private fields */ }Expand description
DynamicFile implements FileOps for files whose contents are generated by the kernel
dynamically either from a sequence (see SequenceFileSource) or as a single blob of data
(see DynamicFileSource). The file may be updated dynamically as it’s normally expected
for files in /proc, e.g. when seeking back from the current position.
The following example shows how DynamicFile can be used with a DynamicFileSource:
#[derive(Clone)]
pub struct SimpleFile(u32);
impl SimpleFile {
pub fn new_node(param: u32) -> impl FsNodeOps {
DynamicFile::new_node(Self(param))
}
}
impl DynamicFileSource for SimpleFile {
fn generate(&self, sink: &mut DynamicFileBuf) -> Result<(), Errno> {
writeln!(sink, "param: {}", self.0)?
Ok(())
}
}SequenceFileSource should be used to generate file contents from a sequence of objects.
SequenceFileSource::next() takes the cursor for the current position, outputs the next
chunk of data in the sequence, and returns the the advanced cursor value. At the start of
iteration, the cursor is Default::default(). The end of the sequence is indicated by
returning None.
The next example generates the contents from a sequence of integer values:
[#derive(Clone)]
struct IntegersFile;
impl SequenceFileSource for IntegersFile {
type Cursor = usize;
fn next(&self, cursor: usize, sink: &mut DynamicFileBuf) -> Result<Option<usize>, Errno> {
// The cursor starts at i32::default(), which is 0.
writeln!(sink, "{}", cursor)?;
if cursor > 1000 {
// End of the sequence.
return Ok(None);
}
Ok(Some(cursor + 1))
}
}Writable files should wrap DynamicFile and delegate it read() and seek() using the
fileops_impl_delegate_read_and_seek! macro, as shown in the example below:
struct WritableProcFileSource {
data: usize,
}
impl DynamicFileSource for WritableProcFileSource {
fn generate(&self, sink: &mut DynamicFileBuf) -> Result<(), Errno> {
writeln!("{}", self.data);
Ok(())
}
}
pub struct WritableProcFile {
dynamic_file: DynamicFile<WritableProcFileSource>,
...
}
impl WritableProcFile {
fn new() -> Self {
Self { dynamic_file: DynamicFile::new(WritableProcFileSource { data: 42 }) }
}
}
impl FileOps for WritableProcFile {
fileops_impl_delegate_read_and_seek!(self, self.dynamic_file);
fn write(
&self,
_file: &FileObject,
_current_task: &CurrentTask,
_offset: usize,
data: &mut dyn InputBuffer,
) -> Result<usize, Errno> {
... Process write() ...
}
}Implementations§
Source§impl<Source: SequenceFileSource> DynamicFile<Source>
impl<Source: SequenceFileSource> DynamicFile<Source>
Source§impl<Source: SequenceFileSource + Clone> DynamicFile<Source>
impl<Source: SequenceFileSource + Clone> DynamicFile<Source>
Trait Implementations§
Source§impl<Source: SequenceFileSource> FileOps for DynamicFile<Source>
impl<Source: SequenceFileSource> FileOps for DynamicFile<Source>
Source§fn sync(
&self,
file: &FileObject,
_current_task: &CurrentTask,
) -> Result<(), Errno>
fn sync( &self, file: &FileObject, _current_task: &CurrentTask, ) -> Result<(), Errno>
Source§fn is_seekable(&self) -> bool
fn is_seekable(&self) -> bool
Source§fn read(
&self,
locked: &mut Locked<FileOpsCore>,
_file: &FileObject,
current_task: &CurrentTask,
offset: usize,
data: &mut dyn OutputBuffer,
) -> Result<usize, Errno>
fn read( &self, locked: &mut Locked<FileOpsCore>, _file: &FileObject, current_task: &CurrentTask, offset: usize, data: &mut dyn OutputBuffer, ) -> Result<usize, Errno>
Source§fn write(
&self,
_locked: &mut Locked<FileOpsCore>,
_file: &FileObject,
_current_task: &CurrentTask,
_offset: usize,
_data: &mut dyn InputBuffer,
) -> Result<usize, Errno>
fn write( &self, _locked: &mut Locked<FileOpsCore>, _file: &FileObject, _current_task: &CurrentTask, _offset: usize, _data: &mut dyn InputBuffer, ) -> Result<usize, Errno>
Source§fn seek(
&self,
locked: &mut Locked<FileOpsCore>,
_file: &FileObject,
current_task: &CurrentTask,
current_offset: off_t,
target: SeekTarget,
) -> Result<off_t, Errno>
fn seek( &self, locked: &mut Locked<FileOpsCore>, _file: &FileObject, current_task: &CurrentTask, current_offset: off_t, target: SeekTarget, ) -> Result<off_t, Errno>
current_offset if the file is seekable.Source§fn open(
&self,
_locked: &mut Locked<FileOpsCore>,
_file: &FileObject,
_current_task: &CurrentTask,
) -> Result<(), Errno>
fn open( &self, _locked: &mut Locked<FileOpsCore>, _file: &FileObject, _current_task: &CurrentTask, ) -> Result<(), Errno>
Source§fn close(
self: Box<Self>,
_locked: &mut Locked<FileOpsCore>,
_file: &FileObjectState,
_current_task: &CurrentTask,
)
fn close( self: Box<Self>, _locked: &mut Locked<FileOpsCore>, _file: &FileObjectState, _current_task: &CurrentTask, )
Source§fn flush(
&self,
_locked: &mut Locked<FileOpsCore>,
_file: &FileObject,
_current_task: &CurrentTask,
)
fn flush( &self, _locked: &mut Locked<FileOpsCore>, _file: &FileObject, _current_task: &CurrentTask, )
Source§fn has_persistent_offsets(&self) -> bool
fn has_persistent_offsets(&self) -> bool
false is only
optimization and will makes FileObject never hold the offset lock when calling read and
write.Source§fn writes_update_seek_offset(&self) -> bool
fn writes_update_seek_offset(&self) -> bool
write() operations on the file will update the seek offset.Source§fn data_sync(
&self,
file: &FileObject,
current_task: &CurrentTask,
) -> Result<(), Errno>
fn data_sync( &self, file: &FileObject, current_task: &CurrentTask, ) -> Result<(), Errno>
Source§fn get_memory(
&self,
_locked: &mut Locked<FileOpsCore>,
_file: &FileObject,
_current_task: &CurrentTask,
_length: Option<usize>,
_prot: ProtectionFlags,
) -> Result<Arc<MemoryObject>, Errno>
fn get_memory( &self, _locked: &mut Locked<FileOpsCore>, _file: &FileObject, _current_task: &CurrentTask, _length: Option<usize>, _prot: ProtectionFlags, ) -> Result<Arc<MemoryObject>, Errno>
length is a hint for the desired size of the VMO. The returned VMO may be larger or
smaller than the requested length.
This method is typically called by Self::mmap.Source§fn mmap(
&self,
locked: &mut Locked<FileOpsCore>,
file: &FileObject,
current_task: &CurrentTask,
addr: DesiredAddress,
memory_offset: u64,
length: usize,
prot_flags: ProtectionFlags,
options: MappingOptions,
filename: NamespaceNode,
) -> Result<UserAddress, Errno>
fn mmap( &self, locked: &mut Locked<FileOpsCore>, file: &FileObject, current_task: &CurrentTask, addr: DesiredAddress, memory_offset: u64, length: usize, prot_flags: ProtectionFlags, options: MappingOptions, filename: NamespaceNode, ) -> Result<UserAddress, Errno>
Self::get_memory to get a VMO
and then maps it with [crate::mm::MemoryManager::map].
Only implement this trait method if your file needs to control mapping, or record where
a VMO gets mapped.Source§fn readdir(
&self,
_locked: &mut Locked<FileOpsCore>,
_file: &FileObject,
_current_task: &CurrentTask,
_sink: &mut dyn DirentSink,
) -> Result<(), Errno>
fn readdir( &self, _locked: &mut Locked<FileOpsCore>, _file: &FileObject, _current_task: &CurrentTask, _sink: &mut dyn DirentSink, ) -> Result<(), Errno>
Source§fn wait_async(
&self,
_locked: &mut Locked<FileOpsCore>,
_file: &FileObject,
_current_task: &CurrentTask,
_waiter: &Waiter,
_events: FdEvents,
_handler: EventHandler,
) -> Option<WaitCanceler>
fn wait_async( &self, _locked: &mut Locked<FileOpsCore>, _file: &FileObject, _current_task: &CurrentTask, _waiter: &Waiter, _events: FdEvents, _handler: EventHandler, ) -> Option<WaitCanceler>
None if this file does not support blocking waits. Read moreSource§fn query_events(
&self,
_locked: &mut Locked<FileOpsCore>,
_file: &FileObject,
_current_task: &CurrentTask,
) -> Result<FdEvents, Errno>
fn query_events( &self, _locked: &mut Locked<FileOpsCore>, _file: &FileObject, _current_task: &CurrentTask, ) -> Result<FdEvents, Errno>
fn ioctl( &self, locked: &mut Locked<Unlocked>, file: &FileObject, current_task: &CurrentTask, request: u32, arg: SyscallArg, ) -> Result<SyscallResult, Errno>
fn fcntl( &self, _file: &FileObject, _current_task: &CurrentTask, cmd: u32, _arg: u64, ) -> Result<SyscallResult, Errno>
Source§fn to_handle(
&self,
file: &FileObject,
current_task: &CurrentTask,
) -> Result<Option<NullableHandle>, Errno>
fn to_handle( &self, file: &FileObject, current_task: &CurrentTask, ) -> Result<Option<NullableHandle>, Errno>
Source§fn as_thread_group_key(
&self,
_file: &FileObject,
) -> Result<ThreadGroupKey, Errno>
fn as_thread_group_key( &self, _file: &FileObject, ) -> Result<ThreadGroupKey, Errno>
fn readahead( &self, _file: &FileObject, _current_task: &CurrentTask, _offset: usize, _length: usize, ) -> Result<(), Errno>
Source§fn extra_fdinfo(
&self,
_locked: &mut Locked<FileOpsCore>,
_file: &FileHandle,
_current_task: &CurrentTask,
) -> Option<FsString>
fn extra_fdinfo( &self, _locked: &mut Locked<FileOpsCore>, _file: &FileHandle, _current_task: &CurrentTask, ) -> Option<FsString>
Auto Trait Implementations§
impl<Source> !Freeze for DynamicFile<Source>
impl<Source> !RefUnwindSafe for DynamicFile<Source>
impl<Source> Send for DynamicFile<Source>
impl<Source> Sync for DynamicFile<Source>
impl<Source> Unpin for DynamicFile<Source>
impl<Source> UnwindSafe for DynamicFile<Source>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T, D> Encode<Ambiguous1, D> for Twhere
D: ResourceDialect,
impl<T, D> Encode<Ambiguous1, D> for Twhere
D: ResourceDialect,
Source§impl<T, D> Encode<Ambiguous2, D> for Twhere
D: ResourceDialect,
impl<T, D> Encode<Ambiguous2, D> for Twhere
D: ResourceDialect,
§impl<T> InstanceFromServiceTransport<T> for T
impl<T> InstanceFromServiceTransport<T> for T
§fn from_service_transport(handle: T) -> T
fn from_service_transport(handle: T) -> T
T to [Self]Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more