selinux が原因だったので、 is_writable の実装探しの旅に出ても結局分からなかったと思われる。
が、気になったので、実装探しの旅に出てみることにした。
emacs + cscope で読むことにする。
php のソースコードを展開して、cscope のファイルを作成。
$ cd php-5.3.8 $ find ./ -name "*.h" -or -name "*.c" > cscope.files $ cscope -b -q -kemacs で展開したディレクトリあたりを開いて、 M-x cscope-find-global-definition is_writable を実行。
まぁそう簡単には見つからない。M-x cscope-find-this-symbol is_writable でいくつか候補が。
その中でそれっぽいのが、
*** ext/standard/php_filestat.h: <global>[39] PHP_FUNCTION(is_writable); ... *** ext/standard/basic_functions.c: ZEND_END_ARG_INFO[3194] PHP_FE(is_writable, arginfo_is_writable)宣言と定義っぽいのが見つかったが、マクロのようだ・・・
宣言っぽいほうを追っていくと
#define ZEND_FN(name) zif_##nameとか出てくる。zif_iswritable とか作られているのだろうか。
次に定義っぽい方を追っていくと、
const zend_function_entry basic_functions[] = { /* {{{ */ [snip] PHP_FE(is_writable, arginfo_is_writable)となっている。
関数ポインタを持った構造体の配列?これを追うのは大変そうだ・・・そもそもの仕組み知らないし・・・呼び出し元が探せない・・・
という訳で、GDB でステップ実行してみることに。
http://d.hatena.ne.jp/anatoo/20111117/1321463886
を参考にまず、まずコンパイル。
$ ./configure --disable-all --enable-debug $ makeでテスト用のスクリプト(~/test_is_writable.php)を作成。(前回通らないと思ってたが Web 経由だとユーザが異なっていてパーミッションの問題だったかも・・・パーミッション確認後、再度実行したらこのスクリプトは true となった)
<?php echo is_writable('/usr/local/etc/pgpool.conf');次に、GDB で実行。
$ gdb sapi/cli/php (gdb) break zif_is_writable Breakpoint 1 at 0x509b30: file /usr/local/src/php-5.3.8/ext/standard/filestat.c, line 1092. (gdb) run ~/test_is_writable.php後は、s と n で辿っていく。
ext/standard/filestat.c:782 の php_stat が実装のようだ。
さらに入っていくと、
eck_open_basedir_ex (path=0xb03350 "/usr/local/etc/pgpool.conf", warn=1) at /usr/local/src/php-5.3.8/main/fopen_wrappers.c:297の
if (PG(open_basedir) && *PG(open_basedir)) {あたりだろうか。
PG の定義は、
# define PG(v) (core_globals.v) extern ZEND_API struct _php_core_globals core_globals;_php_core_globals の open_basedir が設定されているかどうかを見ているっぽい。
が、open_basedir が分からない。
ググッて見ると、php.ini にそういう項目があるようだ。
このあたりをいじればいけるかと思ったがそうでもなかった。
テストスクリプトだと true となるのでこのあたりで断念。
結局追えなかった・・・