Digital Forensics/File System

#1 FAT - File Allocate Table

geunyeong 2022. 1. 20. 23:01

Table of Contents

    Abstract

    FAT는 MS에서 DOS 등 운영체제의 기본 파일 시스템으로 사용하기 위해 개발된 파일 시스템이다. Windows 2000 쯤 부터 NTFS로 기본 파일 시스템이 바뀌었지만 지금도 USB 메모리 등 다양한 곳에서 쓰이고 있다.

    FAT는 오늘날처럼 수십 GB 크기의 스토리지를 고려해 만든 파일 시스템이 아니기 때문에 제법 간단한 구조를 가진다. 본 글에서는 FAT 파일 시스템의 개요와 FAT 파일 시스템으로 포맷된 볼륨의 부트 섹터 구조를 FAT12/16/32 별로 구분해 설명하고 전체 클러스터 사용 내역과 파일 데이터가 저장된 클러스터 체인이 저장되는 파일 할당 테이블(FAT)도 분석하는 내용을 서술했다. 분량 상 디렉토리 엔트리는 다음 글로 미루었다.

    FAT를 다룬 다른 블로그 글들 보다 더 자세한 내용을 담을 수 있도록 노력했다. 본 글이 FAT 입문자는 물론 FAT를 더 깊게 알아보고자 했던 이들에게 도움이 됐으면 좋겠다.

    파일 시스템에 대한 개론은 아래 글을 참고하기 바란다.

    • File System 개론
    https://geun-yeong.tistory.com/74

    FAT

    Overview

    FAT는 Microsoft가 1977년 개발한 파일 시스템으로, 플로피 디스크에서 사용하도록 개발되었다가 하드 디스크같은 다른 저장장치로도 확대됐다. 비교적 간단한 구조와 오랫동안 쓰인 덕인지 개인용 컴퓨터뿐만 아니라 모바일 디바이스, 임베디드 시스템에서도 FAT를 지원하고 서로 다른 시스템(Windows-Linux, Windows-Embedded 등) 간의 데이터 교환을 위해서도 사용된다.[1]

    한 네비게이션의 Map 데이터 업데이트 방법 - USB 메모리의 파일 시스템을 FAT32로 제한하고 있다.

    FAT라는 이름은 FAT 파일 시스템의 구성 요소 중 하나인 File Allocate Table(파일 할당 테이블)에서 따왔다. 본래 8비트 파일 시스템으로 설계됐지만 저장장치 용량이 커지면서 12, 16에 이어 32까지 증가했다. FAT는 보통 FAT12, FAT16, FAT32 같이 숫자와 함께 불리는데, 이 숫자는 클러스터 번호를 나타내기 위해 사용되는 비트의 개수를 의미한다. 달리 말하면 표현 가능한 최대 클러스터 수이기도 하다. 각 FAT# 마다 표현 가능한 클러스터 수는 아래와 같다.

    • FAT12 : 2^12 - 12 = 4,084개
    • FAT16 : 2^16 - 12 = 65,524개
    • FAT32 : 2^28 - 12 = 268,435,444 개

    FAT32의 경우 최상위 4비트를 뺀 28개 비트만을 클러스터 번호를 나타내는 데 사용한다. 4비트는 향후 다른 목적으로 사용하기 위해 예약되었기 때문이다.[3]

    12를 빼는 이유는 12개 값은 이미 다른 목적으로 예약되어 있기 때문이다. 예약된 12개 값과 그에 대한 설명은 아래 표와 같다.[2] 이 외에도 FF0~FF5까지 6개도 용도가 예약되어 있을 수 있으나 비 표준 시스템(non-standard system)에서는 해당 영역에 파일을 할당할 수도 있다. FAT32는 최상위 4비트를 사용하지 않으므로 '?'로 나타냈다. 하지만 보통은 0이다.

    No FAT12 FAT16 FAT32 Desc.
    1 000h 0000h ?000 0000h 사용되고 있지 않은 클러스터(Free Cluster)를 나타낸다. 또는 DOS에서 FAT12/FAT16 볼륨 상의 루트 디렉토리의 서브 디렉토리인 ".." 엔트리의 부모 디렉토리 시작 클러스터를 참조하기 위해 사용된다. 즉 루트 디렉토리의 부모 디렉토리를 나타내는 데 사용된다는 뜻.
    2 001h 0001h ?000 0001h 내부 목적으로 예약된 값이다. MS-DOS/PC DOS는 파일을 할당(클러스터를 할당)할 때 클러스터 체인을 구성하는 동안에 임시적으로 Non-Free Cluster임을 나타내기 위해 이 값을 사용한다.
    3 FF6h FFF6h ?FFF FFF6h 예약된 값이므로 사용해선 안된다. (IBM 호환 머신의 기본 포맷 필터 값인 0xF6에 해당한다.)
    4 FF7h FFF7h ?FFF FFF7h (DOS 2.0부터) 클러스터 내에 배드 섹터가 발생했거나 예약된 클러스터임을 나타내는 값이다. 해당 값이 가리키는 클러스터에 파일을 저장해서는 안되며, 이러한 값을 FAT 엔트리가 가지고 있을 경우 불량 클러스터로 간주해야 한다. FAT32에서 0FFF'FFF7h는 유효한 클러스터일 수 있지만 디스크 유틸리티는 이런 일이 발생할 수 있는 FAT32 볼륨을 만들지 말아야 한다.
    5 FF8h FFF8h ?FFF FFF8h 클러스터 체인(FAT 체인)의 끝을 가리키는 End-of-Chain Marker다.
    86-DOS, MS-DOS, PC DOS, DR-DOS 등 대부분의 시스템은 FFFh, FFFFh, 0FFF'FFFFh를 EoC 마커로 사용하지만 2.5.40 이전의 Linux 시스템은 FF8h, FFF8h, 0FFF'FFF8h를 EoC 마커로 사용한다.
    6 FF9h FFF9h ?FFF FFF9h
    7 FFAh FFFAh ?FFF FFFAh
    8 FFBh FFFBh ?FFF FFFBh
    9 FFCh FFFCh ?FFF FFFCh
    10 FFDh FFFDh ?FFF FFFDh
    11 FFEh FFFEh ?FFF FFFEh
    12 FFFh FFFFh ?FFF FFFFh

    FAT의 클러스터는 2부터 시작한다는 말을 들어봤을 것인데, 위 표에서 볼 수 있듯 0과 1이 다른 목적으로 예약된 값이기 때문에 클러스터 번호로 2부터 할당할 수 있기 때문이다. 실제로 뒤의 FAT 절에서도 설명할 테지만 FAT 엔트리에서 인덱스 0와 인덱스 1에 해당하는 엔트리 값이 FFF?h로 채워지고 인덱스 2에 해당하는 엔트리부터 사용되는 걸 볼 수 있을 것이다.

    [3]에 따르면 MS의 FAT Specification에서 인덱스 0와 인덱스 1의 FAT 엔트리는 아래의 의미를 가진다고 한다. BPB_Media는 볼륨이 생성된 디스크가 고정식 미디어(fixed media)인지 이동식 미디어인지를 나타내는 값이다. 고정식이면 0xF8이 사용되고 이동식이면 0xF0가 설정된다. BPB_Media는 부트 섹터 영역인 BPB에 존재하는 값인데 FAT Specification 상으로 BPB의 BPB_Media 값은 인덱스 0의 FAT 엔트리에도 값이 입력되어 있어야 한다.

    FAT Type Determination

    What are the two reserved clusters at the start of the FAT for? The first reserved cluster, FAT[0], contains the BPB_Media byte value in its low 8 bits, and all other bits are set to 1. For example, if the BPB_Media value is 0xF8, for FAT12 FAT[0] = 0x0FF8, for FAT16 FAT[0] = 0xFFF8, and for FAT32 FAT[0] = 0x0FFFFFF8. The second reserved cluster, FAT[1], is set by FORMAT to the EOC mark. On FAT12 volumes, it is not used and is simply always contains an EOC mark. For FAT16 and FAT32, the file system driver may use the high two bits of the FAT[1] entry for dirty volume flags (all other bits, are always left set to 1). Note that the bit location is different for FAT16 and FAT32, because they are the high 2 bits of the entry.

    첫번째 예약된 클러스터인 FAT[0]는 그것의 하위 8비트에 BPB_Media 바이트 값을 포함한다. 그리고 다른 비트들은 모두 1로 설정된다. 예를 들어 BPB_Media 값이 0xF8이라면 FAT12의 FAT[0] 값은 0x0FF8, FAT16의 FAT[0] 값은 0xFFF8, FAT32의 FAT[0] 값은 0x0FFF'FFF8이다. 두번째 예약 클러스터인 FAT[1]은 EOC 마크 형식으로 설정된다. FAT12 볼륨에서, 그것은 사용되지 않으며 간단하게 언제나 EOC 마크를 포함한다. FAT16과 FAT32에서, 파일 시스템 드라이버는 FAT[1] 엔트리의 상위 2비트를 Dirty Volume 플래그로 사용할 수도 있다(다른 비트들은 모두 1로 설정된다).

    Organization

    FAT는 부트 섹터 영역에 부트 코드와 Bios Parameter Block(BPB), 패딩 영역을 포함한 Reserved 영역과 클러스터 할당 내역을 저장, 관리하는 File Allocate Table(FAT) 영역, 그리고 파일 테이블인 Directory Entry와 실제 파일 데이터가 저장되는 데이터 영역으로 나뉜다. FAT 볼륨의 전체 레이아웃은 아래 그림과 같다.

    Layout of FAT Volume

    Reserved Area

    Non-Partitioned 디바이스(플로피 디스크 등)에서는 전체 디스크에서 가장 첫번째 섹터에 위치하고, 파티션 된 디바이스에서는 MBR, GPT에 의해 나눠진 파티션의 첫번째 섹터에 위치한다. 

    예약 영역의 레이아웃은 아래 그림과 같다.

    Layout of Reserved Area

    Boot Code

    예약 영역 첫 섹터의 첫 3바이트를 포함해 (부팅할 운영체제가 있으면) 운영체제를 부팅하는 코드들이 저장된 영역이다. 첫 3바이트 뒤로는 BPB가 존재하기 때문에 첫 3바이트는 BPB 뒤에 있는 부트 코드로 점프하는 기능을 수행한다. FAT32 기준으로 부트 코드가 90 바이트 오프셋 뒤에 있으므로 88바이트 뒤로 점프하는 OPCode와 NOP을 가진다.

    ; FAT32의 Jump Code
    EB 58 ; jmp 0x58
    90     ; nop

    FAT12의 점프 코드

    BIOS Parameter Block (BPB)

    BPB란 데이터 스토리지 볼륨의 물리적인 레이아웃(배치)를 설명하는 VBR의 데이터 구조다.[4] 쉽게 말하면 볼륨에 대한 메타데이터가 저장되는 구조라는 의미라서 FAT 뿐만 아니라 NTFS에도 존재한다. FAT12/16은 동일한 구조의 BPB를 가지나 FAT32는 FAT12/16의 BPB 구조에서 몇가지 항목이 더 추가됐다.

    아래 표는 FAT12/16의 BPB 항목에 대한 설명이다.

    이름 오프셋(h) 크기 설명
    Jump Code 0 3 부트 코드로 점프하는 OPCode가 담겨있다.
    OEM ID 3 8 OEM 이름이다. 8 바이트 중 남은 공간은 ' '(0x20)으로 패딩된다. OEM 이름을 저장하기 위한 Free 공간이나 일부 옛날 시스템은 이 필드를 확인하기 때문에 쓰레기 값을 넣을 경우 구 시스템에선 인식되지 않을 수 있다.
    오늘날 Windows 시스템에서 FAT 볼륨을 만들면 OEM 이름으로 "MSDOS5.0"이 저장된다.
    여기서부터 DOS 2.0 BPB다. DOS 3.31 BPB는 DOS 2.0 BPB를 포함한다.
    Bytes Per Sector B 2 논리적 섹터의 바이트 크기다. 보통 512(0x200)다.
    Sector Per Cluster D 1 클러스터의 논리적 섹터 크기다. 1, 2, 4, 8, 16, 32, 64, 128 값만 허용한다.
    Reserved Sector Count E 2 Reserved Area의 논리적 섹터 크기다. 달리 말하면 FAT 볼륨의 첫번째 섹터부터 FAT 볼륨의 첫번째 파일 할당 테이블 사이에 존재하는 전체 섹터의 개수이기도 하다. 파일 할당 테이블 위치는 FAT 볼륨의 시작 섹터로부터 이 영의 값 만큼 뒤 섹터에 있다.
    최소 1개 섹터가 예약 영역으로 사용될 수 있으며, FAT32의 경우 32개 섹터를 예약 영역으로 사용한다.
    Num FATs 10 1 파일 할당 테이블(FAT)의 개수다. 대부분은 항상 2다. 첫번째 FAT는 예약 영역 바로 뒤에 나오며, 2번째 FAT는 첫번째 FAT 영역 바로 뒤에 나온다.
    Root Directory Entry 11 2 FAT12/16의 루트 디렉토리 엔트리 번호이다. 루트 디렉토리가 일반 파일처럼 평범하게 데이터 영역 어디든 위치할 수 있는 FAT32에서는 0으로 설정된다.
    Total Sector 16 13 2 FAT12/16 볼륨에 할당된 전체 섹터의 개수다. FAT32는 0으로 설정되고 FAT32 EBPB의 Total Sector 32 항목에 전체 섹터 개수가 저장된다.
    Media 15 1 미디어(스토리지)의 타입을 나타내는 값이다.
    - 0xF8: Fixed Disk (typically a partition on a hdd)
    FAT Size 16 16 2 FAT12/16 볼륨 상의 파일 할당 테이블 하나의 섹터 크기다. FAT32에선 0으로 설정된다.
    여기서부턴 DOS 3.31 BPB다.
    Sector Per Track 18 2 디스크 상의 트랙 당 물리적 섹터의 개수다. 보통 63(0x3F)로 설정된다.
    Num of Heads 1A 2 디스크 상의 헤드 수이다. 보통 255(0xFF)로 설정된다.
    Hidden Sector 1C 4 해당 FAT 볼륨이 포함된 파티션보다 앞에 위치한 섹터들의 개수다. 파티션 되지 않는 미디어에서는 0으로 설정된다. 만약 FAT 볼륨의 시작 섹터가 100이라면 이 값은 100이 저장된다.
    Total Sector 32 20 4 FAT32 볼륨에 할당된 전체 섹터의 개수다.
    만약 Total Sector 16과 이 값이 모두 0이라면 많은 OS들은 MBR이나 GPT를 통해 이 값들을 복원하려 할 것이다.
    여기서부턴 FAT32와 항목이 달라진다.
    Driver Number 24 1 드라이브 번호다. BIOS Interrupt 0x13 호출 시 반환되는 값과 동일하다. 플로피 디스크의 경우 0x00이고, 하드 디스크의 경우 0x80이다.
    - INT 13h: DOS 같은 Real-mode OS에서 INT 13h를 호출하면 CHS 주소 지정 기반의 디스크 읽기/쓰기 작업을 수행하는 Low-level disk service용 ROM-BIOS 코드로 점프한다.[5] 이 때 DL 레지스터에 0x00을 넣으면 첫번째 플로피 디스크(Drive A:)에 대한 서비스라는 의미고, 0x80을 넣으면 첫번재 하드 디스크에 대한 서비스라는 의미다. 즉 INT 13h를 호출할 때 어느 미디어에 대한 인터럽트 서비스인지를 나타내는 값이다.
    Reserved 25 1 -
    Boot Signature 26 1 확장 부팅 시그니처로 0x28 혹은 0x29 값을 가진다. 이는 부팅 섹터에 아래 3개 필드가 있음을 나타내는 시그니처 바이트다. [3]
    Volume ID 27 4 볼륨 시리얼 번호(Volume Serial Number; VSN)다.
    Volume Label 2B 11 볼륨에 대한 레이블 문자열이다. 레이블이 없으면 "NO NAME"으로 설정되며, ' '(0x20)으로 패딩된다
    File System Type 36 8 볼륨에 대한 파일 시스템 타입을 나타내며 "FAT12" 혹은 "FAT16"으로 설정되고 ' '(0x20)으로 패딩된다.
    Boot Code 3E - -

    아래 표는 FAT32의 (가장 일반적인 버전인) DOS 3.31 버전 BPB 항목에 대한 설명이다. 다른 DOS 버전의 BPB는 [2]를 참고하길 바란다.

    이름 오프셋(h) 크기 설명
    이 전까진 FAT12/16과 동일하나
    여기서부턴 FAT32에서 새로 추가된 항목들이다. (FAT32 Extended BPB; EBPB)
    FAT Size 32 24 4 FAT32 볼륨 상의 파일 할당 테이블 하나의 섹터 크기다.
    Mirroring Flags 28 2 미러링 관련 플래그다.
    - 비트 7이 설정됐다면 비트 3-0은 활성 FAT의 0-based 수다.
    - 비트 7이 설정되지 않으면 평소처럼 미러링 한다.
    - 이 외에는 모두 예약되어 있으므로 0으로 설정된다.
    File System Version 2A 2 파일 시스템의 버전이다. Major 버전은 0x2B 오프셋에, Minor 버전은 0x2A 오프셋에 저장되며 보통 둘다 0으로 설정된다.
    Root Directory Cluster 2C 4 FAT32 볼륨의 루트 디렉토리가 위치한 클러스터 번호를 저장한다. 클러스터 2가 배드 섹터를 포함하지 않는다면 보통 2로 설정된다.
    FS Information Sector 30 2 FS 정보가 저장된 섹터의 위치를 나타낸다. 보통 1로 설정된다.
    Backup Boot Sector 32 2 부트 섹터의 복사본이 위치한 섹터 번호를 나타낸다. 보통 6으로 설정된다. (이는 디스크 전체에서 시작 오프셋이 아닌 FAT 볼륨의 시작 섹터로부터의 상대적인 위치다.)
    Reserved 34 12 -
    Drive Number 40 1 <FAT12/16 설명과 상동하다.>
    Reserved 41 1 -
    Boot Signature 42 1 <FAT12/16 설명과 상동하다.>
    Volume ID 43 4 <FAT12/16 설명과 상동하다.>
    Volume Label 47 11 <FAT12/16 설명과 상동하다.>
    File System Type 52 8 <FAT12/16 설명과 상동하다.>
    Boot Code 5A - -

    FS Information (FAT32 only)

    FAT32의 BPB에서 FS Information Sector라는 항목을 봤을 것이다. 보통 이 항목의 값이 1로 설정되어 있기 때문에 BPB와 부트 코드 바로 다음 섹터에 위치하게 되는데, FS Information Sector같은 값이 있다는 의미는 FS Information 구조는 (아마도 예약 영역 내에서) 어디든 있을 수 있다는 걸 의미한다.

    FS Information은 거대한 크기의 볼륨을 가질 수 있는 FAT32를 위해 만들어진 구조다. FS Information 구조는 특정 작업의 시간을 단축시키기 위해 만들어졌는데, 이 특정 작업이란 바로 빈 클러스터를 찾는 작업이다. FAT32는 파일 할당 테이블 영역도 크기 때문에 빈 공간을 찾기 위해 클러스터 2번부터 하나씩 스캔해가면 오래 걸릴 수 밖에 없다. 이를 해소하기 위해 마지막으로 사용한 클러스터 번호를 기억하는 등 FAT32의 성능 향상을 위한 데이터를 저장하는 공간이자 구조다.

    FS Information의 구조는 아래 표와 같다.

    이름 오프셋(h) 크기 설명
    FSI Lead Signature 0 4 FS Information 구조를 나타내는 시그니처다. "RRaA"(0x52526141) 값을 가진다.
    Reserved 4 480 -
    FSI Structure Signature 1E4 4 FS Information 구조를 나타내는 또다른 시그니처다. "rrAa"(0x72724161) 값을 가진다.
    Free Count 1E8 4 볼륨에서 마지막으로 확인된 사용 가능한 클러스터 개수다.
    Next Free 1EC 4 가장 마지막으로 할당한 클러스터의 번호다. FAT32의 파일 할당 테이블이 크다보니 FAT 영역에서 빈 클러스터를 찾는데 시간이 오래 걸릴 수 있다. 때문에 최근에 사용한 클러스터 번호를 기억해 빈 공간을 좀 더 빠르게 찾을 수 있도록 하기 위한 Hint다.
    Reserved 1F0 12 -
    FSI Trail Signature 1FC 4 FS Information 구조의 Trail 시그니처다. 0x000055AA 값을 가진다.

    FAT32의 FS Information 영역

    Boot Strap (FAT32 only)

    FAT 볼륨의 첫 섹터만으로는 부트 코드를 모두 담을 수 없을 때 사용하는 영역이다. 보통은 널 바이트로 채워져있고, 부트 스트랩 섹터의 마지막 2바이트가 부트 레코드 시그니처(0x55AA) 값을 가진다.

    Backup Boot Sector (FAT32 only)

    FAT32의 BPB에 있는 Backup Boot Sector 항목이 가리키는 섹터로 가보면 첫 섹터와 동일한 데이터가 저장된 것을 볼 수 있다. 이는 FAT32의 BPB나 부트 코드가 손상될 경우 복구를 위한 것으로, 첫 섹터 데이터 뿐만 아니라 FS Information, 부트 스트랩 데이터들도 함께 백업되어 있기 때문에 이 영역의 데이터를 FAT32 볼륨의 첫 섹터에 Overwrite하면 볼륨을 복구할 수 있다.

    아래 그림은 섹터 0x20C000(2,146,304)를 FAT 볼륨의 시작 섹터로 사용하는 FAT32 볼륨의 백업 부트 섹터다. 백업 부트 섹터의 위치를 보면 6을 더한 0x20C0006(2,146,310)인 것을 볼 수 있다.

    Backup Boot Sector 영역 데이터

    Remained Reserved Sectors (optional)

    Boot Sector 영역과 FAT 1 사이의 빈 공간을 의미한다. FAT12/16에서는 이 공간이 없을 수 있지만 FAT32에서는 31개 섹터 정도가 존재할 수 있다. 이 영역의 크기는 BPB->RsvdSecCnt에서 1을 뺀 값이다. 이 영역은 모두 널 바이트로 채워진다.

    아래 그림은 FAT12 볼륨의 BPB에서 예약 영역 섹터 크기를 표시한 것이다. 1이 아닌 8로 설정됐기 때문에 부트 섹터 바로 다음이 아닌 7개 섹터 뒤에 파일 할당 테이블이 나타난다.

    FAT12 볼륨의 Reserved Sector Count - 1이 아닌 8이 설정된 걸 볼 수 있다.
    FAT12의 시작 섹터 + 8 위치에 파일 할당 테이블이 위치한 걸 볼 수 있다.

    FAT

    파일 할당 테이블(File Allocate Table; FAT) 데이터 영역의 클러스터 사용 여부를 표시하고 관리하는 배열이다. FAT는 BPB의 NumFATs 항목 값 만큼 생성된다. 보통 2로 설정되기 때문에 FAT는 2개가 만들어진다. FAT 1은 주 FAT, 그 외에는 모두 복구 등에 사용될 복사본이다. FAT 2는 FAT 1 바로 뒤부터 이어진다. FAT #의 위치를 찾는 방법은 아래와 같다.

    • FAT 1의 섹터 위치 = FAT 볼륨 시작 위치 + BPB->ResvSecCnt
    • FAT 2의 섹터 위치 = FAT 1의 섹터 위치 + BPB->FATSz# (FAT12/16이면 FATSz16, FAT32면 FATSz32)
    • FAT n의 섹터 위치 = FAT n-1의 섹터 위치 + BPB->FATSz#

    Structure

    FAT는 특별한 구조를 가지고 있지 않다. Windows에서 테이블이란 용어를 배열과 같은 의미로 쓰기도 한다. FAT32 기준으로 FAT는 4바이트 크기의 요소를 가진 배열이다. FAT16은 2바이트, FAT12는 12비트의 배열이다. 그래서 FAT12는 2개 클러스터를 나타내는데 3 바이트가 필요하다. FAT 배열에 저장되는 값은 EoC 마커이거나 클러스터 체인에서 다음 클러스터 번호를 가리키는 값이다.

    앞서 Overview 절에서 서술했듯, 클러스터 번호 0과 1, FFFF 등은 다른 목적으로 예약되어 있다고 했다. 특히 FAT[0]는 BPB의 Media 값이 들어간다고 했는데, 아래 그림을 보면 실제로 FAT[0]에 Media 값과 동일한 0xF8이 저장된 걸 볼 수 있다. 실제로 클러스터 번호로 할당되는 2부터 보자. 클러스터 n에 대한 정보를 보는 방법은 FAT 배열의 참조 인덱스로 클러스터 번호를 주는 것이다. 즉 클러스터 2에 대한 파일 할당 정보는 FAT[2]에 있다. 아래 그림에서 FAT[2]의 값이 0x0FFF'FFFF인 걸 볼 수 있는데, 이는 클러스터 2 하나만 사용되거나 클러스터 체인의 마지막 클러스터가 클러스터 2라는 걸 알려주는 것이다.

    FAT32 볼륨의 FAT 데이터
    FAT16 볼륨의 FAT 데이터

    FAT Chain (Cluster Chain)

    파일의 크기가 클러스터보다 클 경우 파일 시스템은 2개 이상의 클러스터를 사용해 데이터를 저장한다. 그러므로 나중에 파일 데이터를 다시 가져오기 위해서는 데이터가 어느 클러스터들에 저장됐고, 어느 순서로 참조해야 하는지에 대한 정보가 필요하다. FAT 파일 시스템에서는 이러한 정보를 FAT Chain이라고 한다. 보통은 연속된 클러스터로 파일 데이터를 저장하지만 적당한 빈 공간이 없을 경우 일부 데이터는 연속되지 않은 클러스터에 저장될 수 있다. 파일을 올바르게 복구하기 위해서는 이러한 FAT 체인을 따라가는 방법을 알아야 한다.

    위의 그림에 나온 FAT32 볼륨의 FAT를 보고 FAT 체인을 따라가보자. 우선 image.jpg라는 파일의 데이터가 클러스터 5부터 시작한다고 알아두자. 어느 파일의 데이터가 몇번 클러스터부터 시작하는 지는 뒤의 Directory Entry 절에서 설명할 것이다.

    FAT32 볼륨의 FAT 데이터

    image.jpg 파일 데이터는 클러스터 5부터 시작한다. 클러스터 5에 대한 정보는 FAT[5]에 있으며 FAT[5]의 값은 6임을 알 수 있다. FAT 배열의 값이 예약된 값이 아니면 이는 FAT 체인의 다음 클러스터 값을 의미한다. 즉 image.jpg라는 파일은 2개 이상의 클러스터를 사용해 데이터를 저장하고 있으며 클러스터 5에 파일의 첫 부분이, 클러스터 6에 파일의 두번째 부분이 저장되어 있다는 뜻이 된다.

    EoC(End-of-Chain) 마커 값인 0x?FFF'FFFF가 나올 때 까지 이를 반복해보자.

    // A start number of cluster of image.jpg file is 5.
    /* 1st */ FAT[5] = 6;
    /* 2nd */ FAT[6] = 7;
    /* 3rd */ FAT[7] = 8;
    /* 4th */ FAT[8] = 9;
    //
    // ...
    //
    /* 25th */ FAT[29] = 30; // 0x1E
    /* 26th */ FAT[30] = 31; // 0x1F
    /* 27th */ FAT[31] = 32; // 0x20
    /* 28th */ FAT[32] = 0x0FFF'FFFF; // EoC

    image.jpg는 클러스터 5부터 클러스터 32까지 총 28개 클러스터에 걸쳐 파일 데이터가 저장되어 있다. FAT 체인대로라면 클러스터 5에는 JPEG 헤더가, 클러스터 32에는 JPEG 트레일러가 존재할 것이다. 한번 확인해보자. 클러스터 n의 위치를 찾는 방법은 아래와 같다.

    • FAT 1의 위치 = FAT 볼륨 시작 위치 + BPB->ResvSecCnt
    • 클러스터 2의 위치 = FAT 1의 위치 + (BPB->NumFATs * BPB->FATSz#)
    • 클러스터 n의 위치 = 클러스터 2의 위치 + ((n - 2) * BPB->SecPerClus)

    위 FAT32 볼륨에서 주요 BPB 값은 아래와 같다.

    • FAT 볼륨 시작 위치: 2,146,304 (0x20C000)
    • BPB->ResvSecCnt: 2,114 0x842
    • BPB->NumFATs: 2
    • BPB->FATSz32: 3,039 (0xBDF)
    • BPB->SecPerClus: 8

    이를 토대로 클러스터 5와 32의 섹터 위치를 계산해보면 아래와 같다.

    • FAT 1의 위치 = 2,148,418 + 2,114 = 2,148,418 (0x20C842)
    • 클러스터 2의 위치 = 2,148,418 + (2 * 3,039) = 2,154,496
    • 클러스터 5의 위치 = 2,154,496 + ((5-2) * 8) = 2,154,520
    • 클러스터 32의 위치 = 2,154,496 + ((32-2) * 8) = 2,154,736

    클러스터 5에는 JPEG 헤더 시그니처가, 클러스터 32에는 JPEG 트레일러 시그니처가 있는 걸 볼 수 있다.

    클러스터 5에 위치한 JPEG 헤더 시그니처
    클러스터 32에 위치한 JPEG 트레일러 시그니처

    Directory Entry

    디렉토리 엔트리까지 하기엔 글이 너무 길어지니 다음 글에서 이어 설명하겠다.

    • #2 FAT - Directory Entry
    https://geun-yeong.tistory.com/76

    Close

    이상으로 FAT에 대한 개요와 FAT BPB, 클러스터 할당 테이블인 FAT와 FAT 체인을 따라가는 법을 알아봤다. 점점 사용 빈도가 줄어들고 있지만 임베디드를 포함해 복잡한 구조를 필요로 하지 않는 분야에서는 아직까지도 사용되고 있다. 그나마 가장 간단하고 쉬운 구조를 가진 파일 시스템이 FAT이니 한번 익혀두면 다른 파일 시스템을 공부할 때도 큰 도움이 될 것이다.

    Refs.