GNU tar는 왜 추출이 느릴까
(mort.coffee)- 518GiB tar.gz를 풀면서 엄청나게 느려지는 것 때문에 조사 시작
- Tar 포맷에 대한 설명과 빠른 tar extractor 코드를 작성하며 설명
오리지널 Tar 파일 포맷
- Tar는 아카이브 파일로는 매우 이례적임
→ 아카이브 헤더가 없고, 검색용 파일 인덱스가 없으며, tar 인지 확인 가능한 매직바이트도 없고, 푸터도 없고, 메타데이터도 없음
→ Tar 안에 있는 것은 파일 개체 한 종류임 - 파일 타입 : 0 (일반 파일), 1 (하드 링크), 2 (심볼릭 링크)
- 512바이트 파일 객체 헤더의 구조 설명
→ 가장 큰 제한은 파일 경로 길이가 100글자 밖에 안된다는 것. 또한 파일 크기는 8GiB가 최대
UStar 확장 파일
- 파일 경로 길이가 최대 256 이고, 새로운 파일 타입들 추가
- 헤더를 확장하여 매직 바이트 및 prefix 필드 추가
- 파일 타입 추가 : 3 (캐릭터 디바이스), 4 (블록 디바이스), 5 (디렉토리), 6 (FIFO 파일), 7 (연속 파일)
- 하지만 8GiB 크기 한도는 여전 함
Pax 파일 포맷
- POSIX.1-2001 표준으로 pax CLI를 통해서 tar 포맷을 확장
- UStar와 동일하지만 x 와 g 파일 포맷 추가
→ 확장 헤더 레코드로 x 는 다음 파일에만 적용되며, g 는 뒤의 모든 파일에 적용
GNU Tar 파일 포맷
- 자체 포맷은 gnu 로 pax 와는 다름
- pax 와 비슷하게 UStar 기반이지만, 경로 및 큰 파일을 인코딩하는 다른 방법을 사용
→ 'L' 타입 : 다음 파일 객체의 페이로드가 "file_path" 를 나타냄
→ 'K' 타입 : 다음 파일 객체의 페이로드가 "link_path" 를 나타냄
→ 두가지를 연속으로 적용 가능
→ 파일이 8GiB 보다 크다면 file_size 첫 글자의 하이비트를 세팅. 그러면 문자열의 나머지를 base 256으로 파싱 (95비트 Integer)
왜 GNU tar는 느리게 압축을 해제할까 ?
- 파일의 헤더에
file_path="../hello.txt"
같은 값을 넣으면 보안 문제 발생. 하지만 막기가 쉽지 않음 - GNU tar 는 link_path에 ".."를 만나면 플레이스홀더를 생성하고 딜레이 해서 처리함
- 하지만 ".."가 없는 하드링크의 경우엔 직접 생성하고 싶지만 이미 플레이스홀더가 있기 때문에 생성이 불가
- 즉, 하드링크를 생성하려면 그게 딜레이드 링크인지 먼저 다 확인 해야하며, 그렇다면 새 링크 역시 딜레이 처리해야함
→ 모든 하드링크에 대해서 딜레이드 링크를 탐색해야함. 이유는 모르겠지만 실제로는 2번 탐색함 - 작성자의 Tar파일에는 80만개가 넘는 ".."를 가진 링크와 540만개 이상의 하드링크가 있었기에 압축 해제가 느려진 것
- 이를 방지하기 위해서는
--absolute-paths
또는-P
옵션을 tar에 추가할 것
→ 절대 경로를 저장하며 ".." 를 거부하는 옵션
→ 즉 -P 옵션을 주면 딜레이드 링킹 메커니즘을 비활성화
Tar 관련 글은 항상 재미난 것 같아요..
hop - tar 보다 10배 빠른 아카이브 포맷
왜 Python으로 만든 tar.xz 파일이 기본 tar로 만든 파일보다 작나요?