file.rs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. use super::utils::*;
  2. use super::Ext4;
  3. use crate::constants::*;
  4. use crate::ext4_defs::*;
  5. use crate::prelude::*;
  6. use crate::return_errno_with_message;
  7. impl Ext4 {
  8. pub fn ext4_generic_open(
  9. &self,
  10. file: &mut Ext4File,
  11. path: &str,
  12. iflags: u32,
  13. ftype: u8,
  14. parent_inode: &mut Ext4InodeRef,
  15. ) -> Result<usize> {
  16. let mut is_goal = false;
  17. let mut data: Vec<u8> = Vec::with_capacity(BLOCK_SIZE);
  18. let ext4_blk = Ext4Block {
  19. logical_block_id: 0,
  20. disk_block_id: 0,
  21. block_data: &mut data,
  22. dirty: true,
  23. };
  24. let de = Ext4DirEntry::default();
  25. let mut dir_search_result = Ext4DirSearchResult::new(ext4_blk, de);
  26. file.flags = iflags;
  27. // load root inode
  28. let root_inode_ref = self.get_root_inode_ref();
  29. // if !parent_inode.is_none() {
  30. // parent_inode.unwrap().inode_num = root_inode_ref.inode_num;
  31. // }
  32. // search dir
  33. let mut search_parent = root_inode_ref;
  34. let mut search_path = ext4_path_skip(&path, ".");
  35. let mut len;
  36. loop {
  37. search_path = ext4_path_skip(search_path, "/");
  38. len = ext4_path_check(search_path, &mut is_goal);
  39. let r = self.ext4_dir_find_entry(
  40. &mut search_parent,
  41. &search_path[..len as usize],
  42. len as u32,
  43. &mut dir_search_result,
  44. );
  45. // log::info!("dir_search_result.dentry {:?} r {:?}", dir_search_result.dentry, r);
  46. if r != EOK {
  47. // ext4_dir_destroy_result(&mut root_inode_ref, &mut dir_search_result);
  48. if r != ENOENT {
  49. // dir search failed with error other than ENOENT
  50. return_errno_with_message!(Errnum::ENOTSUP, "dir search failed");
  51. }
  52. if !((iflags & O_CREAT) != 0) {
  53. return_errno_with_message!(Errnum::ENOENT, "file not found");
  54. }
  55. let mut child_inode_ref = Ext4InodeRef::default();
  56. let r = if is_goal {
  57. self.ext4_fs_alloc_inode(&mut child_inode_ref, ftype)
  58. } else {
  59. self.ext4_fs_alloc_inode(&mut child_inode_ref, DirEntryType::EXT4_DE_DIR.bits())
  60. };
  61. if r != EOK {
  62. return_errno_with_message!(Errnum::EALLOCFIAL, "alloc inode fail");
  63. // break;
  64. }
  65. Self::ext4_fs_inode_blocks_init(&mut child_inode_ref);
  66. let r = self.ext4_link(
  67. &mut search_parent,
  68. &mut child_inode_ref,
  69. &search_path[..len as usize],
  70. len as u32,
  71. );
  72. if r != EOK {
  73. /*Fail. Free new inode.*/
  74. return_errno_with_message!(Errnum::ELINKFIAL, "link fail");
  75. }
  76. self.write_back_inode(&mut search_parent);
  77. self.write_back_inode(&mut child_inode_ref);
  78. self.write_back_inode(parent_inode);
  79. continue;
  80. }
  81. let _name = get_name(
  82. dir_search_result.dentry.name,
  83. dir_search_result.dentry.name_len as usize,
  84. )
  85. .unwrap();
  86. // log::info!("find de name{:?} de inode {:x?}", name, dir_search_result.dentry.inode);
  87. if is_goal {
  88. file.inode = dir_search_result.dentry.inode;
  89. return Ok(EOK);
  90. } else {
  91. search_parent = self.get_inode_ref(dir_search_result.dentry.inode);
  92. search_path = &search_path[len..];
  93. }
  94. }
  95. }
  96. pub fn ext4_open(
  97. &self,
  98. file: &mut Ext4File,
  99. path: &str,
  100. // flags: &str,
  101. iflags: u32,
  102. file_expect: bool,
  103. ) -> Result<usize> {
  104. // get mount point
  105. let mut ptr = Box::new(self.mount_point.clone());
  106. file.mp = Box::as_mut(&mut ptr) as *mut Ext4MountPoint;
  107. // get open flags
  108. // let iflags = self.ext4_parse_flags(flags).unwrap();
  109. // file for dir
  110. let filetype = if file_expect {
  111. DirEntryType::EXT4_DE_REG_FILE
  112. } else {
  113. DirEntryType::EXT4_DE_DIR
  114. };
  115. if iflags & O_CREAT != 0 {
  116. self.ext4_trans_start();
  117. }
  118. let mut root_inode_ref = self.get_root_inode_ref();
  119. let r = self.ext4_generic_open(file, path, iflags, filetype.bits(), &mut root_inode_ref);
  120. r
  121. }
  122. pub fn ext4_file_read(&self, ext4_file: &mut Ext4File) -> Vec<u8> {
  123. // 创建一个空的向量,用于存储文件的内容
  124. let mut file_data: Vec<u8> = Vec::new();
  125. // 创建一个空的向量,用于存储文件的所有extent信息
  126. let mut extents: Vec<Ext4Extent> = Vec::new();
  127. let inode_ref = self.get_inode_ref(ext4_file.inode);
  128. self.ext4_find_all_extent(&inode_ref, &mut extents);
  129. // 遍历extents向量,对每个extent,计算它的物理块号,然后调用read_block函数来读取数据块,并将结果追加到file_data向量中
  130. for extent in extents {
  131. // 获取extent的起始块号、块数和逻辑块号
  132. let start_block = extent.start_lo as u64 | ((extent.start_hi as u64) << 32);
  133. let block_count = extent.block_count as u64;
  134. let logical_block = extent.first_block as u64;
  135. // 计算extent的物理块号
  136. let physical_block = start_block + logical_block;
  137. // 从file中读取extent的所有数据块,并将结果追加到file_data向量中
  138. for i in 0..block_count {
  139. let block_num = physical_block + i;
  140. let block_data = self
  141. .block_device
  142. .read_offset(block_num as usize * BLOCK_SIZE);
  143. file_data.extend(block_data);
  144. }
  145. }
  146. file_data
  147. }
  148. pub fn ext4_file_write(&self, ext4_file: &mut Ext4File, data: &[u8], size: usize) {
  149. let super_block_data = self.block_device.read_offset(BASE_OFFSET);
  150. let super_block = Ext4Superblock::try_from(super_block_data).unwrap();
  151. let mut inode_ref = self.get_inode_ref(ext4_file.inode);
  152. let block_size = super_block.block_size() as usize;
  153. let iblock_last = ext4_file.fpos as usize + size / block_size;
  154. let mut iblk_idx = ext4_file.fpos as usize / block_size;
  155. let ifile_blocks = ext4_file.fsize as usize + block_size - 1 / block_size;
  156. let mut fblk = 0;
  157. let mut fblock_start = 0;
  158. let mut fblock_count = 0;
  159. let mut size = size;
  160. while size >= block_size {
  161. while iblk_idx < iblock_last {
  162. if iblk_idx < ifile_blocks {
  163. self.ext4_fs_append_inode_dblk(
  164. &mut inode_ref,
  165. &mut (iblk_idx as u32),
  166. &mut fblk,
  167. );
  168. }
  169. iblk_idx += 1;
  170. if fblock_start == 0 {
  171. fblock_start = fblk;
  172. }
  173. fblock_count += 1;
  174. }
  175. size -= block_size;
  176. }
  177. for i in 0..fblock_count {
  178. let idx = i * BLOCK_SIZE as usize;
  179. let offset = (fblock_start as usize + i as usize) * BLOCK_SIZE;
  180. self.block_device
  181. .write_offset(offset, &data[idx..(idx + BLOCK_SIZE as usize)]);
  182. }
  183. // inode_ref.inner.inode.size = fblock_count as u32 * BLOCK_SIZE as u32;
  184. self.write_back_inode(&mut inode_ref);
  185. // let mut inode_ref = Ext4InodeRef::get_inode_ref(self.self_ref.clone(), ext4_file.inode);
  186. let mut root_inode_ref = self.get_root_inode_ref();
  187. self.write_back_inode(&mut root_inode_ref);
  188. }
  189. pub fn ext4_file_remove(&self, _path: &str) -> Result<usize> {
  190. return_errno_with_message!(Errnum::ENOTSUP, "not support");
  191. }
  192. }