* 들어가기에 앞서 본 스터디에 사용 된 OS 종류 및 VMware 종류에 대해 기술하고 시작하고자 한다. 다른 버전이어도 상관은 없으나, 사용 상 불편한 부분까지 본 블로그에서 일일히 다루어 주지는 않는다. 물론, 질문을 남겨줄 경우, 따로 확인해서 답변을 드리긴 하겠다.
- 필자 E-Mail : wotmd9408@naver.com
- 가상머신 : VMWare WorkStation 12
- OS : Window7 Enterprise K 64bit
- RAM : 1GB
- 나머지 사항은 기본적인 세팅으로 설정하였다.
- 추가 필요 Tool : Hxd(https://mh-nexus.de/en/downloads.php?product=HxD)
이제 FAT32 파일시스템도 어느정도 마무리 단계에 접어 들었다. 물론 이번 포스팅이 끝이 아니고 몇가지가 더 남아있긴 하지만(간단하게 풀어볼 수 있는 문제도 제작 해 보려고 하고있다.) 그래도 칠부능선을 넘은건 사실이다. 이론만 따지면 두번이나 세번 정도의 포스팅이면 간략하게나마 마무리 될 것으로 보인다.
지난 포스팅을 통해 Root Directory Entry의 구조와 각각의 디렉터리 엔트리가 어떤식으로 구성되어있는지 세부적인 내용들을 알아보았다. 그러나 해당 포스팅에서 다루지 않은 내용이 남아있다. 그것이 이번 포스팅에서 다룰 Short File Name과 Long File Names 이다.
파일 및 디렉터리는 생성할 때 각각의 고유한 이름을 가진다. 물론 이 고유한 이름이 절대적으로 Unique 하지는 않다. 동일한 확장자에 대해서만 고유한 이름을 갖고 있으니 오해 없기를 바란다. 그리고 각각의 파일명은 몇가지 규칙을 가지고 있으며, 해당 규칙을 위반할 경우 파일이 정상적으로 생성되지 않는다. 이 규칙은 SFN(Short FIle Name) 과 LFN(Long File Name)이 조금씩 다른 부분이 있기 때문에 따로 나누어 설명 하도록 하겠다.
먼저 알아볼 내용은 SFN(Short File Name)이다. 의미 그대로 짧은 파일명을 의미하고, FAT32기준에서는 8Byte (영문 8자, 한글 4자)이하, 3Byte이하의 확장자 파일 혹은 디렉터리일 경우 Short File Name으로 표기된다. 그림을 통해 예시를 들어보도록 하자.
[그림 1. Short File Name의 예시]
[그림 1]은 지난번 Root Directory Entry에서도 봤던 코알라 사진이다. 위에서 말한 Short File Name의 조건과 일치하는지 한번 확인해 보도록 하자. 먼저 파일명이 8Byte인지 확인하면 K,O,A,L,A로 총 5개의 알파벳으로 파일명이 구성되어 5Byte 값을 가진다. 그리고 확장자 역시 JPG로 3Byte 값만 가지기 때문에 Short File Name의 조건이 된다고 볼 수 있다.
그러면 Short File Name에 만족한다는 가정하에 어떤 규칙을 지켜야 파일이 생성되는지 확인해 보도록 하자.
- 영어 대문자 A ~ Z (소문자는 대문자로 바꾸어 저장)
- 해당 운영체제가 지원하는 언어의 문자( ex : 한글 MS-DOS라면 한글 파일명 가능)
- 아라비아 숫자 0 ~ 9
- 특수문자 중 $, %, ', -. _, @, ~, !, (), {}, ^, #,&
위에서 가장 첫번째 조건의 경우, 실제 파일을 만들때는 소문자로 만들어도 문제가 없지만, Root Directory Entry에 저장될 때는 대문자로 저장하기에 저렇게 기입하였다. 또한 따로 적혀있지 않지만, Short File Name 작성 규칙에서 파일 명 사이에 스페이스(0x20)을 입력하는 것은 가능하다. ( ex : MY NAME.HWP) 그러나 일부 프로그램의 경우 파일명 중간에 Space가 포함될 경우 파일을 제대로 인식 못할 수 있기 때문에 Under Bar( _ )를 지향하는 것이 좋다. 또한 영어가 아닌 외래어의 경우 한 글자당 2Byte로 인식하기 때문에 그 또한 알아두면 좋다. 그리고 마지막으로, 전 포스팅에서 이야기 했듯이 파일명 가장 앞에 스페이스(0x20)이 들어갈 수 없다.
SFN(Short File Name)은 이정도로만 설명해 두도록 하자. 이후 추가적으로 필요한 부분이 있으면 필자가 더 채워 두도록 하겠다. 이제부터는 이 포스팅에서 본격적으로 다뤄 볼 LFNs(Long File Names)에 대해 알아보도록 한다.
Window 95가 나오기 이전, 그러니까 MS-DOS와 Window 3.x버전이 PC의 기본 OS였던 시절에는 FAT 파일시스템이 나올 때부터 쓰이던 8.3 Naming, 즉 우리가 위에서 SFN(Short File Name)으로 알고있는 방식만이 사용되었다. 그러한 이유로 많은 유저들은 매킨토시(MAC OS)나 Unix, Linux 계열처럼 긴 파일명을 사용 할 수 있기를 원했다. 그래서 나온 기능이 Window 95와 함께 나온 LFNs(Long File Names)이다.
LFNs의 자세한 구조를 알기전에, LFNs의 특징들에 대해 먼저 짚고 넘어가도록 하자.
- 유니코드(UTF-16)방식으로 인코딩되어 있기 때문에 다국어 지원이 가능
- 최대 255자까지 저장 가능
- 3자리 이상의 확장자도 저장 가능
- 기존의 SFN(Short File Name)과 호환 됨
- SFN보다 사용할 수 있는 특수문자 폭이 넓어짐
MircroSoft는 LFNs를 설계하면서 하위 호환의 개념을 버리지 않으려고 노력했다. 앞으로 우리가 보게 될 Long File Name Entry는 전 포스팅에서 보았던 Directory Entry를 변형해서 구성하여 하위 호환성을 유지했다. 물론, 억지로 비틀어(?)만든 방식이니 만큼 구조가 어색하고 상당히 불편하다.
LFNs의 가장 큰 특징중 하나는 바로 유니코드를 지원한다는 점이다. 이는 Microsoft의 큰 밑그림(빅픽처??)으로 인해 지원하는 부분인데 Windows가 여러 나라에 사용될 것을 대비해 추가 된 기능이다. 물론 이 기능으로 인해 저장 공간이 2배이상 늘어나 버린 단점은 분명히 존재하지만, 현재의 상황으로 따지고 보면 미래를 정확히 내다 본 좋은 선택이었음에는 틀림없다.
[그림 2. Long File Names 표기의 예시]
[그림 2]는 필자가 예시로 만든 Forensics라는 디렉터리를 Root Directory Entry에서 확인한 것이다. [Forensics] 이라는 단어는 총 9자로 Short File Name 방식인 8/3(8자리 파일명, 3자리 확장자명)법칙으로는 만들어 낼 수 없다. 따라서 [그림 2]처럼 LFNs(Long File Names)로 표기된다. [그림 2]를 보면 동일한 Forensics가 2가지 방식으로 표현된 것을 볼 수 있는데, 붉은색 네모칸과 초록색 네모칸이 바로 그것이다. LFNs의 특징 중 하나는 표기 할 수 있는 부분까지 표기해준 뒤 모자란 부분에 대해서 ~1로 표현하여 LFNs로 표현됐음을 알려주는 것이다. 앞으로 여러분이 보게 될 디렉터리 엔트리 중 ~1이 있으면 LFNs로 표기되었다고 보아도 좋다.
위 그림에 대해 자세히 알아보도록 하자. 먼저 초록색 네모를 보면 SFN(Short File Name)처럼 기록되어있다. 최대 6자까지 파일명을 표기하고 남은 부분을 ~1로 표기하여 LFNs(Long File Names)로 표현되었음을 지칭한 뒤. 파일의 나머지 정보(생성시간, 파일 용량 등)을 표기한다. 여기까지는 [그림 1]에서 본 SFN(Short File Name)과 비슷하다. 그런데 LFNs(Long FIle Names)는 어찌됐든 File명을 전체를 표시해 줘야 하기 때문에, 해당 디렉터리 엔트리 상단 32Byte를 추가로 할당하여 파일명을 마저 표기한다. 이 부분이 붉은색 네모에 해당하는 부분이며 Short Directory Entry와 구분되게 Long Directory Entry라 지칭한다.
아래 정리를 통해 [그림 2] 중 붉은색 영역(Long Directory Entry)에 해당하는 부분에 대하여 자세히 알아보도록 하자.
이름 | Order |
offset | 0 | Size | 1 Byte | Value | 가변적 |
설명 | Long File Name Entry가 정렬 된 순번을 기록하는 항목으로 만약 이 항목의 6번째 비트(0x40)가 1이라면 해당 파일명을 구성하는 마지막 Entry를 의미 |
이름 | Name1 |
offset | 1~10 | Size | 10 Byte | Value | 가변적 |
설명 | 해당 엔트리에 저장할 문자열 중 1~5번째 문자열을 여기에 저장 |
이름 | Attribute |
offset | 11 | Size | 1 Byte | Value | 0x0F |
설명 | 이 항목은 언제나 ATTR_LONG_FILE_NAME을 뜻하는 '0x0F'가 들어가야 한다. 그렇지 않으면 MS-DOS와 같이 LFN Entry를 인식하지 못하는 기존 운영체제에서 문제를 일으키게 된다. |
이름 | Type |
offset | 12 | Size | 1 Byte | Value | 일반적으로 0 |
설명 | 이 항목의 값이 0이라면 일반적으로 LFNs의 항목 중 하나라는 의미이다. 다른 값들은 미래를 위해 예약되어 있다. |
이름 | Check Sum |
offset | 13 | Size | 1 Byte | Value | 가변적 |
설명 | 이 항목은 Short Directory Entry 항목에 들어가는 11자의 문자열에 대한 Check Sum을 저장한다. |
이름 | Name2 |
offset | 14~25 | Size | 12 Byte | Value | 가변적 |
설명 | 해당 Entry에 저장할 문자열 중 6~11번째 문자열을 이곳에 저장한다. |
이름 | First Cluster Low |
offset | 26~27 | Size | 2 Byte | Value | 반드시 0 |
설명 | Long Directory Entry는 파일명을 저장하는 기능밖에 없기 때문에 이 부분은 의미 없는 값이기는 하나, 기존의 FAT 코드와의 호환성을 위해 반드시 0으로 기입한다. |
이름 | Name3 |
offset | 28~31 | Size | 4 Byte | Value | 가변적임 |
설명 | 해당 Entry에 저장할 문자열 중 12~13번째 문자열을 이곳에 저장한다. |
위 표들을 자세히 살펴보면 한가지 특이한 점을 알 수 있다. Long File Name Entry 하나 당 13개의 문자열을 저장할 수 있으며, 문자열을 저장할 때 2Byte 당 1개의 문자열을 저장한다는 점이다. 이는 LFNs가 문자열 지정 방식을 유니코드(UTF-16)으로 하고 있기 때문인데, 이 부분에 대해서는 차후에 기회가 되면 따로 정리해보도록 하겠다.
여기서 의문점 하나. 만약 파일명, 혹은 디렉터리 명이 13자를 넘어갈 경우에는 어떻게 되겠는가? 간단하다. 필요한 숫자만큼 Long Directory Entry를 생성하게 되며 최대 255자 까지 생성이 가능하기 때문에 255/13을 해보면 최대 20개의 Long Directory Entry가 생성되게 된다.
그러면 Short Directory Entry 와 Long Directory Entry가 저장되는 형태에는 어떠한 규칙이 존재하는지 아래표를 통해 알아보자.
Directory Entry 순서 |
Order 항목 값 |
N번째 Long File Name Entry(마지막 Entry) |
LAST_LONG_ENTRY(0x40) | N |
|
두 번째 Long File Name Entry |
0x02 |
첫 번째 Long File Name Entry |
0x01 |
위와 대응하는 Short Directory Entry |
(해당 없음) |
위 표대로 Short Directory Entry가 가장 하단에 위치하고 그 위로 Long Directory Entry가 순서대로 시작되어서 맨 위쪽에 마지막 문자열의 Long File Name Entry가 위치한다. 마지막 Long File Name Entry에는 해당 Entry가 마지막임을 알려주기 위해 Order 항목에 마지막 Entry 번호와 0x40번 비트를 OR시키게 된다. 만약 7번째가 Long File Name Entry라면 Order 값은 0x47이 되는 것이다. 아래 예시를 통해 Short Directory Entry 및 Long Directory Entry를 정리 해 보도록 하자.
[그림 3. Short/Long Directory Entry 예시]
실습을 위해 제목이 긴 파일 하나를 만들었다(필자가 매우 좋아하는 영국 드라마 "Doctor Who"에서 주인공이 타고다니는 우주선 이름이다). [그림 3]을 통해 하나하나 확인 하도록 하자. 먼저 가장 하단의 Short Directory Entry부터 확인해 보도록 하겠다. 기준은 전 포스팅에서 설명했던 디렉터리 엔트리 설명과 이번 포스팅에서 설명한 Long File Name Entry 설명을 기준으로 작성하도록 하겠다.
- Name : TIMEAN~1
-> 해당 파일명으로만 봤을 때는 TIMEAN~1로 보일 수 있으나 위의 내용들을 함께 봤을 때 이 파일은 LFNs로 표현되어 있음을 알 수 있다.
- Extender : TXT
- Attribute : 0x20
-> 0x10은 디렉터리, 0x20은 파일을 의미한다. 따라서 이 디렉터리 엔트리는 파일임을 알 수 있다.
- Create Time : 0xB61A => 1011 0110 0001 1010
5/6/5로 변환하면 10110 110000 11010 가 되는데 이를 다시 10진수로 변환하면 22시 48분 26초가 되는데 마지막 Seconds 부분은 최대 31까지밖에 표기하지 못하므로 2를 곱해야 해서 22시 48분 52초가 된다.
[그림 4. Create Time 확인]
- Create Date : 0x4B47 => 0100 1011 0100 0111
7/4/5로 변환하면 0100101 1010 00111 가 되는데 이를 다시 10진수로 변환하면 37년 10월 7일이 된다. 전 포스팅에서 연도를 계산할 때는 기본 1980에 앞에서 구한값을 더하라고 했으므로 최종 값은 2017년 10월 7일이 된다. [그림 4]를 통해 맞는 결과인지 확인하도록 하자.
- Last Access Date : 0x4B47 => 마지막 접속 날짜는 날짜 변경 이후에 따로 접속한 이력이 없기 때문에 생성 날짜와 동일한 값을 가진다.
- First Cluster High : 0x00
- Write Time : 0xB623 => 1011 0110 0010 0011
5/6/5로 변환하면 10110 110001 00011 이 되는데 이를 다시 10진수로 변환하면 22시 49분 3초가 된다. 위의 Create Time과 마찬가지로 마지막 seconds 값은 2를 곱해줘야 하므로 최종 결과는 22시 49분 6초가 된다. [그림 4]에서 수정한 날짜의 시간을 확인해 보도록 하자.
- Write Date : 0x4B47 => Create Date와 같은 값이 표기되어 있다.
- First Cluster Low : 0x00C4 => 다음 포스팅에서 실제로 사용 할 수 있을 것이다.
- File Size : 0x00000E => 10진수로 변환하면 14Byte가 나온다. [그림 4]에서 크기를 확인해 보도록 하자.
위에서는 Short Directory Entry에 대해서 알아보았다. 전 포스팅의 복습이 되었길 바라며 이제 이번 포스팅에서 다루었던 Long Directory Entry 내용을 확인 해 보도록 하자.
먼저 32Byte 씩 잘라서 총 몇개의 Long File Name Entry가 있는지 확인해보자.
[그림 5. 예제 파일의 Long File Name Entry 종류]
조금 그림자체가 복잡하게 되어있지만 [그림 5]는 에제 파일의 Long Directory Entry 내에 Long File Name Entry를 하나하나 나눈 것이다. Long File Name Entry의 수를 세는것은 생각보다 간단하다. Short Directory Entry에서 LFNs 타입을 확인 한 후 해당 디렉터리 엔트리 위로 32Byte씩 잘라가면서 가장 앞 바이트 값을 확인하면 된다.(마지막 엔트리가 0x01, 0x02 등이 아닌 0x41~ 0x60 사이의 값이 오면 마지막 엔트리가 된다.)
앞서 위의 표에서 봤던 내용을 토대로 Long File Name Entry 값을 확인해 보도록 하자.(내용이 길어지는 관계로 본 포스팅에서는 1번 Long Directory Entry만 함께하도록 하겠다. 이후 내용은 스스로 실습 해 보도록 하자)
- Order : 0x01 => 첫번째 Long Directory Entry
- Name1 : T.i.m.e. . => Time 과 스페이스(0x20)이 해당 Name1에 포함된 이름 값으로 되어있다.
- Attribute : 0x0F => 이 값은 반드시 고정되어야 한다.
- Type : 0x00 => LFNs의 항목중 하나
- Check Sum : 0xA3 => 계산법은 추후에 따로 설명하도록 한다.
- Name2 : A.n.d. .R.e. => And와 스페이스(0x20), 그리고 Re가 Name2에 포함되어 있다.
- First Cluster Low : 0x00
- Name3 : l.a. => la가 name3에 포함되어 있다.
위 내용으로 봤을 때 첫번째 Long Directory Entry에 포함된 파일의 이름은 Time And Rela가 된다. 이후 나머지 Long Directory Entry값은 독자분들이 실습을 통해 확인해 보기 바란다. 파일명은 [그림 4]에 나와있으니 최종 결과는 그곳에서 확인하면 되겠다.
생각보다 짧게 끝날것으로 예상했던 포스트였는데 실습이 포함되면서 생각보다 길어진 감이 있다. 이해가 잘 안될수도 있고, 이론만으로 진행하다보니 학습에 지루함이 있을 수 있다. 실제 업무에 들어가서는 이렇게 Hex Editor를 사용하는 일보다는 Encase나 FTK Editor를 이용하는 일이 더 많을 것이다.(필자로 실제로 실무를 하지 않아서 확신할 수는 없지만..) 그러나 이렇게 이론을 알아가는 것이 실제 업무를 하는데 상당한 도움이 될 것이니 소홀히 하지 말기 바란다.
다음 포스팅에서는 FAT32 의 마지막 단계인 Data Area에 대해 기술하도록 하겠다.
* 참고 : 임베디드 개발자를 위한 파일시스템의 원리와 실습(정준석, 정용원 공저), 한빛미디어