Support generating fdinfo for most of the existing FileLikes
This commit is contained in:
parent
61a5bb7241
commit
59cd3bd61d
|
|
@ -4,7 +4,10 @@ use alloc::{
|
|||
collections::vec_deque::VecDeque,
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
use core::{
|
||||
fmt::Display,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
|
||||
use keyable_arc::{KeyableArc, KeyableWeak};
|
||||
use ostd::sync::{LocalIrqDisabled, Mutex, MutexGuard, SpinLock, SpinLockGuard};
|
||||
|
|
@ -31,6 +34,15 @@ pub(super) struct Entry {
|
|||
observer: Arc<Observer>,
|
||||
}
|
||||
|
||||
impl Display for Entry {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let inner = self.inner.lock();
|
||||
write!(f, "tfd: {:8} ", self.key.fd)?;
|
||||
write!(f, "events: {:8x} ", inner.event.events.bits())?;
|
||||
write!(f, "data: {:16x}", inner.event.user_data)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub(super) struct EntryKey {
|
||||
fd: FileDesc,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use alloc::{collections::btree_set::BTreeSet, sync::Arc};
|
||||
use core::{borrow::Borrow, time::Duration};
|
||||
use core::{borrow::Borrow, fmt::Display, time::Duration};
|
||||
|
||||
use keyable_arc::KeyableWeak;
|
||||
use ostd::sync::Mutex;
|
||||
|
|
@ -14,9 +14,10 @@ use crate::{
|
|||
events::IoEvents,
|
||||
fs::{
|
||||
file_handle::FileLike,
|
||||
file_table::{get_file_fast, FileDesc},
|
||||
file_table::{get_file_fast, FdFlags, FileDesc},
|
||||
path::RESERVED_MOUNT_ID,
|
||||
pseudofs::anon_inodefs_shared_inode,
|
||||
utils::{Inode, IoctlCmd},
|
||||
utils::{CreationFlags, Inode, IoctlCmd},
|
||||
},
|
||||
prelude::*,
|
||||
process::{
|
||||
|
|
@ -270,6 +271,38 @@ impl FileLike for EpollFile {
|
|||
fn inode(&self) -> &Arc<dyn Inode> {
|
||||
anon_inodefs_shared_inode()
|
||||
}
|
||||
|
||||
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
|
||||
struct FdInfo {
|
||||
inner: Arc<EpollFile>,
|
||||
fd_flags: FdFlags,
|
||||
}
|
||||
|
||||
impl Display for FdInfo {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let mut flags = self.inner.status_flags().bits() | self.inner.access_mode() as u32;
|
||||
if self.fd_flags.contains(FdFlags::CLOEXEC) {
|
||||
flags |= CreationFlags::O_CLOEXEC.bits();
|
||||
}
|
||||
|
||||
writeln!(f, "pos:\t{}", 0)?;
|
||||
writeln!(f, "flags:\t0{:o}", flags)?;
|
||||
// TODO: This should be the mount ID of the pseudo filesystem.
|
||||
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?;
|
||||
writeln!(f, "ino:\t{}", self.inner.inode().ino())?;
|
||||
for entry in self.inner.interest.lock().iter() {
|
||||
writeln!(f, "{}", entry.0)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Box::new(FdInfo {
|
||||
inner: self,
|
||||
fd_flags,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct EntryHolder(Arc<Entry>);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::sync::atomic::AtomicU32;
|
||||
use core::{fmt::Display, sync::atomic::AtomicU32};
|
||||
|
||||
use aster_rights::Rights;
|
||||
use inherit_methods_macro::inherit_methods;
|
||||
|
|
@ -10,10 +10,11 @@ use crate::{
|
|||
events::IoEvents,
|
||||
fs::{
|
||||
file_handle::{FileLike, Mappable},
|
||||
file_table::FdFlags,
|
||||
path::Path,
|
||||
utils::{
|
||||
AccessMode, DirentVisitor, FallocMode, FlockItem, Inode, InodeType, IoctlCmd,
|
||||
RangeLockItem, RangeLockType, SeekFrom, StatusFlags,
|
||||
AccessMode, CreationFlags, DirentVisitor, FallocMode, FlockItem, Inode, InodeType,
|
||||
IoctlCmd, RangeLockItem, RangeLockType, SeekFrom, StatusFlags,
|
||||
},
|
||||
},
|
||||
prelude::*,
|
||||
|
|
@ -206,6 +207,32 @@ impl FileLike for InodeHandle {
|
|||
fn inode(&self) -> &Arc<dyn Inode> {
|
||||
self.0.path.inode()
|
||||
}
|
||||
|
||||
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
|
||||
struct FdInfo {
|
||||
inner: Arc<InodeHandle>,
|
||||
fd_flags: FdFlags,
|
||||
}
|
||||
|
||||
impl Display for FdInfo {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let mut flags = self.inner.status_flags().bits() | self.inner.access_mode() as u32;
|
||||
if self.fd_flags.contains(FdFlags::CLOEXEC) {
|
||||
flags |= CreationFlags::O_CLOEXEC.bits();
|
||||
}
|
||||
|
||||
writeln!(f, "pos:\t{}", self.inner.offset())?;
|
||||
writeln!(f, "flags:\t0{:o}", flags)?;
|
||||
writeln!(f, "mnt_id:\t{}", self.inner.path().mount_node().id())?;
|
||||
writeln!(f, "ino:\t{}", self.inner.inode().ino())
|
||||
}
|
||||
}
|
||||
|
||||
Box::new(FdInfo {
|
||||
inner: self,
|
||||
fd_flags,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for InodeHandle {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
use core::time::Duration;
|
||||
|
||||
use inherit_methods_macro::inherit_methods;
|
||||
pub use mount::{Mount, MountPropType, PerMountFlags};
|
||||
pub use mount::{Mount, MountPropType, PerMountFlags, RESERVED_MOUNT_ID};
|
||||
pub use mount_namespace::MountNamespace;
|
||||
|
||||
use crate::{
|
||||
|
|
|
|||
|
|
@ -40,11 +40,17 @@ impl Default for MountPropType {
|
|||
|
||||
static ID_ALLOCATOR: Once<SpinLock<IdAlloc>> = Once::new();
|
||||
|
||||
/// The reserved mount ID, which represents an invalid mount.
|
||||
pub static RESERVED_MOUNT_ID: usize = 0;
|
||||
|
||||
pub(super) fn init() {
|
||||
// TODO: Make it configurable.
|
||||
const MAX_MOUNT_NUM: usize = 10000;
|
||||
|
||||
ID_ALLOCATOR.call_once(|| SpinLock::new(IdAlloc::with_capacity(MAX_MOUNT_NUM)));
|
||||
let mut id_allocator = IdAlloc::with_capacity(MAX_MOUNT_NUM);
|
||||
let _ = id_allocator.alloc_specific(RESERVED_MOUNT_ID).unwrap(); // Reserve mount ID 0.
|
||||
|
||||
ID_ALLOCATOR.call_once(|| SpinLock::new(id_allocator));
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,19 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
use core::{
|
||||
fmt::Display,
|
||||
sync::atomic::{AtomicU32, Ordering},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
events::IoEvents,
|
||||
fs::{
|
||||
file_handle::FileLike,
|
||||
file_table::FdFlags,
|
||||
path::RESERVED_MOUNT_ID,
|
||||
pipe::common::{PipeReader, PipeWriter},
|
||||
pseudofs::{pipefs_singleton, PseudoInode},
|
||||
utils::{mkmod, AccessMode, Inode, InodeType, StatusFlags},
|
||||
utils::{mkmod, AccessMode, CreationFlags, Inode, InodeType, StatusFlags},
|
||||
},
|
||||
prelude::*,
|
||||
process::{
|
||||
|
|
@ -76,6 +81,21 @@ impl Pollable for PipeReaderFile {
|
|||
}
|
||||
}
|
||||
|
||||
struct FdInfo {
|
||||
flags: u32,
|
||||
ino: u64,
|
||||
}
|
||||
|
||||
impl Display for FdInfo {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
writeln!(f, "pos:\t{}", 0)?;
|
||||
writeln!(f, "flags:\t0{:o}", self.flags)?;
|
||||
// TODO: This should be the mount ID of the pseudo filesystem.
|
||||
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?;
|
||||
writeln!(f, "ino:\t{}", self.ino)
|
||||
}
|
||||
}
|
||||
|
||||
impl FileLike for PipeReaderFile {
|
||||
fn read(&self, writer: &mut VmWriter) -> Result<usize> {
|
||||
if !writer.has_avail() {
|
||||
|
|
@ -109,6 +129,18 @@ impl FileLike for PipeReaderFile {
|
|||
fn inode(&self) -> &Arc<dyn Inode> {
|
||||
&self.pseudo_inode
|
||||
}
|
||||
|
||||
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
|
||||
let mut flags = self.status_flags().bits() | self.access_mode() as u32;
|
||||
if fd_flags.contains(FdFlags::CLOEXEC) {
|
||||
flags |= CreationFlags::O_CLOEXEC.bits();
|
||||
}
|
||||
|
||||
Box::new(FdInfo {
|
||||
flags,
|
||||
ino: self.inode().ino(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for PipeReaderFile {
|
||||
|
|
@ -179,6 +211,18 @@ impl FileLike for PipeWriterFile {
|
|||
fn inode(&self) -> &Arc<dyn Inode> {
|
||||
&self.pseudo_inode
|
||||
}
|
||||
|
||||
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
|
||||
let mut flags = self.status_flags().bits() | self.access_mode() as u32;
|
||||
if fd_flags.contains(FdFlags::CLOEXEC) {
|
||||
flags |= CreationFlags::O_CLOEXEC.bits();
|
||||
}
|
||||
|
||||
Box::new(FdInfo {
|
||||
flags,
|
||||
ino: self.inode().ino(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn check_status_flags(status_flags: StatusFlags) -> Result<()> {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
use alloc::format;
|
||||
use core::{
|
||||
fmt::Display,
|
||||
sync::atomic::{AtomicU32, Ordering},
|
||||
time::Duration,
|
||||
};
|
||||
|
|
@ -19,8 +20,9 @@ use crate::{
|
|||
events::IoEvents,
|
||||
fs::{
|
||||
file_handle::{FileLike, Mappable},
|
||||
file_table::FdFlags,
|
||||
inode_handle::{do_fallocate_util, do_resize_util, do_seek_util},
|
||||
path::check_open_util,
|
||||
path::{check_open_util, RESERVED_MOUNT_ID},
|
||||
tmpfs::TmpFs,
|
||||
utils::{
|
||||
chmod, mkmod, AccessMode, CachePage, CreationFlags, Extension, FallocMode, FileSystem,
|
||||
|
|
@ -469,6 +471,32 @@ impl FileLike for MemfdFile {
|
|||
fn inode(&self) -> &Arc<dyn Inode> {
|
||||
&self.memfd_inode
|
||||
}
|
||||
|
||||
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
|
||||
struct FdInfo {
|
||||
inner: Arc<MemfdFile>,
|
||||
fd_flags: FdFlags,
|
||||
}
|
||||
|
||||
impl Display for FdInfo {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let mut flags = self.inner.status_flags().bits() | self.inner.access_mode() as u32;
|
||||
if self.fd_flags.contains(FdFlags::CLOEXEC) {
|
||||
flags |= CreationFlags::O_CLOEXEC.bits();
|
||||
}
|
||||
|
||||
writeln!(f, "pos:\t{}", *self.inner.offset.lock())?;
|
||||
writeln!(f, "flags:\t0{:o}", flags)?;
|
||||
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?;
|
||||
writeln!(f, "ino:\t{}", self.inner.inode().ino())
|
||||
}
|
||||
}
|
||||
|
||||
Box::new(FdInfo {
|
||||
inner: self,
|
||||
fd_flags,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::fmt::Display;
|
||||
|
||||
use options::SocketOption;
|
||||
use util::{MessageHeader, SendRecvFlags, SockShutdownCmd, SocketAddr};
|
||||
|
||||
use crate::{
|
||||
fs::{
|
||||
file_handle::FileLike,
|
||||
file_table::FdFlags,
|
||||
path::RESERVED_MOUNT_ID,
|
||||
pseudofs::{sockfs_singleton, PseudoInode},
|
||||
utils::{mkmod, Inode, InodeType, StatusFlags},
|
||||
utils::{mkmod, CreationFlags, Inode, InodeType, StatusFlags},
|
||||
},
|
||||
prelude::*,
|
||||
process::{Gid, Uid},
|
||||
|
|
@ -175,6 +179,33 @@ impl<T: Socket + 'static> FileLike for T {
|
|||
fn inode(&self) -> &Arc<dyn Inode> {
|
||||
self.pseudo_inode()
|
||||
}
|
||||
|
||||
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
|
||||
struct FdInfo {
|
||||
flags: u32,
|
||||
ino: u64,
|
||||
}
|
||||
|
||||
impl Display for FdInfo {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
writeln!(f, "pos:\t{}", 0)?;
|
||||
writeln!(f, "flags:\t0{:o}", self.flags)?;
|
||||
// TODO: This should be the mount ID of the pseudo filesystem.
|
||||
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?;
|
||||
writeln!(f, "ino:\t{}", self.ino)
|
||||
}
|
||||
}
|
||||
|
||||
let mut flags = self.status_flags().bits() | self.access_mode() as u32;
|
||||
if fd_flags.contains(FdFlags::CLOEXEC) {
|
||||
flags |= CreationFlags::O_CLOEXEC.bits();
|
||||
}
|
||||
|
||||
Box::new(FdInfo {
|
||||
flags,
|
||||
ino: self.inode().ino(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new pseudo inode for a socket.
|
||||
|
|
|
|||
|
|
@ -1,13 +1,18 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
use core::{
|
||||
fmt::Display,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
events::IoEvents,
|
||||
fs::{
|
||||
file_handle::FileLike,
|
||||
file_table::FdFlags,
|
||||
path::RESERVED_MOUNT_ID,
|
||||
pseudofs::anon_inodefs_shared_inode,
|
||||
utils::{Inode, StatusFlags},
|
||||
utils::{CreationFlags, Inode, StatusFlags},
|
||||
},
|
||||
prelude::*,
|
||||
process::{
|
||||
|
|
@ -92,6 +97,38 @@ impl FileLike for PidFile {
|
|||
fn inode(&self) -> &Arc<dyn Inode> {
|
||||
anon_inodefs_shared_inode()
|
||||
}
|
||||
|
||||
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
|
||||
struct FdInfo {
|
||||
flags: u32,
|
||||
ino: u64,
|
||||
pid: u32,
|
||||
}
|
||||
|
||||
impl Display for FdInfo {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
writeln!(f, "pos:\t{}", 0)?;
|
||||
writeln!(f, "flags:\t0{:o}", self.flags)?;
|
||||
// TODO: This should be the mount ID of the pseudo filesystem.
|
||||
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?;
|
||||
writeln!(f, "ino:\t{}", self.ino)?;
|
||||
writeln!(f, "Pid:\t{}", self.pid)?;
|
||||
// TODO: Currently we do not support PID namespaces. Just print the PID once.
|
||||
writeln!(f, "NSpid:\t{}", self.pid)
|
||||
}
|
||||
}
|
||||
|
||||
let mut flags = self.status_flags().bits() | self.access_mode() as u32;
|
||||
if fd_flags.contains(FdFlags::CLOEXEC) {
|
||||
flags |= CreationFlags::O_CLOEXEC.bits();
|
||||
}
|
||||
|
||||
Box::new(FdInfo {
|
||||
flags,
|
||||
ino: self.inode().ino(),
|
||||
pid: self.process.pid(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Pollable for PidFile {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
//! refer to the man 2 eventfd documentation.
|
||||
//!
|
||||
|
||||
use core::fmt::Display;
|
||||
|
||||
use ostd::sync::WaitQueue;
|
||||
|
||||
use super::SyscallReturn;
|
||||
|
|
@ -22,6 +24,7 @@ use crate::{
|
|||
fs::{
|
||||
file_handle::FileLike,
|
||||
file_table::{FdFlags, FileDesc},
|
||||
path::RESERVED_MOUNT_ID,
|
||||
pseudofs::anon_inodefs_shared_inode,
|
||||
utils::{CreationFlags, Inode, StatusFlags},
|
||||
},
|
||||
|
|
@ -234,4 +237,32 @@ impl FileLike for EventFile {
|
|||
fn inode(&self) -> &Arc<dyn Inode> {
|
||||
anon_inodefs_shared_inode()
|
||||
}
|
||||
|
||||
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
|
||||
struct FdInfo {
|
||||
inner: Arc<EventFile>,
|
||||
fd_flags: FdFlags,
|
||||
}
|
||||
|
||||
impl Display for FdInfo {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let mut flags = self.inner.status_flags().bits() | self.inner.access_mode() as u32;
|
||||
if self.fd_flags.contains(FdFlags::CLOEXEC) {
|
||||
flags |= CreationFlags::O_CLOEXEC.bits();
|
||||
}
|
||||
|
||||
writeln!(f, "pos:\t{}", 0)?;
|
||||
writeln!(f, "flags:\t0{:o}", flags)?;
|
||||
// TODO: This should be the mount ID of the pseudo filesystem.
|
||||
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?;
|
||||
writeln!(f, "ino:\t{}", self.inner.inode().ino())?;
|
||||
writeln!(f, "eventfd-count: {:16x}", *self.inner.counter.lock())
|
||||
}
|
||||
}
|
||||
|
||||
Box::new(FdInfo {
|
||||
inner: self,
|
||||
fd_flags,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@
|
|||
//! enabling better integration with event loops.
|
||||
//! See https://man7.org/linux/man-pages/man2/signalfd.2.html
|
||||
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
use core::{
|
||||
fmt::Display,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
|
||||
use bitflags::bitflags;
|
||||
|
||||
|
|
@ -16,6 +19,7 @@ use crate::{
|
|||
fs::{
|
||||
file_handle::FileLike,
|
||||
file_table::{get_file_fast, FdFlags, FileDesc},
|
||||
path::RESERVED_MOUNT_ID,
|
||||
pseudofs::anon_inodefs_shared_inode,
|
||||
utils::{CreationFlags, Inode, StatusFlags},
|
||||
},
|
||||
|
|
@ -261,6 +265,36 @@ impl FileLike for SignalFile {
|
|||
fn inode(&self) -> &Arc<dyn Inode> {
|
||||
anon_inodefs_shared_inode()
|
||||
}
|
||||
|
||||
fn dump_proc_fdinfo(self: Arc<Self>, fd_flags: FdFlags) -> Box<dyn Display> {
|
||||
struct FdInfo {
|
||||
flags: u32,
|
||||
ino: u64,
|
||||
sigmask: u64,
|
||||
}
|
||||
|
||||
impl Display for FdInfo {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
writeln!(f, "pos:\t{}", 0)?;
|
||||
writeln!(f, "flags:\t0{:o}", self.flags)?;
|
||||
// TODO: This should be the mount ID of the pseudo filesystem.
|
||||
writeln!(f, "mnt_id:\t{}", RESERVED_MOUNT_ID)?;
|
||||
writeln!(f, "ino:\t{}", self.ino)?;
|
||||
writeln!(f, "sigmask:\t{:016x}", self.sigmask)
|
||||
}
|
||||
}
|
||||
|
||||
let mut flags = self.status_flags().bits() | self.access_mode() as u32;
|
||||
if fd_flags.contains(FdFlags::CLOEXEC) {
|
||||
flags |= CreationFlags::O_CLOEXEC.bits();
|
||||
}
|
||||
|
||||
Box::new(FdInfo {
|
||||
flags,
|
||||
ino: self.inode().ino(),
|
||||
sigmask: self.mask().load(Ordering::Relaxed).into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
|
|
|||
Loading…
Reference in New Issue