xzソースをgrepで解析する


アニメ『スロウスタート』

中学浪人して高校に入ると不安でしょうがないでしょうねえ。自分だったら、高校は諦めて自宅で勉強してたかもしれません。急がば回れというので、ゆっくりでも前に進むということが大事ですね。アニメですが、まだ2話しか見てないので、楽しみ方がいまいちわからない状態です。もう少し慣れが必要かも。

さて、今回は遠回りの解析をします。
前回作成したスクリプトを実行すると、このようなメッセージが表示されました。

takk@deb9:~$ chmod 755 c.out
takk@deb9:~$ ./c.out
xzcat: c.out.xz: Unexpected end of input
Hello
takk@deb9:~$ 

このメッセージどういう意味でしょう。xzのソースから調べたいと思います。
まず、xzが含まれるパッケージを知りたいので、apt-fileをインストール。

takk@deb9:~$ sudo apt-get install apt-file
takk@deb9:~$ apt-file update

xzコマンドの場所を確認。

takk@deb9:~$ which xz
/usr/bin/xz
takk@deb9:~$ 

パッケージを確認します。

takk@deb9:~$ apt-file search /usr/bin/xz
xz-utils: /usr/bin/xz
xz-utils: /usr/bin/xzcat
xz-utils: /usr/bin/xzcmp
xz-utils: /usr/bin/xzdiff
xz-utils: /usr/bin/xzegrep
xz-utils: /usr/bin/xzfgrep
xz-utils: /usr/bin/xzgrep
xz-utils: /usr/bin/xzless
xz-utils: /usr/bin/xzmore
xzdec: /usr/bin/xzdec
xzgv: /usr/bin/xzgv
xzoom: /usr/bin/xzoom
takk@deb9:~$ 

パッケージ名がxz-utilsであると分かったのでソースを取得します。

takk@deb9:~$ apt-get source xz-utils
takk@deb9:~$ cd xz-utils-5.2.2/
takk@deb9:~/xz-utils-5.2.2$ 

後ほどビルドも通すつもりなので、autoconfもいれておきます。

takk@deb9:~$ sudo apt-get install autoconf

では “Unexpected end of input” を検索します。

takk@deb9:~/xz-utils-5.2.2$ cd src
takk@deb9:~/xz-utils-5.2.2/src$ grep -r 'Unexpected.*input' *
xz/message.c:		return _("Unexpected end of input");
xz/main.c:				message_error(_("%s: Unexpected end of input "
xzdec/xzdec.c:				msg = "Unexpected end of input";
takk@deb9:~/xz-utils-5.2.2/src$ 

同じメッセージが複数のファイルで使われています。
いずれかに該当しているはずなので、動かして特定しようと思います。
ただし、それぞれのメッセージを区別できるようにしないと特定できないのでメッセージを置換します。

一括置換します。

takk@deb9:~/xz-utils-5.2.2/src$ for i in `grep -rl 'Unexpected.*input' *`;do echo $i;perl -pe "s#Unexpected.*input#HERE:[$i]#" -i $i;done
xz/message.c
xz/main.c
xzdec/xzdec.c
takk@deb9:~/xz-utils-5.2.2/src$ 

確認してみましょう。各ファイル名を埋め込んだので、これで特定できます。

takk@deb9:~/xz-utils-5.2.2/src$ grep -r HERE *
xz/message.c:		return _("HERE:[xz/message.c]");
xz/main.c:				message_error(_("%s: HERE:[xz/main.c] "
xzdec/xzdec.c:				msg = "HERE:[xzdec/xzdec.c]";
takk@deb9:~/xz-utils-5.2.2/src$ 

次はビルドです。configureしてmakeするだけです。

takk@deb9:~/xz-utils-5.2.2/src$ cd ..
takk@deb9:~/xz-utils-5.2.2$ ./configure
takk@deb9:~/xz-utils-5.2.2$ make

c.outファイルのxzcatを、さきほどビルドしたコマンドに置き換えます。

takk@deb9:~$ cat -n c.out | head -7
     1	#!/bin/bash
     2	tail -n +8 c.out > c.out.xz
     3	sleep 1
     4	~/xz-utils-5.2.2/src/xz/xz -dc c.out.xz > /tmp/c.out
     5	chmod 755 /tmp/c.out
     6	/tmp/c.out
     7	exit
takk@deb9:~$ 

c.outを実行します。

takk@deb9:~$ ./c.out
/home/takk/xz-utils-5.2.2/src/xz/.libs/xz: c.out.xz: HERE:[xz/message.c]
Hello
takk@deb9:~$ 

判明しました。messsage.cです。ソースを元に戻した上で、再度検索してみましょう。

takk@deb9:~/xz-utils-5.2.2$ grep -rn -C5 'Unex.*input' --include message.c
src/xz/message.c-810-
src/xz/message.c-811-	case LZMA_DATA_ERROR:
src/xz/message.c-812-		return _("Compressed data is corrupt");
src/xz/message.c-813-
src/xz/message.c-814-	case LZMA_BUF_ERROR:
src/xz/message.c:815:		return _("Unexpected end of input");
src/xz/message.c-816-
src/xz/message.c-817-	case LZMA_OK:
src/xz/message.c-818-	case LZMA_STREAM_END:
src/xz/message.c-819-	case LZMA_GET_CHECK:
src/xz/message.c-820-	case LZMA_PROG_ERROR:
takk@deb9:~/xz-utils-5.2.2$

LZMA_BUF_ERRORの時の表示されるメッセージのようです。
このエラーが何を表すのかは、コメントを見た方が早そうなので、再度検索。

takk@deb9:~/xz-utils-5.2.2$ grep -rn 'LZMA_BUF_ERROR' *
〜省略〜
src/liblzma/api/lzma/container.h:432: *              - LZMA_BUF_ERROR: Not enough output buffer space.
src/liblzma/api/lzma/container.h:611: *              - LZMA_BUF_ERROR: Output buffer was too small.
src/liblzma/api/lzma/filter.h:248: *              - LZMA_BUF_ERROR: Not enough output buffer space.
src/liblzma/api/lzma/block.h:518: *              - LZMA_BUF_ERROR: Not enough output buffer space.
src/liblzma/api/lzma/block.h:574: *              - LZMA_BUF_ERROR: Output buffer was too small.
〜省略〜

Output buffer was too small.
バッファが不足しているってことですね。

c.outに結合する前のc.out.xzファイルと、c.out実行時に抽出されたc.out.xzと比較してみます。

takk@deb9:~$ ls -l old/c.out.xz
-rwxr-xr-x 1 takk takk 2116  3月 10 19:57 old/c.out.xz
takk@deb9:~$ ls -l c.out.xz
-rw-r--r-- 1 takk takk 2117  3月 11 20:21 c.out.xz
takk@deb9:~$ 

サイズが違います。
つまり、圧縮されたデータサイズでバッファを用意しているのに、実際のファイルサイズがそれよりも大きいため、メッセージが出ていたということですね。
エディタで編集するときに、改行が入ったのでしょう。

takk@deb9:~$ od -tx1z c.out.xz | tail -2
0004100 00 04 59 5a 0a                                   >..YZ.<
0004105
takk@deb9:~$ 

ということで、先に比較しておけば、もっと簡単に解決したと思いますが、回り道をしたことでxzコマンドに関して少し強くなりました。

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA