Skip to content

FAT32 分析 1

FAT

File Allocation Table


  • FAT12
  • FAT16
  • FAT32

Read

Allocation Table

位于保留区域之后, 在数据区之前, 一般有两个 FAT , FAT1 是主分配表, FAT2 是备份使用的, 我们只驱动 FAT1

FAT1 的每一项占用 4B, 开头的 8 个字节是文件系统保留项, 其中 第0项 为介质类型,第1项 为文件系统错误标志,用户的数据从第2项开始.

Indexing...

目录项的读取的话, 假设我们有一个簇号, 那么 簇号就可以当作 FAT1 的索引, FAT1[簇号] 会告诉你当前簇的下一个部分在哪个簇. 当 "簇号" 是 0x0FFFFFFF 时, 说明已经没有下一个簇了.

伪代码如下:

# first_data_sect
# fat_sect_idx -> the sector index of current part of FAT1
# sect_size -> is defaltly 512 (Byte)

while true:
    cluster = read_cluster(current)
    if entry_exist(cluster, name):
        return entry_get(cluster, name)
    else:
        if not (align_down(current, nr_aloc) <= fat_read[current] < align_down(current, nr_aloc) + nr_aloc):
            fat_read = read_sector(div_round_down(fat_base + fat_read[current] * 4, sect_size))
        current = fat_read[current % nr_aloc]
        if current is 0x0FFFFFFF:
            return none

# whatever it goes
return none

Specification

Long file name programming

A long file name for a target file or sub-directory is stored in a set (one or more) of additional directory entries associated with the short name directory entry describing the target file or subdirectory. This set of additional directory entries (also known as the long name directory entries) must immediately precede the corresponding short name directory entry and is, therefore, physically contiguous with the short name directory entry.

  • precede v. 先于

NOTE: The sequence of long name directory entries is stored in reverse order (last entry in the set is stored first, followed by entry n-1, followed by entry n-2, and so on, until entry 1).

That's:

1
2
3
4
5
6
7
addr
|       | n     | -> Last long entry
|       | n - 1 |
|       | n - 2 |
|       |  ...  |
|       | short | -> Short entry
v

关于 Order:

The order of this entry in the sequence of long name directory entries (each containing components of the long file name) associated with the corresponding short name directory entry. The contents of this field must be masked with 0x40 (LAST_LONG_ENTRY) for the last long directory name entry in the set. Therefore, each sequence of long name directory entries begins with the contents of this field masked with LAST_LONG_ENTRY.

也就是说, Order 标记了它在这个由许多长项构成的序列中是第几个. 最后一个长项, 也就是存储在最前面的一项, Order & 0x40 != 0


关于 Attr:

ATTR_LONG_NAME = (ATTR_READ_ONLY | 
                  ATTR_HIDDEN | 
                  ATTR_SYSTEM | 
                  ATTR_VOLUME_ID)

ATTR_LONG_NAME_MASK = (ATTR_READ_ONLY | 
                       ATTR_HIDDEN | 
                       ATTR_SYSTEM | 
                       ATTR_VOLUME_ID |
                       ATTR_DIRECTORY |
                       ATTR_ARCHIVE) 

命名规则:

  1. The first member of a set has an LDIR_Ord value of 1.
  2. The LDIR_Ord value for each subsequent entry must contain a monotonically increasing value.
  3. The N-th (last) member of the set must contain a value of (N | LAST_LONG_ENTRY)

关于 校验和 ?


关于 "zero" ?

  • Type
  • Cluster

Note

Linux:

1
2
3
4
> │00170800│ 41 74 00 65 00 73 00 74 ┊ 00 2e 00 0f 00 8f 74 00 │At⋄e⋄s⋄t┊⋄.⋄•⋄×t⋄│
> │00170810│ 78 00 74 00 00 00 ff ff ┊ ff ff 00 00 ff ff ff ff │x⋄t⋄⋄⋄××┊××⋄⋄××××│
> │00170820│ 54 45 53 54 20 20 20 20 ┊ 54 58 54 20 00 8d e1 4c │TEST    ┊TXT ⋄××L│
> │00170830│ a1 58 a1 58 00 00 e1 4c ┊ a1 58 00 00 00 00 00 00 │×X×X⋄⋄×L┊×X⋄⋄⋄⋄⋄⋄│

TextOS:

1
2
3
4
< │00170840│ 41 74 00 65 00 73 00 74 ┊ 00 2e 00 0f 00 8f 74 00 │At⋄e⋄s⋄t┊⋄.⋄•⋄×t⋄│
< │00170850│ 78 00 74 00 00 00 ff ff ┊ ff ff 00 00 ff ff ff ff │x⋄t⋄⋄⋄××┊××⋄⋄××××│
< │00170860│ 54 45 53 54 20 20 20 20 ┊ 54 58 54 20 00 00 00 00 │TEST    ┊TXT ⋄⋄⋄⋄│
< │00170870│ c0 00 00 00 00 00 00 00 ┊ 00 00 8b 03 b8 02 00 00 │×⋄⋄⋄⋄⋄⋄⋄┊⋄⋄וו⋄⋄│