Ver Fonte

fix: file read and write

liujingx há 11 meses atrás
pai
commit
bc44f44a57
6 ficheiros alterados com 36 adições e 18 exclusões
  1. 12 1
      ext4_test/src/main.rs
  2. 1 0
      src/ext4/dir.rs
  3. 1 0
      src/ext4/extent.rs
  4. 5 7
      src/ext4/file.rs
  5. 3 3
      src/ext4_defs/extent.rs
  6. 14 7
      src/ext4_defs/inode.rs

+ 12 - 1
ext4_test/src/main.rs

@@ -1,5 +1,4 @@
 use ext4_rs::{BlockDevice, Ext4, BLOCK_SIZE};
-use log::info;
 use simple_logger::SimpleLogger;
 use std::fs::{File, OpenOptions};
 use std::io::{Read, Seek, SeekFrom, Write};
@@ -79,6 +78,16 @@ fn open_test(ext4: &mut Ext4) {
     ext4.ext4_open("2/4", "w+", true).expect("open failed");
 }
 
+fn read_write_test(ext4: &mut Ext4) {
+    let buffer = "hello world".as_bytes();
+    let mut wfile = ext4.ext4_open("1/2/3/4/5", "w+", true).expect("open failed");
+    ext4.ext4_file_write(&mut wfile, buffer).expect("write failed");
+    let mut rfile = ext4.ext4_open("1/2/3/4/5", "r", true).expect("open failed");
+    let mut buffer2 = vec![0u8; buffer.len()];
+    ext4.ext4_file_read(&mut rfile, &mut buffer2, buffer.len()).expect("read failed");
+    assert_eq!(buffer, buffer2);
+}
+
 fn main() {
     logger_init();
     make_ext4();
@@ -89,4 +98,6 @@ fn main() {
     println!("mkdir test done");
     open_test(&mut ext4);
     println!("open test done");
+    read_write_test(&mut ext4);
+    println!("read write test done");
 }

+ 1 - 0
src/ext4/dir.rs

@@ -13,6 +13,7 @@ impl Ext4 {
 
         while iblock < total_blocks {
             // Get the fs block id
+            debug!("Parent {:?}", parent.inode);
             let fblock = self.extent_get_pblock(parent, iblock)?;
             // Load block from disk
             let block_data = self.block_device.read_offset(fblock as usize * BLOCK_SIZE);

+ 1 - 0
src/ext4/extent.rs

@@ -9,6 +9,7 @@ impl Ext4 {
     fn find_extent(&self, inode_ref: &Ext4InodeRef, iblock: LBlockId) -> Vec<ExtentSearchPath> {
         let mut path: Vec<ExtentSearchPath> = Vec::new();
         let mut ex_node = inode_ref.inode.extent();
+        ex_node.print();
         let mut pblock = 0;
         let mut block_data: Vec<u8>;
 

+ 5 - 7
src/ext4/file.rs

@@ -173,13 +173,11 @@ impl Ext4 {
         let mut iblock = start_iblock;
         while cursor < size {
             let write_len = min(BLOCK_SIZE, size - cursor);
-            let fblock = self.extent_get_pblock(&mut inode_ref, iblock)?;
-            if fblock != 0 {
-                self.block_device
-                    .write_offset(cursor, &data[cursor..cursor + write_len]);
-            } else {
-                panic!("Write to unallocated block");
-            }
+            let fblock = self.extent_get_pblock(&mut inode_ref, iblock)? as usize;
+            self.block_device.write_offset(
+                fblock * BLOCK_SIZE + file.fpos % BLOCK_SIZE,
+                &data[cursor..cursor + write_len],
+            );
             cursor += write_len;
             file.fpos += write_len;
             iblock += 1;

+ 3 - 3
src/ext4_defs/extent.rs

@@ -231,7 +231,7 @@ impl Ext4Extent {
 /// Interpret an immutable byte slice as an extent node. Provide methods to
 /// access the extent header and the following extents or extent indices.
 ///
-/// The underlying `raw_data` could be of `[u8;15]` (root node) or a
+/// The underlying `raw_data` could be of `[u32;15]` (root node) or a
 /// data block `[u8;BLOCK_SIZE]` (other node).
 pub struct ExtentNode<'a> {
     raw_data: &'a [u8],
@@ -305,7 +305,7 @@ impl<'a> ExtentNode<'a> {
     }
 
     pub fn print(&self) {
-        debug!("Extent header count {}", self.header().entries_count());
+        debug!("Extent header {:?}", self.header());
         let mut i = 0;
         while i < self.header().entries_count() as usize {
             let ext = self.extent_at(i);
@@ -378,7 +378,7 @@ impl<'a> ExtentNodeMut<'a> {
     }
 
     pub fn print(&self) {
-        debug!("Extent header count {}", self.header().entries_count());
+        debug!("Extent header {:?}", self.header());
         let mut i = 0;
         while i < self.header().entries_count() as usize {
             let ext = self.extent_at(i);

+ 14 - 7
src/ext4_defs/inode.rs

@@ -28,7 +28,7 @@ pub struct Linux2 {
 }
 
 #[repr(C)]
-#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 pub struct Ext4Inode {
     pub mode: u16,
     pub uid: u16,
@@ -42,7 +42,7 @@ pub struct Ext4Inode {
     pub blocks: u32,
     pub flags: u32,
     pub osd1: u32,
-    pub block: [u32; 15], // Block bitmap or extent tree
+    pub block: [u8; 60], // Block bitmap or extent tree
     pub generation: u32,
     pub file_acl: u32,
     pub size_hi: u32,
@@ -59,6 +59,13 @@ pub struct Ext4Inode {
     pub i_version_hi: u32,   // 64位版本的高32位
 }
 
+/// Because `[u8; 60]` cannot derive `Default`, we implement it manually.
+impl Default for Ext4Inode {
+    fn default() -> Self {
+        unsafe { mem::zeroed() }
+    }
+}
+
 impl Ext4Inode {
     pub fn from_bytes(bytes: &[u8]) -> Self {
         unsafe { *(bytes.as_ptr() as *const Ext4Inode) }
@@ -241,16 +248,16 @@ impl Ext4Inode {
     pub fn extent_init(&mut self) {
         self.set_flags(EXT4_INODE_FLAG_EXTENTS);
         let header = Ext4ExtentHeader::new(0, 4, 0, 0);
-        let header_ptr = &header as *const Ext4ExtentHeader as *const u32;
-        let array_ptr = &mut self.block as *mut [u32; 15] as *mut u32;
+        let header_ptr = &header as *const Ext4ExtentHeader as *const u8;
+        let array_ptr = &mut self.block as *mut u8;
         unsafe {
-            core::ptr::copy_nonoverlapping(header_ptr, array_ptr, 3);
+            core::ptr::copy_nonoverlapping(header_ptr, array_ptr, size_of::<Ext4ExtentHeader>());
         }
     }
 }
 
 /// A combination of an `Ext4Inode` and its id
-#[derive(Default, Clone)]
+#[derive(Clone)]
 pub struct Ext4InodeRef {
     pub inode_id: InodeId,
     pub inode: Ext4Inode,
@@ -307,7 +314,7 @@ impl Ext4InodeRef {
     ) -> Result<()> {
         let disk_pos = Self::inode_disk_pos(super_block, block_device.clone(), self.inode_id);
         let data = unsafe {
-            core::slice::from_raw_parts(self as *const _ as *const u8, size_of::<Ext4Inode>())
+            core::slice::from_raw_parts(&self.inode as *const _ as *const u8, size_of::<Ext4Inode>())
         };
         block_device.write_offset(disk_pos, data);
         Ok(())