mod.rs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. use alloc::string::ToString;
  2. use core::{cmp::min, fmt::Debug, intrinsics::unlikely};
  3. use alloc::{
  4. string::String,
  5. sync::{Arc, Weak},
  6. vec::Vec,
  7. };
  8. use hashbrown::HashMap;
  9. use log::warn;
  10. use system_error::SystemError;
  11. use crate::{
  12. driver::base::device::device_number::DeviceNumber,
  13. libs::{
  14. casting::DowncastArc,
  15. rwlock::RwLock,
  16. spinlock::{SpinLock, SpinLockGuard},
  17. },
  18. time::PosixTimeSpec,
  19. };
  20. use self::callback::{KernCallbackData, KernFSCallback, KernInodePrivateData};
  21. use super::vfs::{
  22. file::FileMode, syscall::ModeType, vcore::generate_inode_id, FilePrivateData, FileSystem,
  23. FileType, FsInfo, IndexNode, InodeId, Magic, Metadata, SuperBlock,
  24. };
  25. pub mod callback;
  26. #[derive(Debug)]
  27. pub struct KernFS {
  28. root_inode: Arc<KernFSInode>,
  29. fsname: &'static str,
  30. }
  31. impl FileSystem for KernFS {
  32. fn as_any_ref(&self) -> &dyn core::any::Any {
  33. self
  34. }
  35. fn info(&self) -> FsInfo {
  36. return FsInfo {
  37. blk_dev_id: 0,
  38. max_name_len: KernFS::MAX_NAMELEN,
  39. };
  40. }
  41. fn root_inode(&self) -> Arc<dyn IndexNode> {
  42. return self.root_inode.clone();
  43. }
  44. fn name(&self) -> &str {
  45. self.fsname
  46. }
  47. fn super_block(&self) -> SuperBlock {
  48. SuperBlock::new(
  49. Magic::KER_MAGIC,
  50. KernFS::KERNFS_BLOCK_SIZE,
  51. KernFS::MAX_NAMELEN as u64,
  52. )
  53. }
  54. }
  55. impl KernFS {
  56. pub const MAX_NAMELEN: usize = 4096;
  57. pub const KERNFS_BLOCK_SIZE: u64 = 512;
  58. #[inline(never)]
  59. pub fn new(fsname: &'static str) -> Arc<Self> {
  60. let root_inode = Self::create_root_inode();
  61. let fs = Arc::new(Self {
  62. root_inode: root_inode.clone(),
  63. fsname,
  64. });
  65. root_inode.inner.write().parent = Arc::downgrade(&root_inode);
  66. *root_inode.fs.write() = Arc::downgrade(&fs);
  67. return fs;
  68. }
  69. fn create_root_inode() -> Arc<KernFSInode> {
  70. let metadata = Metadata {
  71. size: 0,
  72. mode: ModeType::from_bits_truncate(0o755),
  73. uid: 0,
  74. gid: 0,
  75. blk_size: 0,
  76. blocks: 0,
  77. atime: PosixTimeSpec::new(0, 0),
  78. mtime: PosixTimeSpec::new(0, 0),
  79. ctime: PosixTimeSpec::new(0, 0),
  80. btime: PosixTimeSpec::new(0, 0),
  81. dev_id: 0,
  82. inode_id: generate_inode_id(),
  83. file_type: FileType::Dir,
  84. nlinks: 1,
  85. raw_dev: DeviceNumber::default(),
  86. };
  87. let root_inode = Arc::new_cyclic(|self_ref| KernFSInode {
  88. name: String::from(""),
  89. inner: RwLock::new(InnerKernFSInode {
  90. parent: Weak::new(),
  91. metadata,
  92. symlink_target: None,
  93. symlink_target_absolute_path: None,
  94. }),
  95. self_ref: self_ref.clone(),
  96. fs: RwLock::new(Weak::new()),
  97. private_data: SpinLock::new(None),
  98. callback: None,
  99. children: SpinLock::new(HashMap::new()),
  100. inode_type: KernInodeType::Dir,
  101. lazy_list: SpinLock::new(HashMap::new()),
  102. });
  103. return root_inode;
  104. }
  105. }
  106. #[derive(Debug)]
  107. pub struct KernFSInode {
  108. inner: RwLock<InnerKernFSInode>,
  109. /// 指向当前Inode所属的文件系统的弱引用
  110. fs: RwLock<Weak<KernFS>>,
  111. /// 指向自身的弱引用
  112. self_ref: Weak<KernFSInode>,
  113. /// 私有数据
  114. private_data: SpinLock<Option<KernInodePrivateData>>,
  115. /// 回调函数
  116. callback: Option<&'static dyn KernFSCallback>,
  117. /// 子Inode
  118. children: SpinLock<HashMap<String, Arc<KernFSInode>>>,
  119. /// Inode类型
  120. inode_type: KernInodeType,
  121. /// Inode名称
  122. name: String,
  123. /// lazy list
  124. lazy_list: SpinLock<HashMap<String, fn() -> KernFSInodeArgs>>,
  125. }
  126. pub struct KernFSInodeArgs {
  127. pub mode: ModeType,
  128. pub inode_type: KernInodeType,
  129. pub size: Option<usize>,
  130. pub private_data: Option<KernInodePrivateData>,
  131. pub callback: Option<&'static dyn KernFSCallback>,
  132. }
  133. #[derive(Debug)]
  134. pub struct InnerKernFSInode {
  135. parent: Weak<KernFSInode>,
  136. /// 当前inode的元数据
  137. metadata: Metadata,
  138. /// 符号链接指向的inode(仅当inode_type为SymLink时有效)
  139. symlink_target: Option<Weak<KernFSInode>>,
  140. symlink_target_absolute_path: Option<String>,
  141. }
  142. impl IndexNode for KernFSInode {
  143. fn as_any_ref(&self) -> &dyn core::any::Any {
  144. self
  145. }
  146. fn open(
  147. &self,
  148. _data: SpinLockGuard<FilePrivateData>,
  149. _mode: &FileMode,
  150. ) -> Result<(), SystemError> {
  151. if let Some(callback) = self.callback {
  152. let callback_data =
  153. KernCallbackData::new(self.self_ref.upgrade().unwrap(), self.private_data.lock());
  154. return callback.open(callback_data);
  155. }
  156. return Ok(());
  157. }
  158. fn close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> {
  159. return Ok(());
  160. }
  161. fn metadata(&self) -> Result<Metadata, SystemError> {
  162. return Ok(self.inner.read().metadata.clone());
  163. }
  164. fn set_metadata(&self, _metadata: &Metadata) -> Result<(), SystemError> {
  165. // 若文件系统没有实现此方法,则返回“不支持”
  166. return Err(SystemError::ENOSYS);
  167. }
  168. fn resize(&self, _len: usize) -> Result<(), SystemError> {
  169. return Ok(());
  170. }
  171. fn create_with_data(
  172. &self,
  173. _name: &str,
  174. _file_type: FileType,
  175. _mode: ModeType,
  176. _data: usize,
  177. ) -> Result<Arc<dyn IndexNode>, SystemError> {
  178. // 应当通过kernfs的其它方法来创建文件,而不能从用户态直接调用此方法。
  179. return Err(SystemError::ENOSYS);
  180. }
  181. fn link(&self, _name: &str, _other: &Arc<dyn IndexNode>) -> Result<(), SystemError> {
  182. // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。
  183. return Err(SystemError::ENOSYS);
  184. }
  185. fn unlink(&self, _name: &str) -> Result<(), SystemError> {
  186. // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。
  187. return Err(SystemError::ENOSYS);
  188. }
  189. fn rmdir(&self, _name: &str) -> Result<(), SystemError> {
  190. // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。
  191. return Err(SystemError::ENOSYS);
  192. }
  193. fn move_to(
  194. &self,
  195. _old_name: &str,
  196. _target: &Arc<dyn IndexNode>,
  197. _new_name: &str,
  198. ) -> Result<(), SystemError> {
  199. // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。
  200. return Err(SystemError::ENOSYS);
  201. }
  202. fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
  203. if unlikely(name.len() > KernFS::MAX_NAMELEN) {
  204. return Err(SystemError::ENAMETOOLONG);
  205. }
  206. if unlikely(self.inode_type != KernInodeType::Dir) {
  207. return Err(SystemError::ENOTDIR);
  208. }
  209. match name {
  210. "" | "." => {
  211. return Ok(self.self_ref.upgrade().ok_or(SystemError::ENOENT)?);
  212. }
  213. ".." => {
  214. return Ok(self
  215. .inner
  216. .read()
  217. .parent
  218. .upgrade()
  219. .ok_or(SystemError::ENOENT)?);
  220. }
  221. name => {
  222. // 在子目录项中查找
  223. let child = self.children.lock().get(name).cloned();
  224. if let Some(child) = child {
  225. return Ok(child);
  226. }
  227. let lazy_list = self.lazy_list.lock();
  228. if let Some(provider) = lazy_list.get(name) {
  229. // 如果存在lazy list,则调用提供者函数创建
  230. let args = provider();
  231. let inode = self.inner_create(
  232. name.to_string(),
  233. args.inode_type,
  234. args.mode,
  235. args.size.unwrap_or(4096),
  236. args.private_data,
  237. args.callback,
  238. )?;
  239. return Ok(inode);
  240. }
  241. Err(SystemError::ENOENT)
  242. }
  243. }
  244. }
  245. fn get_entry_name(&self, ino: InodeId) -> Result<String, SystemError> {
  246. if self.inode_type != KernInodeType::Dir {
  247. return Err(SystemError::ENOTDIR);
  248. }
  249. let children = self.children.lock();
  250. let r = children
  251. .iter()
  252. .find(|(_, v)| v.metadata().unwrap().inode_id == ino)
  253. .map(|(k, _)| k.clone());
  254. return r.ok_or(SystemError::ENOENT);
  255. }
  256. fn get_entry_name_and_metadata(&self, ino: InodeId) -> Result<(String, Metadata), SystemError> {
  257. // 如果有条件,请在文件系统中使用高效的方式实现本接口,而不是依赖这个低效率的默认实现。
  258. let name = self.get_entry_name(ino)?;
  259. let entry = self.find(&name)?;
  260. return Ok((name, entry.metadata()?));
  261. }
  262. fn ioctl(
  263. &self,
  264. _cmd: u32,
  265. _data: usize,
  266. _private_data: &FilePrivateData,
  267. ) -> Result<usize, SystemError> {
  268. // 若文件系统没有实现此方法,则返回“不支持”
  269. return Err(SystemError::ENOSYS);
  270. }
  271. fn truncate(&self, _len: usize) -> Result<(), SystemError> {
  272. // 应当通过kernfs的其它方法来操作文件,而不能从用户态直接调用此方法。
  273. return Err(SystemError::ENOSYS);
  274. }
  275. fn sync(&self) -> Result<(), SystemError> {
  276. return Ok(());
  277. }
  278. fn fs(&self) -> Arc<dyn FileSystem> {
  279. return self.fs.read().upgrade().unwrap();
  280. }
  281. fn list(&self) -> Result<Vec<String>, SystemError> {
  282. let info = self.metadata()?;
  283. if info.file_type != FileType::Dir {
  284. return Err(SystemError::ENOTDIR);
  285. }
  286. let mut keys: Vec<String> = Vec::new();
  287. keys.push(String::from("."));
  288. keys.push(String::from(".."));
  289. self.children
  290. .lock()
  291. .keys()
  292. .for_each(|x| keys.push(x.clone()));
  293. return Ok(keys);
  294. }
  295. fn read_at(
  296. &self,
  297. offset: usize,
  298. len: usize,
  299. buf: &mut [u8],
  300. data: SpinLockGuard<FilePrivateData>,
  301. ) -> Result<usize, SystemError> {
  302. if self.inode_type == KernInodeType::SymLink {
  303. let inner = self.inner.read();
  304. if offset >= inner.symlink_target_absolute_path.as_ref().unwrap().len() {
  305. return Ok(0);
  306. }
  307. let len = min(len, buf.len());
  308. let len = min(
  309. len,
  310. inner.symlink_target_absolute_path.as_ref().unwrap().len() - offset,
  311. );
  312. buf[0..len].copy_from_slice(
  313. &inner
  314. .symlink_target_absolute_path
  315. .as_ref()
  316. .unwrap()
  317. .as_bytes()[offset..offset + len],
  318. );
  319. return Ok(len);
  320. }
  321. if self.inode_type != KernInodeType::File {
  322. return Err(SystemError::EISDIR);
  323. }
  324. if self.callback.is_none() {
  325. warn!("kernfs: callback is none");
  326. return Err(SystemError::ENOSYS);
  327. }
  328. // release the private data lock before calling the callback
  329. drop(data);
  330. let callback_data =
  331. KernCallbackData::new(self.self_ref.upgrade().unwrap(), self.private_data.lock());
  332. return self
  333. .callback
  334. .as_ref()
  335. .unwrap()
  336. .read(callback_data, &mut buf[..len], offset);
  337. }
  338. fn write_at(
  339. &self,
  340. offset: usize,
  341. len: usize,
  342. buf: &[u8],
  343. data: SpinLockGuard<FilePrivateData>,
  344. ) -> Result<usize, SystemError> {
  345. if self.inode_type != KernInodeType::File {
  346. return Err(SystemError::EISDIR);
  347. }
  348. if self.callback.is_none() {
  349. return Err(SystemError::ENOSYS);
  350. }
  351. // release the private data lock before calling the callback
  352. drop(data);
  353. let callback_data =
  354. KernCallbackData::new(self.self_ref.upgrade().unwrap(), self.private_data.lock());
  355. return self
  356. .callback
  357. .as_ref()
  358. .unwrap()
  359. .write(callback_data, &buf[..len], offset);
  360. }
  361. }
  362. impl KernFSInode {
  363. pub fn new(
  364. parent: Option<Arc<KernFSInode>>,
  365. name: String,
  366. mut metadata: Metadata,
  367. inode_type: KernInodeType,
  368. private_data: Option<KernInodePrivateData>,
  369. callback: Option<&'static dyn KernFSCallback>,
  370. ) -> Arc<KernFSInode> {
  371. metadata.file_type = inode_type.into();
  372. let parent: Weak<KernFSInode> = parent.map(|x| Arc::downgrade(&x)).unwrap_or_default();
  373. let inode = Arc::new(KernFSInode {
  374. name,
  375. inner: RwLock::new(InnerKernFSInode {
  376. parent: parent.clone(),
  377. metadata,
  378. symlink_target: None,
  379. symlink_target_absolute_path: None,
  380. }),
  381. self_ref: Weak::new(),
  382. fs: RwLock::new(Weak::new()),
  383. private_data: SpinLock::new(private_data),
  384. callback,
  385. children: SpinLock::new(HashMap::new()),
  386. inode_type,
  387. lazy_list: SpinLock::new(HashMap::new()),
  388. });
  389. {
  390. let ptr = inode.as_ref() as *const KernFSInode as *mut KernFSInode;
  391. unsafe {
  392. (*ptr).self_ref = Arc::downgrade(&inode);
  393. }
  394. }
  395. if parent.strong_count() > 0 {
  396. let kernfs = parent
  397. .upgrade()
  398. .unwrap()
  399. .fs()
  400. .downcast_arc::<KernFS>()
  401. .expect("KernFSInode::new: parent is not a KernFS instance");
  402. *inode.fs.write() = Arc::downgrade(&kernfs);
  403. }
  404. return inode;
  405. }
  406. /// 在当前inode下增加子目录
  407. ///
  408. /// ## 参数
  409. ///
  410. /// - `name`:子目录名称
  411. /// - `mode`:子目录权限
  412. /// - `private_data`:子目录私有数据
  413. /// - `callback`:子目录回调函数
  414. ///
  415. /// ## 返回值
  416. ///
  417. /// - 成功:子目录inode
  418. /// - 失败:错误码
  419. #[allow(dead_code)]
  420. #[inline]
  421. pub fn add_dir(
  422. &self,
  423. name: String,
  424. mode: ModeType,
  425. private_data: Option<KernInodePrivateData>,
  426. callback: Option<&'static dyn KernFSCallback>,
  427. ) -> Result<Arc<KernFSInode>, SystemError> {
  428. if unlikely(self.inode_type != KernInodeType::Dir) {
  429. return Err(SystemError::ENOTDIR);
  430. }
  431. return self.inner_create(name, KernInodeType::Dir, mode, 0, private_data, callback);
  432. }
  433. /// 在当前inode下增加文件
  434. ///
  435. /// ## 参数
  436. ///
  437. /// - `name`:文件名称
  438. /// - `mode`:文件权限
  439. /// - `size`:文件大小(如果不指定,则默认为4096)
  440. /// - `private_data`:文件私有数据
  441. /// - `callback`:文件回调函数
  442. ///
  443. ///
  444. /// ## 返回值
  445. ///
  446. /// - 成功:文件inode
  447. /// - 失败:错误码
  448. #[allow(dead_code)]
  449. #[inline]
  450. pub fn add_file(
  451. &self,
  452. name: String,
  453. mode: ModeType,
  454. size: Option<usize>,
  455. private_data: Option<KernInodePrivateData>,
  456. callback: Option<&'static dyn KernFSCallback>,
  457. ) -> Result<Arc<KernFSInode>, SystemError> {
  458. if unlikely(self.inode_type != KernInodeType::Dir) {
  459. return Err(SystemError::ENOTDIR);
  460. }
  461. let size = size.unwrap_or(4096);
  462. return self.inner_create(
  463. name,
  464. KernInodeType::File,
  465. mode,
  466. size,
  467. private_data,
  468. callback,
  469. );
  470. }
  471. pub fn add_file_lazy(
  472. &self,
  473. name: String,
  474. provider: fn() -> KernFSInodeArgs,
  475. ) -> Result<(), SystemError> {
  476. if unlikely(self.inode_type != KernInodeType::Dir) {
  477. return Err(SystemError::ENOTDIR);
  478. }
  479. self.lazy_list.lock().insert(name, provider);
  480. Ok(())
  481. }
  482. fn inner_create(
  483. &self,
  484. name: String,
  485. file_type: KernInodeType,
  486. mode: ModeType,
  487. mut size: usize,
  488. private_data: Option<KernInodePrivateData>,
  489. callback: Option<&'static dyn KernFSCallback>,
  490. ) -> Result<Arc<KernFSInode>, SystemError> {
  491. match file_type {
  492. KernInodeType::Dir | KernInodeType::SymLink => {
  493. size = 0;
  494. }
  495. _ => {}
  496. }
  497. let metadata = Metadata {
  498. size: size as i64,
  499. mode,
  500. uid: 0,
  501. gid: 0,
  502. blk_size: 0,
  503. blocks: 0,
  504. atime: PosixTimeSpec::new(0, 0),
  505. mtime: PosixTimeSpec::new(0, 0),
  506. ctime: PosixTimeSpec::new(0, 0),
  507. btime: PosixTimeSpec::new(0, 0),
  508. dev_id: 0,
  509. inode_id: generate_inode_id(),
  510. file_type: file_type.into(),
  511. nlinks: 1,
  512. raw_dev: DeviceNumber::default(),
  513. };
  514. let new_inode: Arc<KernFSInode> = Self::new(
  515. Some(self.self_ref.upgrade().unwrap()),
  516. name.clone(),
  517. metadata,
  518. file_type,
  519. private_data,
  520. callback,
  521. );
  522. self.children.lock().insert(name, new_inode.clone());
  523. return Ok(new_inode);
  524. }
  525. /// 在当前inode下删除子目录或者文件
  526. ///
  527. /// 如果要删除的是子目录,且子目录不为空,则返回ENOTEMPTY
  528. ///
  529. /// ## 参数
  530. ///
  531. /// - `name`:子目录或者文件名称
  532. ///
  533. /// ## 返回值
  534. ///
  535. /// - 成功:()
  536. /// - 失败:错误码
  537. #[allow(dead_code)]
  538. pub fn remove(&self, name: &str) -> Result<(), SystemError> {
  539. if unlikely(self.inode_type != KernInodeType::Dir) {
  540. return Err(SystemError::ENOTDIR);
  541. }
  542. let mut children = self.children.lock();
  543. let inode = children.get(name).ok_or(SystemError::ENOENT)?;
  544. if inode.children.lock().is_empty() {
  545. children.remove(name);
  546. return Ok(());
  547. } else {
  548. return Err(SystemError::ENOTEMPTY);
  549. }
  550. }
  551. /// add_link - create a symlink in kernfs
  552. ///
  553. /// ## 参数
  554. ///
  555. /// - `parent`: directory to create the symlink in
  556. /// - `name`: name of the symlink
  557. /// - `target`: target node for the symlink to point to
  558. ///
  559. /// Returns the created node on success
  560. ///
  561. /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/kernfs/symlink.c#25
  562. pub fn add_link(
  563. &self,
  564. name: String,
  565. target: &Arc<KernFSInode>,
  566. target_absolute_path: String,
  567. ) -> Result<Arc<KernFSInode>, SystemError> {
  568. // debug!("kernfs add link: name:{name}, target path={target_absolute_path}");
  569. let inode = self.inner_create(
  570. name,
  571. KernInodeType::SymLink,
  572. ModeType::S_IFLNK | ModeType::from_bits_truncate(0o777),
  573. 0,
  574. None,
  575. None,
  576. )?;
  577. inode.inner.write().symlink_target = Some(Arc::downgrade(target));
  578. inode.inner.write().symlink_target_absolute_path = Some(target_absolute_path);
  579. return Ok(inode);
  580. }
  581. pub fn name(&self) -> &str {
  582. return &self.name;
  583. }
  584. pub fn parent(&self) -> Option<Arc<KernFSInode>> {
  585. return self.inner.read().parent.upgrade();
  586. }
  587. pub fn private_data_mut(&self) -> SpinLockGuard<Option<KernInodePrivateData>> {
  588. return self.private_data.lock();
  589. }
  590. #[allow(dead_code)]
  591. pub fn symlink_target(&self) -> Option<Arc<KernFSInode>> {
  592. return self.inner.read().symlink_target.as_ref()?.upgrade();
  593. }
  594. /// remove a kernfs_node recursively
  595. pub fn remove_recursive(&self) {
  596. let mut children = self.children.lock().drain().collect::<Vec<_>>();
  597. while let Some((_, child)) = children.pop() {
  598. children.append(&mut child.children.lock().drain().collect::<Vec<_>>());
  599. }
  600. }
  601. /// 删除当前的inode(包括其自身、子目录和子文件)
  602. #[allow(dead_code)]
  603. pub fn remove_inode_include_self(&self) {
  604. let parent = self.parent();
  605. if let Some(parent) = parent {
  606. parent.children.lock().remove(self.name());
  607. }
  608. self.remove_recursive();
  609. }
  610. }
  611. #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  612. pub enum KernInodeType {
  613. Dir,
  614. File,
  615. SymLink,
  616. }
  617. impl From<KernInodeType> for FileType {
  618. fn from(val: KernInodeType) -> Self {
  619. match val {
  620. KernInodeType::Dir => FileType::Dir,
  621. KernInodeType::File => FileType::File,
  622. KernInodeType::SymLink => FileType::SymLink,
  623. }
  624. }
  625. }