Tarning for Windows – MacやLinuxでの安全なtarファイルの作りかた

LinuxやMacで作成したtarアーカイブをWindowsで展開したときに,本来なら深い階層にあるはずのディレクトリが一番上の階層に展開されてしまったことはないでしょうか?展開したファイルの中に”PaxHeader”という見慣れないディレクトリが作られてしまったことは?これは,tarアーカイブの各種フォーマット規格の違いと.それぞれが持つ制約が原因となって起こる現象です.今回は「”Tarning” for Windows」と題して,Windowsで安全に展開可能なtarアーカイブを作成する方法について考えてみたいと思います.

まず,tarアーカイブと一言でいっても,そのフォーマットには下記のようにいくつもの規格が存在しています.

  • v7: Version 7 Unix(V7)での実装と互換性のあるフォーマット
  • ustar: POSIX.1-1988によって策定されたフォーマット
  • pax: POSIX.1-2001によって策定されたフォーマット
  • gnutar: GNU tarのデフォルトフォーマット

それぞれ,以下の表のように各フォーマットで利用できるファイル名の最大長などが異なっています.

Format UID ファイルサイズ ファイル名 デバイス番号
v7 2097151 8GB 99byte n/a
ustar 2097151 8GB 256byte 21bit
pax 制限なし 制限なし 制限なし 制限なし
gnutar 1.8e19 制限なし 制限なし 63bit

参考: GNU tar 1.26: 8. Controlling the Archive Format

さて早速ですが,各フォーマットで作成したtarアーカイブをWindowsで展開するとどのような結果になるでしょうか.現在Windowsで一般的に利用されている下記のソフトを利用して実験してみます.

※tar32.dllの実行には同梱のminitar.exeを利用

各ソフトでの展開の可否をまとめたものが下記の表です.なお,v7では制約上99文字のファイル名を,その他のフォーマットでは256文字のファイル名を用いてアーカイブを作成しています.

v7 ustar pax gnutar
Lhaplus ver1.59 × × ×
+Lacha ver1.24 × ×
tar32.dll ver0.53 × × ×
tar32.dll ver2.24

結果として,最も原始的なv7以外のフォーマットでは,「tar32.dll ver2.24」の除いてほぼ全滅のようです(ちなみに99文字以内のファイル名を用いた場合は,ustarやgnutarフォーマットでもすべてのソフトで展開が可能です).つまりWindows環境で展開することを想定してtarアーカイブを作成する場合,できる限りv7フォーマットを用いると安全ということになります.

次は安全なtarアーカイブの作成方法について検討してみましょう.まず,LinuxやMacで普通にtarアーカイブを作成すると,v7フォーマットは用いられません.LinuxとMac 10.5以前ではGNU tarが標準のtarコマンドとなっているため,gnutarフォーマットが利用されます.一方,Macの10.6以降ではlibarchiveが標準となっているため,paxフォーマットがデフォルトで用いられます.なお,GNU tarも将来的にはPOSIX準拠のpaxフォーマットをデフォルトとする予定のようです.

GNU tarでv7フォーマットのtarアーカイブを作成するには”–format=v7″オプションを指定します.

$ tar -c --format=v7 -f a.tar file

また,v7フォーマットを指定することで,ファイル名が99文字を超えるファイルをアーカイブしようとしたときには警告が表示されます.

$ tar -c --format=v7 -f a.tar 0...00000
tar: 0.....00000: file name is too long (max 99); not dumped

ただ,Mac OS 10.6以降では標準のtarがlibarchiveを利用するbsdtarに差し替えられており,残念ながらbsdtarはv7フォーマットのtarアーカイブ作成をサポートしていません.

$ tar --version
bsdtar 2.8.3 - libarchive 2.8.3
$ ls -l /usr/bin/tar
lrwxr-xr-x 1 root wheel 6 8 12 16:48 /usr/bin/tar -> bsdtar

でもご心配なく.10.6以降のMacにも,ちゃんとGNU版のtarが,”gnutar”コマンドとして残されています.こちらを利用すれば,Macでもv7フォーマットのtarアーカイブを生成することができます.

$ ls -l /usr/bin/gnutar
-rwxr-xr-x 1 root wheel 336112 8 12 16:47 /usr/bin/gnutar
$ gnutar -c --format=v7 -f a.tar file

もしbsdtarではなくgnutarを標準のtarとして利用したい場合は,シンボリックリンクを差し替えてしまっても良いでしょう.

$ sudo rm /usr/bin/tar
$ sudo ln -s /usr/bin/gnutar /usr/bin/tar

というわけで,今回はWindows環境で安全に展開できることを目的としたtarアーカイブの作成方法についてご紹介しました.ただ,今回のケースに限らず,tarアーカイブの可搬性の高めるためにはv7フォーマットで作成すると安全です.GNUのautomakeなどもまだv7フォーマットがデフォルトで利用されています.
tarアーカイブのフォーマットや可搬性に関する話題については,ここここに良くまとまっています.もし興味があればご覧下さい.

最後にオマケを.Macでgnutarを用いてtgzファイルを生成する簡単なスクリプトを作成しました.圧縮したいファイルを第一引数に与えて実行すると,リソースフォークと.DS_Storeを除外して,圧縮対象ファイルと同じディレクトリにtgzファイルを生成します.一応自己責任ということでご利用下さい.

#!/usr/bin/env bash

tar="/usr/bin/gnutar"
format="v7"

if [ -z "$1" ]; then
echo "Usage: $(basename $0) file" 1>&2
exit 1
fi

if [ ! -e "$1" ]; then
echo "$(basename $0): '$1' is not found." 1>&2
exit 1
fi

dir="$(dirname "$1")"
src="$(basename "$1")"
dst="$src.tgz"
echo "Creating '$dst'"

# リソースフォークの無視
# 10.4以前 COPY_EXTENDED_ATTRIBUTES_DISABLE
# 10.5以降 COPYFILE_DISABLE
COPY_EXTENDED_ATTRIBUTES_DISABLE=1 \
COPYFILE_DISABLE=1 \
$tar -cvz --format=$format \
--exclude=.DS_Store \
-f "$dir/$dst" -C "$dir" "$src"

また,上記のスクリプトをPlatypusでapp化したものも作りましたのでリンクを張っておきます.ドラッグアンドドロップでファイルを放り込めばtgzファイルが生成されます.
mktgz-1.0.dmg