試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

Mandriva Linux 2009.1でGNU screenのRPMパッケージが再ビルドできない件とその対処(前半)

Mandriva Linuxのバージョン2009.0のときに自前で修正もしくは作成したパッケージの内の幾つかを再ビルドしている中で、256色モードサポートなどの目的で修正したGNU screenのパッケージが2009.1上でビルドできなかった。

  1. パッチ適用時のズレ許容度(曖昧度合い)
  2. printf()のフォーマット引数に関するエラー

パッチ適用時のズレ許容度(曖昧度合い)

最初に出たエラーは下のようになった。

+ echo 'Patch #1 (screen-ia64.patch):'
Patch #1 (screen-ia64.patch):
+ /usr/bin/patch -U -s -p1 --fuzz=0 -i /home/mandrake/rpm/SOURCES/screen-ia64.patch
1 out of 1 hunk FAILED -- saving rejects to file configure.in.rej
error: Bad exit status from /var/tmp/rpm-tmp.sGONA7 (%prep)


RPM build errors:
    Bad exit status from /var/tmp/rpm-tmp.sGONA7 (%prep)

パッチの適用に失敗しているが、手動でやってみると

$ patch -p1 < ../../SOURCES/screen-ia64.patch                    
patching file configure.in
Hunk #1 succeeded at 664 with fuzz 1 (offset 61 lines).

ズレがあるものの適用はされた。しかし、パッケージビルドの中で付けられている--fuzz=0オプションを付けると

$ patch --fuzz=0 -p1 < ../../SOURCES/screen-ia64.patch
patching file configure.in
Hunk #1 FAILED at 603.
1 out of 1 hunk FAILED -- saving rejects to file configure.in.rej

適用に失敗した。
今回は

$ patch --fuzz=1 -p1 < ../../SOURCES/screen-ia64.patch
patching file configure.in
Hunk #1 succeeded at 664 with fuzz 1 (offset 61 lines).

「1」指定でOKだったが、2009.1になってどこでこれが付くようになったのかを調べてみると

$ grep fuzz /usr/lib/rpm -r       
/usr/lib/rpm/macros:#   Default fuzz level for %patch in spec file.
/usr/lib/rpm/macros:%_default_patch_fuzz        0
/usr/lib/rpm/macros:%apply_patches %{lua: keys = {}; for i, p in ipairs(patches) do print(rpm.expand("%{_patch} -s -p1 -b --suffix " .. string.format(".%04d", patches_num[p]) .. " --fuzz=%{_default_patch_fuzz} -i " .. p .. "\\n")) end }

「_default_patch_fuzz」というマクロがそのレベルを定めているようだということが分かった。そこで
ファイル名: /home/[RPMパッケージビルド用ユーザ]/.rpmmacros

%_default_patch_fuzz 2

のようにマクロ定義を行ったところ、パッチは当たるようになった。しかし、正確に一致するようにパッチ側を修正したほうがよいのかもしれない。

printf()のフォーマット引数に関するエラー

今度は本体のソースでエラーが出た。

gcc -c -I. -I.    -O2 -g -pipe -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -DETCSCREENRC=\"/etc/screenrc\" screen.c
(中略)
screen.c: In function ‘MakeNewEnv’:
screen.c:1894: error: format not a string literal and no format arguments
(中略)
screen.c: In function ‘setbacktick’:
screen.c:2222: error: format not a string literal and no format arguments
screen.c:2244: error: format not a string literal and no format arguments
(中略)
make: *** [screen.o] Error 1
error: Bad exit status from /var/tmp/rpm-tmp.F9zaV8 (%build)

警告も出ているが略した。該当部分は

Panic(0, strnomem);

Msg(0, strnomem);

となっていて、ともに

int err, char *fmt, ...(可変長引数)

という引数の取り方をしている。「strnomem」というのは

char strnomem[] = "Out of memory.";

のように定義されている文字列。
エラーメッセージなどで調べると、GCC-Wformat -Werror=format-securityという2つのオプション群を付けるとprintf()のようなフォーマット引数を取ることのできる関数でフォーマット部分(printf()の場合は最初の引数)の後ろに引数がないとエラーを出すことが分かった(セキュリティ問題対策で用意されているオプションのようだ)。
このオプションが付いたのは

$ grep format-security /etc/rpm -r    
/etc/rpm/macros.d/10manbo-build.macros:%Werror_cflags -Wformat -Werror=format-security

上のファイルであると分かったため「%Werror_cflags」を上書きすればビルドできなくはないのだが、それでは問題なので、このエラーを解決するために実験を行った。

関連URL: