TAR 파일 – 3.헤더 구조

TAR 아카이브 포맷

TAR 아카이브의 포맷을 보면 이전의 유닉스 호환 포맷(UNIX-compatible formats)과 POSIX (IEEE P1003.1) 기준으로 새로이 정의된 USTAR 포맷(USTAR format)이 있습니다. 새로이 정의된 USTAR 포맷은 유닉스 호환 포맷보다 더 많은 정보를 저장할 수 있으며 더 긴 파일 패스명을 지원합니다. 그러나 어느 포맷이 되었든지 헤더는 512바이트 크기의 1블록으로 구성되어 있습니다.

우선 이전의 유닉스 호환 포맷에 의한 헤더 구조를 보면 아래와 같습니다.

< 유닉스 호환 포맷에 의한 헤더 구조 >
FIELD NAME OFFSET SIZE MEANING
name 0 100 name of file
mode 100 8 file mode
uid 108 8 owner user ID
gid 116 8 owner group ID
size 124 12 length of file in bytes
mtime 136 12 modify time of file
chksum 148 8 checksum for header
link 156 1 indicator for links
linkname 157 100 name of linked file

link 필드에는 링크 파일(linked file)이면 1, 심볼릭 링크(symbolic link) 이면 2, 기타일 때는 0이 기록됩니다. 디렉토리의 경우에는 링크명에 슬래시(/)가 붙게되지요.

새로운 USTAR 포맷에 의한 헤더 구조는 아래와 같습니다. magic 필드에는 null 문자로 종료되는 문자열 “ustra”이 기록되며 magic 필드 이전의 모든 필드는 typeflag 필드를 제외하고는 모두 이전의 유닉스 호환 포맷과 동일합니다. 유닉스 호환 포맷에서의 link 필드가 USTAR 포맷에서는 typeflag 필드로 변경되었습니다.

< USTAR 포맷에 의한 헤더 구조 >
FIELD NAME OFFSET SIZE MEANING
name 0 100 name of file
mode 100 8 file mode
uid 108 8 owner user ID
gid 116 8 owner group ID
size 124 12 length of file in bytes
mtime 136 12 modify time of file
chksum 148 8 checksum for header
typeflag 156 1 type of file
linkname 157 100 name of linked file
magic 257 6 USTAR indicator
varsion 263 2 USTAR version
uname 265 32 owner user name
gname 297 32 owner group name
devmajor 329 8 device major number
devminor 337 8 device minor number
prefix 345 155 prefix for file name

이와 같이 어느 포맷이 되었든지 파일명, 파일크기 등 파일 정보에 관한 내용이 저장되는 헤더는 1블록(512바이트)로 구성되어 있습니다.

TAR 아카이브를 다룰 때 name 필드부터 typeflag 필드까지만 정확히 다루게 된다면 윈도우를 포함한 어느 시스템에서나 정상적으로 동작하는 것 같습니다. 즉 여러분이 PHP를 이용하여 작성된 TAR 아카이브를 가지고 유닉스 또는 리눅스의 tar 유틸리티를 이용하여 풀 수 있으며, 또한 윈도우에서 알집이나 window commander에서 풀 수도 있습니다.

테이블에 나타난 바와 같이 각 필드마다 그 위치와 크기가 고정되어 있습니다.

magic, uname, gname 필드는 마지막 코드는 반드시 null(아스키문자 0)이 나타나는 null 종료 문자열(null-terminated character strings)입니다. name, linkname, prefix 필드는 마지막 코드가 반드시 null일 필요는 없으나 정해진 필드크기가 다 채워지지 않았다면 채워지지 않은 빈 공간을 반드시 null로 채워야 합니다. name 필드의 예를 들어보면 만약 파일명이 “s1.txt”라면 name 필드에 기록될 때는 “s1.txt” . str_repeat(chr(0), 100 – strlen(“s1.txt”))에서 얻은 값으로 기록됩니다.

USTAR 포맷에서 uname, gname 필드는 각각 로그인 사용자명과 그룹 사용자명을 기록합니다.

mode, uid, gid, chksum, devmajor, devminor 필드의 마지막 코드는 반드시 null이 기록되어야 하나 size, mtime, version 필드는 반드시 null로 종료할 필요는 없으나 일반적으로 null이 기록되는 것 같습니다. 따라서 숫자를 나타내는 이들 필드는 모두 null로 종료한다고 생각하시면 될 것입니다. 이와 같이 숫자를 나타내는 필드들은 모두 null로 종료되므로 실제로 숫자가 기록되는 장소의 크기는 테이블에 정하여진 SIZE-1이 됩니다. 예를 들어 uid의 경우를 보면 필드 크기는 8바이트이지만 실제로 OFFSET 108부터 114까지의 7바이트에만 기록되며 마지막 OFFSET 115에는 null이 기록됩니다. 숫자 필드에서 한가지 주의할 것은 기록되는 숫자는 10진수가 아니라 8진수로 기록된다는 것이지요. 그리고 기록되는 숫자의 자리수가 필드 크기보다 작을 때는 앞쪽으로 남는 자리수만큼 “0”으로 채워지게 됩니다. 만약 uid 값이 8이라면 uid 필드에는 “0000010”이 기록됩니다.

어떤 필드가 되었든지 헤더에서 사용되지 않는 공간은 모두 null로 채우도록 되어있습니다. 이제는 각 필드별로 다른 특징을 살펴보지요.

“name” 필드는 파일명 또는 디렉토리명이 기록되는 곳으로 총 100자까지 기록될 수 있습니다. 파일명이 100자가 되지 않아 비워있는 곳은 모두 null 값으로 채워집니다. 여기에 기록되는 파일명에는 패스명이 포함됩니다.

USTAR 포맷의 경우를 보면 prefix 필드의 값이 null이 아니라면 100자가 넘는 파일명이 가능하도록 name 필드 앞에 붙게 됩니다. 그러나 이전의 유닉스 호환 포맷이나 윈도우 시스템에서 TAR 아카이브를 만들 수 있는 윈도우커맨더 등과의 호환성을 생각한다면 prefix 필드를 null로 남겨두는 것이 좋을 듯하며 100자가 넘는 파일명인 경우 뒷쪽을 짤라내어 100자까지만 name 필드에 저장하는 것이 좋을 듯합니다.

USTAR 포맷에서만 사용하고 있는 typeflag 필드는 이전의 유닉스 호환 포맷의 link 필드와 호환성을 유지한 채 확장시킨 것입니다. 아래는 typeflag 필드에 기록될 수 있는 값들이며 이 중에 0, 1, 2까지는 이전의 유닉스 호환 포맷과 호환성을 유지합니다.

< typeflag 필드의 값 >
TYPE FLAG FILE TYPE
0 or null Regular file
1 Link to another file already archived
2 Symbolic link
3 Character special device
4 Block special device
5 Directory
6 FIFO special file
7 Reserved
A-Z Available for custom usage

“typeflag”는 파일 형식을 나타내는 필드로 디렉토리일 때는 “5”가 기록되며 파일일 경우에는 “0”이 기록됩니다.

“mode” 필드는 파일 모드가 기록되는 곳으로 8진수로 기록됩니다. 예를 들면 0755, 0644와 같지요. “mode” 필드에서 사용할 수 있는 크기는 총 7자입니다. 이 경우 보통 “0000755”와 같이 남는 공간은 앞쪽에 “0”으로 채우게 됩니다. 그러나 이러한 기록 방법은 프로그램에 따라 약간씩 차이가 나기도 하네요. 윈도우 유틸리티인 windows commander에서 TAR 아카이브를 만들게 되면 “000755 ” 또는 “000644 “와 같이 6자만 8진수로 만들어 주고 7번째 자리에는 ” “로 채우게 됩니다. 윈도우에서야 원래 파일 모드라는 개념이 없으니까 관계가 없다고 생각할지 모르겠으나 윈도우에서 압축한 TAR 아카이브를 리눅스에서 풀 때는 생각한다면 이를 적절히 처리하는 것이 좋을 것 같습니다.

“uid”와 “gid”도 “mode”와 같이 8진수로 기록되며 총 7자리를 만들 게 됩니다. 빈 공간은 앞쪽에 “0”을 채우게 되지요.

“size”는 바이트 단위의 파일 크기를 나타내며 8진수로 기록됩니다.

“mtime”는 파일을 수정한 시간을 나타내며 이에 해당하는 php 함수는 filemtime()입니다.

“magic” 필드는 압축 알고리즘의 이름을 나타내며 보통 “ustar” 또는 “GNUtar” 등이 기록됩니다. 6자가 안되는 부분은 ” “로 뒤쪽에 채워지게 됩니다.

“linkname”, “uname”, “gname”, “devmajor”, “devminor”, “prefix”, “noname” 필드는 모두 chr(0)으로 채워넣습니다.

위와 같이 “chksum” 필드를 제외한 필드를 모두 기록한 후에 마지막으로 “chksum” 필드를 기록합니다. “chksum” 필드는 묶여진 파일이 정상적인가를 확인하는데 이용하는 체크섬 필드입니다. 8진수로 기록되며 채워지지 않는 부분은 앞쪽으로 “0”으로 채우게 됩니다. 체크섬 값은 아래와 같은 방법으로 구하게 됩니다. 이 때 변수 $HEADER에는 “chksum” 필드를 제외한 필드가 위에서 기술한 방법대로 먼저 기록되어 있다고 가정합니다.

만약 기록하고자 하는 것이 파일이 아니라 디렉토리라면 파일과 같은 내용이 없기 때문에 512바이트의 헤더만 존재합니다. 한번 디렉토리 정보가 기록되면 그 뒤의 파일들은 앞에서 나타난 디렉토리에 속하게 됩니다. 따라서 디렉토리가 변경되는 부분에서만 단 한번 디렉토리 정보가 기록됩니다. 앞에서도 설명하였지만 파일 헤더와 다른 점이라면 “typeflag” 필드값이 “5”라는 것과 “name” 필드에는 파일명 대신에 패스명이 기록됩니다. 예를 들면 “sub1/sub2/”와 같지요. 다른 필드는 파일일 때와 같습니다.

디렉토리 정보가 없이 파일을 묶었을 때의 헤더 구조

예를 들어 TAR 아카이브 파일 내용 중에서 s1.txt 파일에 대한 헤더 구조를 덤프(dump)해 보면 아래와 같습니다.

< s1.txt 파일에 대한 헤더 구조 >

디렉토리 정보와 함께 기록된 파일에 대한 헤더 구조

  • sub/s1.txt
  • sub/s2.txt
  • sub/s3.txt

만약 위에서와 같이 s1.txt, s2.txt, s3.txt 파일이 모두 동일한 디렉토리 sub에 존재하며 이를 묶을 때 디렉토리 정보 sub를 기록했을 때 TAR 아카이브의 s1.txt 파일에 대한 헤더 구조를 덤프해 보면 아래와 같습니다.

< 디렉토리 정보가 기록된 s1.txt 파일의 헤더 구조 >

디렉토리 정보를 기록한 헤더 구조

  • sub/s1.txt
  • sub/s2.txt
  • sub/s3.txt

만약 위에서와 같이 s1.txt, s2.txt, s3.txt 파일이 모두 동일한 디렉토리 sub에 존재하며 이를 묶을 때 디렉토리 정보 sub를 기록했을 때 TAR 아카이브의 sub 디렉토리 헤더 구조를 덤프해 보면 아래와 같습니다.

< sub 디렉토리에 대한 헤더 구조 >

답글 남기기