先日、TARにはpaxフォーマットがあるからこれを使おうという記事を書いた:
ところで、自分のマシンではGNU TARが入っていて、デフォルトでpaxを使う設定になっていた(これはコンパイルタイミングで設定される)。自分はopenSuSE Tumbleweedを利用しているが、他のディストリビューションではどうなっているのだろう?そもそも、GNU TARがどのフォーマットをデフォルトで吐くかは決まってないってみんな知ってた?
The default format for GNU tar is defined at compilation time.
わざわざディストリビューションをインストールしなくても、実際に欲しいのは各ディストリビューションにおける(GNU) TARの実行結果である。そしてこれはdockerを実行すれば簡単に得られることに気付いた。
そこで、以下のよく使われるディストリビューションについて、tar --helpを実行して得られたデフォルトフォーマットを抽出してみることにした:
ubuntu debian alpine fedora rockylinux almalinux oraclelinux archlinux opensuse/leap amazonlinux
手法
以下のスクリプトを実行する。rockylinuxとoraclelinuxにはlatestが存在しなかったため執筆タイミングで最新のイメージを指定した。またデフォルトでtarが含まれないディストリビューションがあるため、この場合はインストールコマンドを実行させた:
check-all.sh
#!/bin/sh set -eux set -o pipefail LISTFILE=./images.txt VERIFIER=./check-tar-default-format.sh while read LINE; do IMAGE=$(echo "${LINE}" | awk -F ':' '{print $1}') TAG=$(echo "${LINE}" | awk -F ':' '{print $2}') PRERUN=$(echo "${LINE}" | awk -F ':' '{print $3}') $VERIFIER "${IMAGE}" "${TAG}" "${PRERUN}" done < $LISTFILE
check-tar-default-format.sh
#!/bin/sh set -ux set -o pipefail IMAGE=$1 TAG=${2:-latest} PRERUN=${3:-} echo "## $IMAGE" if [ ! -z "$PRERUN" ]; then docker run --rm ${IMAGE}:${TAG} sh -c "$PRERUN && tar --help" | grep -F -e '*This* tar defaults to:' -A 1 | sed -ne '1d;s/\s.*$//;p'; else docker run --rm ${IMAGE}:${TAG} sh -c "tar --help" | grep -F -e '*This* tar defaults to:' -A 1 | sed -ne '1d;s/\s.*$//;p' fi if [ $? -ne 0 ]; then echo 'N/A' fi
images.txt
ubuntu debian alpine fedora rockylinux:9.3 almalinux oraclelinux:10 archlinux opensuse/leap:latest:zypper install -y tar amazonlinux:latest:yum install -y tar
結果(2025-09-17時点)
## ubuntu --format=gnu ## debian --format=gnu ## alpine N/A ## fedora --format=gnu ## rockylinux --format=gnu ## almalinux --format=gnu ## oraclelinux --format=gnu ## archlinux --format=gnu ## opensuse/leap --format=posix ## amazonlinux --format=gnu
ほとんどのディストリビューションはGNU拡張形式を利用していることがわかった。冒頭で紹介した記事にも書いたが、GNU拡張形式はGNU TARにしか実装されていない独自の拡張形式であり、使うべきではない。paxを使うべきである。
また、opensuseはposix(これはpaxのシノニム)を利用していることがわかった。自分のマシンのtarがpaxを利用していたのも、opensuseを利用していたからだった。
alpineのtarはどのtarか
最後にalpineは検出に失敗している。これは、alpineに入っているtarはbusybox由来のものであるためだ。そこでtar.cを読みに行く。
するとマジックナンバーとしてGNU拡張のものを書いているっぽい。しかしGNU特有のヘッダは使わず、内容はustarに寄せている感じの素朴な実装になっている。
以下の記事によれば、LまたはKファイルタイプが出現すればGNU拡張だといえるし、xまたはgファイルタイプが出現すればpaxである。
しかしながらこのいずれもソースコードには登場しないため、互換性のためにGNU拡張のようなヘッダを利用しつつ、実質的にはustarを読み書きしているものと思われる。
また、ソースコードには以下のような記述がある:
/* POSIX tar Header Block, from POSIX 1003.1-1990 */ struct TarHeader { /* byte offset */ char name[100]; /* 0-99 */ char mode[8]; /* 100-107 */ char uid[8]; /* 108-115 */ char gid[8]; /* 116-123 */ char size[12]; /* 124-135 */ char mtime[12]; /* 136-147 */ char chksum[8]; /* 148-155 */ char typeflag; /* 156-156 */ char linkname[100]; /* 157-256 */ char magic[6]; /* 257-262 */ char version[2]; /* 263-264 */ char uname[32]; /* 265-296 */ char gname[32]; /* 297-328 */ char devmajor[8]; /* 329-336 */ char devminor[8]; /* 337-344 */ char prefix[155]; /* 345-499 */ char padding[12]; /* 500-512 (pad to exactly the TAR_BLOCK_SIZE) */ };
POSIX 1003.1-1990はPOSIX 1003.1-1988の後継であるため、ustarを使っているとみて間違いない。