zanesterling / fatr

A FAT12 parsing and manipulation tool
MIT License
1 stars 0 forks source link

Implement FAT12/FAT16/FAT32 support #6

Open kallisti5 opened 7 years ago

kallisti5 commented 7 years ago

Once we have dynamic sector sizes and counts from be BPB, Implementing FAT12/FAT16/FAT32 support is a breeze. :-)

kallisti5@nyx fatr :( $ file ~/fat12.img 
/home/kallisti5/fat12.img: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID "mkfs.fat", sectors/cluster 4, root entries 512, sectors 8192 (volumes <=32 MB) , Media descriptor 0xf8, sectors/FAT 6, sectors/track 32, heads 64, serial number 0xd6deda69, label: "HAIKU      ", FAT (12 bit)
kallisti5@nyx fatr :) $ file ~/fat16.img 
/home/kallisti5/fat16.img: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID "mkfs.fat", sectors/cluster 4, reserved sectors 4, root entries 512, Media descriptor 0xf8, sectors/FAT 64, sectors/track 32, heads 64, sectors 65536 (volumes > 32 MB) , serial number 0x7994b8ff, unlabeled, FAT (16 bit)
kallisti5@nyx fatr :) $ file ~/fat32.img 
/home/kallisti5/fat32.img: DOS/MBR boot sector, code offset 0x58+2, OEM-ID "mkfs.fat", Media descriptor 0xf8, sectors/track 32, heads 64, sectors 524288 (volumes > 32 MB) , FAT (32 bit), sectors/FAT 4033, serial number 0x2122bd13, unlabeled
kallisti5@nyx fatr :) $ ./target/debug/fatr ls ~/fat12.img
HAIKU   .    0
Atest.. 4294967295
TEST    .TXT 7

kallisti5@nyx fatr :) $ ./target/debug/fatr ls ~/fat16.img
Atest.. 4294967295
TEST    .TXT 22

kallisti5@nyx fatr :) $ ./target/debug/fatr ls ~/fat32.img
Atest.. 4294967295
TEST    .TXT 22
kallisti5 commented 7 years ago

While reading FAT12,FAT16,FAT32 images works...

$ ./target/debug/fatr ls ~/fat16.img 
 Volume TESTVOLUME 
 Volume has 512 bytes per sector

19229   41550   1448277     HARVEY.PNG
19229   41553   1448277     TIM.PNG
    2 File(s)       2896554 bytes
$ ./target/debug/fatr detail ~/fat16.img HARVEY.PNG
RootEntry {
    filename: "HARVEY.PNG",
    attrs: 32,
    creation_time: 41550,
    creation_date: 19229,
    last_access_date: 19229,
    last_write_time: 41550,
    last_write_date: 19229,
    first_logical_cluster: 3,
    file_size: "0x161955"
}
0x3 
0x0

writing to them seems to be broken still...

$ RUST_BACKTRACE=1 ./target/debug/fatr add ~/bug.txt ~/fat16.img 
thread 'main' panicked at 'destination and source slices have different lengths', /checkout/src/libcore/slice/mod.rs:654:8
stack backtrace:
   0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
             at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::_print
             at /checkout/src/libstd/sys_common/backtrace.rs:71
   2: std::panicking::default_hook::{{closure}}
             at /checkout/src/libstd/sys_common/backtrace.rs:60
             at /checkout/src/libstd/panicking.rs:380
   3: std::panicking::default_hook
             at /checkout/src/libstd/panicking.rs:396
   4: std::panicking::rust_panic_with_hook
             at /checkout/src/libstd/panicking.rs:611
   5: std::panicking::begin_panic_new
             at /checkout/src/libstd/panicking.rs:553
   6: std::panicking::begin_panic_fmt
             at /checkout/src/libstd/panicking.rs:521
   7: rust_begin_unwind
             at /checkout/src/libstd/panicking.rs:497
   8: core::panicking::panic_fmt
             at /checkout/src/libcore/panicking.rs:92
   9: core::panicking::panic
             at /checkout/src/libcore/panicking.rs:51
  10: <[T] as core::slice::SliceExt>::clone_from_slice
             at /checkout/src/libcore/macros.rs:32
  11: alloc::slice::<impl [T]>::clone_from_slice
             at /checkout/src/liballoc/slice.rs:1432
  12: fatr::fat::root_entry::RootEntry::set_filename
             at src/fat/root_entry.rs:63
  13: fatr::fat::image::Image::create_file_entry
             at src/fat/image.rs:199
  14: fatr::commands::add::add_file
             at src/commands/add.rs:33
  15: fatr::main
             at src/main.rs:32
  16: __rust_maybe_catch_panic
             at /checkout/src/libpanic_unwind/lib.rs:98
  17: std::rt::lang_start
             at /checkout/src/libstd/panicking.rs:458
             at /checkout/src/libstd/panic.rs:361
             at /checkout/src/libstd/rt.rs:59
  18: main
  19: __libc_start_main
  20: _start

I encountered the same error back when fatr was FAT12 only, so it appears to not be a regression. Maybe something hard-coded somewhere still?

kallisti5 commented 7 years ago

I've solved the panics in one of my branches, but it seems get_free_fat_entry is always returning the same sector (4, the first one).

I don't see where we assign the fat entry when writing chunks of data.

kallisti5 commented 7 years ago

getting closer...

kallisti5@eris fatr :) $ mkfs.fat -F32 ~/fat32.img 
mkfs.fat 4.1 (2017-01-24)

kallisti5@eris fatr :) $ cargo build
   Compiling fatr v0.2.0 (file:///home/kallisti5/Code/fatr)
    Finished dev [unoptimized + debuginfo] target(s) in 2.16 secs

kallisti5@eris fatr :) $ ls -la README.md 
-rw-rw-r-- 1 kallisti5 kallisti5 120 Oct  9 16:22 README.md

kallisti5@eris fatr :) $ ./target/debug/fatr add README.md ~/fat32.img

kallisti5@eris fatr :) $ sudo mount ~/fat32.img /tmp/test

kallisti5@eris fatr :) $ ls -la /tmp/test/
total 1
drwxr-xr-x  2 root root 512 Dec 31  1969 .
drwxrwxrwt 27 root root 820 Oct 10 09:14 ..
-rwxr-xr-x  1 root root 120 Dec 31  1979 README.MD

kallisti5@eris fatr :) $ cat /tmp/test/README.MD 
kallisti5@eris fatr :) $ 

The file is empty however... definitely an issue with the file allocation tables. Also, writing to FAT12 or FAT16 causes a bunch of corrupt directory entries...

kallisti5@eris fatr :) $ mkfs.fat -F12 ~/fat12.img 
mkfs.fat 4.1 (2017-01-24)

kallisti5@eris fatr :( $ ./target/debug/fatr add README.md ~/fat12.img

kallisti5@eris fatr :) $ sudo mount ~/fat12.img /tmp/test

kallisti5@eris fatr :) $ ls -la /tmp/test/
total 1661496
drwxr-xr-x  2 root root      16384 Dec 31  1969  .
drwxrwxrwt 27 root root        820 Oct 10 09:17  ..
-rwxr-xr-x  1 root root 1701344096 Jan  9  1985  nipulati.ng
-rwxr-xr-x  1 root root        120 Dec 31  1979  README.MD
-r-xr-xr-x  1 root root          0 Dec 31  1979 'To run:'$'\n''.$ c'
kallisti5 commented 6 years ago

Currently, adding files is broken. I think the failure to write file data is due to the following:

kallisti5 commented 6 years ago

There definitely is something going on with the chains getting written in the data_area.


kallisti5@nyx fatr :( $ ./target/debug/fatr detail ~/fat12-ok.img TEST.TXT
RootEntry {
    filename: "TEST.TXT",
    attrs: 32,
    creation_time: 29966,
    creation_date: 19564,
    last_access_date: 19564,
    hi_first_lcluster: 0,
    last_write_time: 29966,
    last_write_date: 19564,
    lo_first_lcluster: 3,
    file_size: "0x74"
}
0x3 
0xfff

kallisti5@nyx fatr :) $ ./target/debug/fatr detail ~/fat12-fatr.img TEST.TXT
RootEntry {
    filename: "TEST.TXT",
    attrs: 0,
    creation_time: 0,
    creation_date: 0,
    last_access_date: 0,
    hi_first_lcluster: 0,
    last_write_time: 0,
    last_write_date: 0,
    lo_first_lcluster: 0,
    file_size: "0x74"
}
0x0 
0xff8

The fatr one has a starting cluster of 0 instead of 3, and doesn't seem to have an end of chain defined per fsck:

kallisti5@nyx fatr :) $ fsck ~/fat12-fatr.img
fsck from util-linux 2.30.2
fsck.fat 4.1 (2017-01-24)
/TEST.TXT
  File size is 116 bytes, cluster chain length is 0 bytes.
  Truncating file to 0 bytes.
/1 ABCDEF.GHI
  Start cluster beyond limit (23129 > 2037). Truncating file.
/1 ABCDEF.GHI
  File size is 1092629002 bytes, cluster chain length is 0 bytes.
  Truncating file to 0 bytes.
/BCDEFGHI.JKL
  Start cluster beyond limit (8243 > 2037). Truncating file.
/BCDEFGHI.JKL
  File size is 1145258561 bytes, cluster chain length is 0 bytes.
  Truncating file to 0 bytes.
/EFGHIJKL.MNO
  Directory has non-zero size. Fixing it.
/EFGHIJKL.MNO
  Start cluster beyond limit (17218 > 2037). Truncating file.
/HIJKLMNO.PQR
 Start does point to root directory. Deleting dir. 
Perform changes ? (y/n) 
kallisti5 commented 6 years ago

More testing. Writing a small test text file to each image, then parsing the image with the native linux tools. Looks as though the data chunks are being seen as root entries.

$ ./run_test 
TEST FILE 8<   8<     8<
THIS IS A TEST
TEST FILE 8<   8<     8<

======== fat12.img ===========
16+0 records in
16+0 records out
16777216 bytes (17 MB, 16 MiB) copied, 0.00726132 s, 2.3 GB/s
mkfs.fat 4.1 (2017-01-24)
new root entry RootEntry { filename: "TEST.TXT", attrs: 0, creation_time: 0, creation_date: 0, last_access_date: 0, hi_first_lcluster: 0, last_write_time: 0, last_write_date: 0, lo_first_lcluster: 0, file_size: "0xf" }
write chunk to entry_index 5
 Volume has no label
 Volume has 512 bytes per sector

0   0   15      TEST.TXT
    1 File(s)       15 bytes
 OS Mount + ls =========
total 24
drwxr-xr-x  2 root root 16384 Dec 31  1969  .
drwxrwxrwt 22 root root   800 Apr 26 09:05  ..
-rwxr-xr-x  1 root root    15 Dec 31  1979  TEST.TXT
-r-xr-xr-x  1 root root     0 Dec 31  1979 'THIS IS.a t'
FILE 8<   8<     8<
FILE 8<   8<     8<

======== fat16.img ===========
100+0 records in
100+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 0.0423376 s, 2.5 GB/s
mkfs.fat 4.1 (2017-01-24)
new root entry RootEntry { filename: "TEST.TXT", attrs: 0, creation_time: 0, creation_date: 0, last_access_date: 0, hi_first_lcluster: 0, last_write_time: 0, last_write_date: 0, lo_first_lcluster: 0, file_size: "0xf" }
write chunk to entry_index 6
 Volume has no label
 Volume has 512 bytes per sector

0   0   15      TEST.TXT
    1 File(s)       15 bytes
 OS Mount + ls =========
total 18
drwxr-xr-x  2 root root 16384 Dec 31  1969  .
drwxrwxrwt 22 root root   800 Apr 26 09:05  ..
-rwxr-xr-x  1 root root    15 Dec 31  1979  TEST.TXT
-r-xr-xr-x  1 root root     0 Dec 31  1979 'THIS IS.a t'
FILE 8<   8<     8<
FILE 8<   8<     8<