ソースコード・リテラシーのススメ

第8回 ソースコードを追いかける

この記事を読むのに必要な時間:およそ 6 分

設定ファイルの確認

lib/utimens.cの中でAT_FDCWDが使われているのは# if HAVE_FUTIMESAT ~#endifで括られた中でした。すなわち,HAVE_FUTIMESATというシンボルが定義されていなければこの部分は通らないのでエラーにはならないはずです。そこでHAVE_FUTIMESATというシンボルはどこで定義されているかを調べてみました。

 kojima@vmathlon/tar-1.19]% find . ¦ xargs grep HAVE_FUTIMESAT
 ./lib/utimens.c:#if HAVE_FUTIMESAT ¦¦ HAVE_WORKING_UTIMES
 ...
 ./config.log:¦ #define HAVE_FUTIMESAT 1
 ./config.log:#define HAVE_FUTIMESAT 1
 ./config.h:#define HAVE_FUTIMESAT 1

HAVE_FUTIMESATはconfig.hの中で 1 に定義されているようです。config.hはconfigureスクリプトによって生成されるファイルなので,configureスクリプトが「このシステムにはfutimesatという機能がある」と判断したことになります。そこでfutimesatをキーワードにconfigureスクリプトのログconfig.logを調べてみたところ,このような部分がありました。

 configure:9225: checking for futimes
 configure:9281: gcc -std=gnu99 -o conftest -g -O2   conftest.c  >&5
 configure:9287: $? = 0
 configure:9305: result: yes
 configure:9225: checking for futimesat
 configure:9281: gcc -std=gnu99 -o conftest -g -O2   conftest.c  >&5
 configure:9287: $? = 0
 configure:9305: result: yes

この結果を見ると,configureスクリプトがテスト用のCプログラムをコンパイルしてみて大丈夫だったから,futime, futimesatが使えることを示すHAVE_FUTIMESATやHAVE_FUTIMESといったシンボルが#defineされたのだろうことがわかります。

それでは,futimesatやfutimesはシステム的にどう定義されているのでしょう?

 kojima@vmathlon/tar-1.19]% find /usr/include ¦ xargs grep futimesat
 find /usr/include ¦ xargs grep futimesat
 kojima@vmathlon/tar-1.19]% find /usr/include ¦ xargs grep futimes
 find /usr/include ¦ xargs grep futimes
 /usr/include/sys/time.h:extern int futimes (int __fd, __const struct timeval __tvp[2]) __THROW;

この結果を見ると,futimesは/usr/include/sys/time.hで定義されているもののextern定義になっているので,実態はどこか別にあるはずです。またfutimesatは該当する定義が見つかりません。

本稿では触れていませんが,このあたりでfutimesやfutimesatがどういう機能なのかをGoogleで調べて,どうやらutimesのファイルディスクリプタ版だ,という理解も得ています。

これを見る限り,この環境でconfig.hにHAVE_FUTIMESATやHAVE_FUTIMESという定義が行なわれることがおかしいようです。そこで,HAVE_FUTIMESの定義部分をコメントアウトして,再コンパイルを試してみました。

config.hのコメントアウト部分

 /* Define to 1 if you have the `futimes' function. */
 /* #define HAVE_FUTIMES 1 */
 kojima@vmathlon/tar-1.19]% make
 make
 make  all-recursive
 ...
 make[2]: Leaving directory `/home/kojima/tar-1.19'
 make[1]: Leaving directory `/home/kojima/tar-1.19'
 kojima@vmathlon/tar-1.19]%

今度は無事tar-1.19のコンパイルが終了しました。どうやら,この環境(Plamo-4.22β1)では,本来は存在しないfutimesやfutimesatという関数が,configureスクリプトには存在すると誤認され,不適切な設定ファイル(config.h)が生成されたことによるエラーだったようです。

あまり綺麗な方法ではありませんが,この程度の修正ならばconfigureスクリプトを実行してから,config.hファイルをsed等で修正するような処理を追加すればパッケージ化することも可能でしょう。

その後の展開

とりあえずPlamo-4.22β1の環境でtar-1.19をコンパイルする方法は見つかったのですが,config.hを修正するというのはあまり綺麗な方法ではないので,改めて正式公開版のPlamo-4.22の環境でどうなるかを試してみたところ,config.hを修正する必要もなくconfigure && make でコンパイルが完了してしまいました。

あれれ,と思いつつPlamo-4.22環境でAT_FDCWDというシンボルが存在するかを調べると,

 kojima@xeon]% find /usr/include ¦ xargs grep AT_FDCWD
 /usr/include/linux/fcntl.h:#define AT_FDCWD             -100    /* Special value used to indicate

となり,/usr/include/linux/以下に収められたカーネルのヘッダファイルの中でAT_FDCWDという定数が設定されているようです。そこで,Plamo-4.22β1と4.22の間でカーネルのヘッダファイルがどう変ったのかを調べると,4.22β1ではglibc2をコンパイルした環境であるLinux 2.6.14由来のヘッダファイルを使っていたのに対し,4.22ではインストールするカーネルと同じ2.6.22.9由来のヘッダファイルを使っていました。すなわち,2.6.14 から2.6.22.9の間のどこかで,カーネルヘッダにAT_FDCWDという定数が設定されるようになり,その結果,両者の間で動作の違いが生じていたようです。

/usr/include/linux/以下に収めるカーネルのヘッダファイルをどのように用意するかはさまざまな流儀があります。昔のLinuxでは/usr/src/linux/以下にソースコードを展開し,/usr/include/linuxは/usr/src/linux/includeへのシンボリックリンクにする,という形でソースコードにあるヘッダファイルをそのまま利用する,という方法が取られていました。

しかし,カーネルのソースコードが急速に変化していくのに対して,システムのCライブラリ(glibc2)の変化は緩慢なため,カーネルのヘッダファイルを直接利用すると,Cライブラリとの間に齟齬が生じるという問題が指摘され,Cライブラリをビルドした際のカーネルヘッダファイルを別途用意しておくようなスタイルに移行したことがあります。Plamo-4.22β1では,そのようなスタイルを採用していたので,カーネルのヘッダファイルはglibc-2.3.6をコンパイルした2.6.14カーネルの環境を利用していました。

しかしながらこの方法では,カーネルに新しい機能が組み込まれても,それに対応したバージョンのCライブラリが用意されるまではその機能を利用できない,という不便さが指摘され,最近ではカーネルのソースコードのうち,ユーザ空間から利用してもいいヘッダファイルのみを取り出すmake headers_installという機能がカーネルのMakefileに用意され,/usr/include/linux/等にはこのコマンドで取り出されたヘッダファイルを配置するような流儀になっています。Plamo-4.22では,このスタイルを採用してカーネルのヘッダファイルのパッケージを更新したおかげで,AT_FDCWDという定数がユーザ領域のソフトウェア(tar-1.19)から利用できるようになっていた,というのが両者の違いだったようです。

この結果を踏まえると,β1環境での修正も,HAVE_FUTIMESをコメントアウトして機能を削除するよりも,AT_FDCWDを-100に定義するような修正を追加する方がいいでしょう。ただ,そもそもβ1環境というのは開発の途中経過であり,現在では問題自体が存在しなくなっているので,この件については,この連載の中に記録するだけに留めることにしました。

著者プロフィール

こじまみつひろ

Plamo Linuxとりまとめ役。もともとは人類学的にハッカー文化を研究しようとしていたのが,いつの間にかミイラ取りがミイラになってOSSを仕事にするようになってしまいました。最近はスペシャリスト養成を目的とした専門職大学院で教壇に立ったりもしています。

URLhttp://www.linet.gr.jp/~kojima/Plamo/index.html