#navi_header|技術| RPMパッケージやAppleの"pax"インストーラ, Linux kernel 2.6でのinitramfsに使われていたりと、何気なく現役で使われている。 というわけで、例によって自分用メモ。 - GNU cpio -- http://www.gnu.org/software/cpio/cpio.html - GNU cpio HTML ドキュメント(1ページ版) -- http://www.gnu.org/software/cpio/manual/cpio.html - Linux jman cpio -- http://www.linux.or.jp/JM/html/GNU_cpio/man1/cpio.1.html - http://en.wikipedia.org/wiki/Cpio * 基本的な使い方 GNU cpio HTML ドキュメントにもTutorialが用意されており、基本は「Copy-out:アーカイブ作成」「Copy-in:アーカイブ展開」「Copy-pass:ディレクトリ単位でコピー」の3つのモードを使い分ける。 ** Copy-out : アーカイブ作成 cpio {-o|--create} その他オプション < 対象ファイル一覧 > アーカイブファイル 標準入力でファイル名の一覧を与えると、標準出力にアーカイブデータを出力する。findコマンドを組み合わせると使いやすくなる。 $ find . -print | cpio -ov > foo.cpio パイプでつなげれば、gzip圧縮もできる。拡張子としては".cpio.gz"や".cpgz"が使われるようだ。 $ find . -print | cpio -o | gzip > foo.cpio.gz ** Copy-in : アーカイブ展開 cpio {-i|--extract} その他オプション < アーカイブファイル 標準入力でアーカイブデータを与えると、アーカイブの展開を行う。 $ cpio -iv < foo.cpio "-t"オプションを指定すると、実際の展開は行わず入力ファイル名の一覧を表示するだけとなる。 $ cpio -t < foo.cpio ** Copy-pass : ディレクトリ単位でコピー cpio {-p|--pass-through} その他オプション コピー先ディレクトリ名 < 対象ファイル一覧 例: $ cd $ find . -print | cpio -pvd "-d"オプションをつけておくと、""が存在しない場合は自動的に作成してくれる。 * その他 ** 改行を含むファイル名 ファイル名に改行を含むファイルをアーカイブしたい場合は、"-0"または"--null"で、ファイル名の一覧がNULL区切りであることを指示しておく。 同時に、findコマンドでファイル名をNULL区切りにするよう"-print0"を使う。 $ find . -print0 | cpio -ov0 > foo.cpio $ find . -print0 | cpio --null -ov > foo.cpio ** findコマンドと組み合わせる時の、findの"-depth"オプション GNU cpio HTMLドキュメントのTutorialを読んでいたら、findコマンドに"-depth"オプションをつけた例がある。 find . -print -depth | cpio -ov > tree.cpio これについて実際に実験してみて、「何故 "-depth" 付を推奨しているのか」分かったのでメモ。ちなみにCentOS 5.2 の GNU find 4.2.27 を使うと、"-print -depth"の順にするとwarningが出てしまったので、以降は"-depth -print"の順にしている。 まず、"-depth"オプション(or "-d")を指定すると「ディレクトリ階層が深い方を優先して処理する」ようになる。 例: #pre||> $ cd cpio_test/ $ find . . ./foo ./foo/bar ./foo/bar/test3.txt ./foo/test2.txt ./test1.txt $ find . -depth ./foo/bar/test3.txt ./foo/bar ./foo/test2.txt ./foo ./test1.txt . ||< これとcpioを組み合わせ、展開した時の動作を考えてみる。 - "-depth"無し:先にディレクトリを作成し、権限を復元し、次にディレクトリの中のエントリを展開していく。 - "-depth"有り:まずディレクトリ中のエントリを展開し、最後にディレクトリの権限を復元する。 このため、"-depth"有りで作成されたcpioアーカイブを展開する時は cpio -i < foo.cpio ではなくて、"-d"でディレクトリの自動作成を有効にした上で展開する必要がある。 cpio -id < foo.cpio もし"-d"を使わない場合は、予めディレクトリだけは作成しておく必要がある。 わざわざ"-depth"有りの動作を使う理由は、ディレクトリの権限が特殊な場合を想定しているからである。 一番分かりやすい例だと、そのディレクトリ権限の所有者bitから"w"が落ちている場合である。 #pre||> $ cd cpio_test/ $ find . | xargs ls -ld drwxrwxr-x 3 msakamoto msakamoto 4096 11月 18 19:07 . drwxrwxr-x 3 msakamoto msakamoto 4096 11月 18 19:09 ./foo dr-x------ 2 msakamoto msakamoto 4096 11月 18 19:14 ./foo/bar ^ "test3.txt"を作成後に、chmod u-w して"w"権限を落としている。 -rw-rw-r-- 1 msakamoto msakamoto 10 11月 18 19:14 ./foo/bar/test3.txt -rw-rw-r-- 1 msakamoto msakamoto 6 11月 18 19:08 ./foo/test2.txt -rw-rw-r-- 1 msakamoto msakamoto 6 11月 18 19:08 ./test1.txt ||< この場合に、"-depth"無しでアーカイブしたcpioを展開すると、"foo/bar/test3.txt"が展開できなくなる。 + "./foo/bar" ディレクトリを作成+権限を復元 → ownerの"w"フラグが落ちる。 + "./foo/bar/test3.txt" ファイルを作成しようとするが、ディレクトリの"w"フラグが落ちているので書き込めない。 実際にやってみる: #pre||> $ cd cpio_test/ $ find . -print | cpio -o > ../test1.cpio $ cd ..; mkdir test1; cd test1 $ cpio -iv < ../test1.cpio . foo foo/bar cpio: foo/bar/test3.txt: 許可がありません foo/bar/test3.txt foo/test2.txt test1.txt 1 block ||< こういう場合に "-depth"有りでアーカイブしておけば、中のファイルツリーを展開した後で権限を復元するようになるので、問題は発生しなくなる。 実際にやってみる: #pre||> $ cd cpio_test/ $ find . -depth -print | cpio -o > ../test2.cpio $ cd ..; mkdir test2; cd test2 $ cpio -ivd < ../test2.cpio # ← "-d"オプションを忘れずに! foo/bar/test3.txt foo/bar foo/test2.txt foo test1.txt . 1 block ||< #navi_footer|技術|