Bläddra i källkod

update: use new file read interface

liujingx 11 månader sedan
förälder
incheckning
692b6251a0
5 ändrade filer med 143 tillägg och 55 borttagningar
  1. 2 0
      src/constants.rs
  2. 29 29
      src/ext4/dir.rs
  3. 98 26
      src/ext4/file.rs
  4. 10 0
      src/ext4_defs/inode.rs
  5. 4 0
      src/ext4_defs/super_block.rs

+ 2 - 0
src/constants.rs

@@ -28,6 +28,8 @@ pub const EXT4_INODE_MODE_TYPE_MASK: u16 = 0xF000;
 
 pub const EXT_MAX_BLOCKS: Ext4LogicBlockId = core::u32::MAX;
 
+pub const EXT4_SUPERBLOCK_OS_HURD: u32 = 1;
+
 /// Maximum bytes in a path
 pub const PATH_MAX: usize = 4096;
 

+ 29 - 29
src/ext4/dir.rs

@@ -5,35 +5,6 @@ use crate::ext4_defs::*;
 use crate::prelude::*;
 
 impl Ext4 {
-    pub fn ext4_dir_mk(&self, path: &str) -> Result<usize> {
-        let mut file = Ext4File::new();
-        let flags = "w";
-
-        let filetype = DirEntryType::EXT4_DE_DIR;
-
-        // get mount point
-        let mut ptr = Box::new(self.mount_point.clone());
-        file.mp = Box::as_mut(&mut ptr) as *mut Ext4MountPoint;
-
-        // get open flags
-        let iflags = ext4_parse_flags(flags).unwrap();
-
-        if iflags & O_CREAT != 0 {
-            self.ext4_trans_start();
-        }
-
-        let mut root_inode_ref = self.get_root_inode_ref();
-
-        let r = self.ext4_generic_open(
-            &mut file,
-            path,
-            iflags,
-            filetype.bits(),
-            &mut root_inode_ref,
-        );
-        r
-    }
-
     pub fn ext4_dir_add_entry(
         &self,
         parent: &mut Ext4InodeRef,
@@ -316,4 +287,33 @@ impl Ext4 {
     
         false
     }
+
+    pub fn ext4_dir_mk(&self, path: &str) -> Result<usize> {
+        let mut file = Ext4File::new();
+        let flags = "w";
+
+        let filetype = DirEntryType::EXT4_DE_DIR;
+
+        // get mount point
+        let mut ptr = Box::new(self.mount_point.clone());
+        file.mp = Box::as_mut(&mut ptr) as *mut Ext4MountPoint;
+
+        // get open flags
+        let iflags = ext4_parse_flags(flags).unwrap();
+
+        if iflags & O_CREAT != 0 {
+            self.ext4_trans_start();
+        }
+
+        let mut root_inode_ref = self.get_root_inode_ref();
+
+        let r = self.ext4_generic_open(
+            &mut file,
+            path,
+            iflags,
+            filetype.bits(),
+            &mut root_inode_ref,
+        );
+        r
+    }
 }

+ 98 - 26
src/ext4/file.rs

@@ -118,17 +118,16 @@ impl Ext4 {
         &self,
         file: &mut Ext4File,
         path: &str,
-        // flags: &str,
-        iflags: u32,
+        flags: &str,
         file_expect: bool,
     ) -> Result<usize> {
+        // get open flags
+        let iflags = ext4_parse_flags(flags).unwrap();
+
         // get mount point
         let mut ptr = Box::new(self.mount_point.clone());
         file.mp = Box::as_mut(&mut ptr) as *mut Ext4MountPoint;
 
-        // get open flags
-        // let iflags = self.ext4_parse_flags(flags).unwrap();
-
         // file for dir
         let filetype = if file_expect {
             DirEntryType::EXT4_DE_REG_FILE
@@ -147,35 +146,108 @@ impl Ext4 {
         r
     }
 
-    pub fn ext4_file_read(&self, ext4_file: &mut Ext4File) -> Vec<u8> {
-        // 创建一个空的向量,用于存储文件的内容
-        let mut file_data: Vec<u8> = Vec::new();
+    #[allow(unused)]
+    pub fn ext4_file_read(
+        &self,
+        ext4_file: &mut Ext4File,
+        read_buf: &mut [u8],
+        size: usize,
+        read_cnt: &mut usize,
+    ) -> Result<usize> {
+        if size == 0 {
+            return Ok(EOK);
+        }
+
+        let mut inode_ref = self.get_inode_ref(ext4_file.inode);
+
+        // sync file size
+        ext4_file.fsize = inode_ref.inode.size();
+
+        let is_softlink =
+            inode_ref.inode.inode_type(&self.super_block) == EXT4_INODE_MODE_SOFTLINK as u32;
+
+        if is_softlink {
+            log::debug!("ext4_read unsupported softlink");
+        }
+
+        let block_size = BLOCK_SIZE;
+
+        // 计算读取大小
+        let size_to_read = if size > (ext4_file.fsize as usize - ext4_file.fpos) {
+            ext4_file.fsize as usize - ext4_file.fpos
+        } else {
+            size
+        };
+
+        let mut iblock_idx = (ext4_file.fpos / block_size) as u32;
+        let iblock_last = ((ext4_file.fpos + size_to_read) / block_size) as u32;
+        let mut unalg = (ext4_file.fpos % block_size) as u32;
+
+        let mut offset = 0;
+        let mut total_bytes_read = 0;
 
-        // 创建一个空的向量,用于存储文件的所有extent信息
-        let mut extents: Vec<Ext4Extent> = Vec::new();
+        if unalg > 0 {
+            let first_block_read_len = core::cmp::min(block_size - unalg as usize, size_to_read);
+            let mut fblock = 0;
 
-        let inode_ref = self.get_inode_ref(ext4_file.inode);
+            self.ext4_fs_get_inode_dblk_idx(&mut inode_ref, &mut iblock_idx, &mut fblock, false);
 
-        self.ext4_find_all_extent(&inode_ref, &mut extents);
+            // if r != EOK {
+            //     return Err(Ext4Error::new(r));
+            // }
 
-        // 遍历extents向量,对每个extent,计算它的物理块号,然后调用read_block函数来读取数据块,并将结果追加到file_data向量中
-        for extent in extents {
-            // 获取extent的起始块号、块数和逻辑块号
-            let start_block = extent.start_lo as u64 | ((extent.start_hi as u64) << 32);
-            let block_count = extent.block_count as u64;
-            let logical_block = extent.first_block as u64;
-            // 计算extent的物理块号
-            let physical_block = start_block + logical_block;
-            // 从file中读取extent的所有数据块,并将结果追加到file_data向量中
-            for i in 0..block_count {
-                let block_num = physical_block + i;
+            if fblock != 0 {
+                let block_offset = fblock * block_size as u64 + unalg as u64;
+                let block_data = self.block_device.read_offset(block_offset as usize);
+
+                // Copy data from block to the user buffer
+                read_buf[offset..offset + first_block_read_len]
+                    .copy_from_slice(&block_data[0..first_block_read_len]);
+            } else {
+                // Handle the unwritten block by zeroing out the respective part of the buffer
+                for x in &mut read_buf[offset..offset + first_block_read_len] {
+                    *x = 0;
+                }
+            }
+
+            offset += first_block_read_len;
+            total_bytes_read += first_block_read_len;
+            ext4_file.fpos += first_block_read_len;
+            *read_cnt += first_block_read_len;
+            iblock_idx += 1;
+        }
+
+        // Continue with full block reads
+        while total_bytes_read < size_to_read {
+            let read_length = core::cmp::min(block_size, size_to_read - total_bytes_read);
+            let mut fblock = 0;
+
+            self.ext4_fs_get_inode_dblk_idx(&mut inode_ref, &mut iblock_idx, &mut fblock, false);
+
+            // if r != EOK {
+            //     return Err(Ext4Error::new(r));
+            // }
+
+            if fblock != 0 {
                 let block_data = self
                     .block_device
-                    .read_offset(block_num as usize * BLOCK_SIZE);
-                file_data.extend(block_data);
+                    .read_offset((fblock * block_size as u64) as usize);
+                read_buf[offset..offset + read_length].copy_from_slice(&block_data[0..read_length]);
+            } else {
+                // Handle the unwritten block by zeroing out the respective part of the buffer
+                for x in &mut read_buf[offset..offset + read_length] {
+                    *x = 0;
+                }
             }
+
+            offset += read_length;
+            total_bytes_read += read_length;
+            ext4_file.fpos += read_length;
+            *read_cnt += read_length;
+            iblock_idx += 1;
         }
-        file_data
+
+        return Ok(EOK);
     }
 
     pub fn ext4_file_write(&self, ext4_file: &mut Ext4File, data: &[u8], size: usize) {

+ 10 - 0
src/ext4_defs/inode.rs

@@ -83,6 +83,16 @@ impl Ext4Inode {
         self.mode |= mode;
     }
 
+    pub fn inode_type(&self, super_block: &Ext4Superblock) -> u32{
+        let mut v = self.mode;
+
+        if super_block.creator_os() == EXT4_SUPERBLOCK_OS_HURD{
+            v |= ((self.osd2.l_i_file_acl_high as u32 ) << 16) as u16;
+        }
+
+        (v & EXT4_INODE_MODE_TYPE_MASK) as u32
+    }
+
     pub fn links_cnt(&self) -> u16 {
         self.links_count
     }

+ 4 - 0
src/ext4_defs/super_block.rs

@@ -133,6 +133,10 @@ impl Ext4Superblock {
         self.features_read_only
     }
 
+    pub fn creator_os(&self) -> u32 {
+        self.creator_os
+    }
+
     /// Returns total number of inodes.
     pub fn total_inodes(&self) -> u32 {
         self.inodes_count