[owner] タイムスタンプを更新しない時にエラー

  • ページ: BugTrack2
  • 投稿者: ishii
  • 優先順位: 低
  • 状態: 完了
  • カテゴリー: 本体バグ
  • 投稿日: 2005-04-12 (火) 05:41:16
  • バージョン: 今朝のCVS版

修正

「タイムスタンプを更新しない」にチェックして更新をかけたページについて、ファイルの owner がPHPのものではないとき、可能であれば(そのファイルが収められているディレクトリに、適切な書き込み権限があるならば) ファイルを再作成することによって owner を自動的に修正する。なお、ファイルのタイムスタンプは修正前のものを維持する。

  • cvs:lib/file.php (1.15-1.21)
    • 関数 pkwk_chown() を追加。可能であれば(ファイルを作り直すことで)ファイルのownerをPHPのものに修正する。元のファイルのタイムスタンプを保存する。Windows上ではUIDが適切に取得できないため、常にTRUEを返す。
    • 関数 pkwk_touch_file() を追加。pkwk_chown()を呼ぶtouch()のラッパー。
    • touch() の代わりに pkwk_touch_file() を呼ぶように修正

メッセージ

データファイルのオーナーがウェブサーバーの実行ユーザーではない時に凍結、凍結 解除、タイムスタンプを更新しないにチェックして更新すると以下のようなエラーが 出て終了してしまいます。

Touch failed for: 46726F6E7450616765.txt

レンタルサーバー等でパーミッションの変更は可能でも、オーナーを変更出来ない場 合が考えられるので lib/file.php の 1.13 -> 1.14 は戻しておいたほうが良いと思 いますがどうでしょうか?このチェックはチョット厳し過ぎるんじゃないかなぁ…な んて (^^;


  • そもそも編集時にファイルオーナーが違う場合にファイルを作り直すという処理をいれるのはなしでしょうか?そうなるとofficial:自作プラグイン/remakewiki.php とか消せて少しうれしいのですが。ちなみに remakewiki から必要となりそうな所を抜き出すと
    $phpuser = posix_getuid();
    if( fileowner("$file") != $phpuser ) {
         copy("$file","$file.tmp");
         unlink("$file");
         rename("$file.tmp","$file");
    }
    この程度かなと思います。copy して unlink して rename は処理的にいいかは微妙ですが。コードが短くてすんだので ^^; -- sonots 2005-04-12 (火) 13:12:12
  • http://jp2.php.net/manual/ja/ref.posix.php ここを見るとどうやらWindowsではPOSIX 関数が使えないみたいだけど…Windowsだとtouch()でエラーになったりしないのだろうか… -- ishii 2005-04-12 (火) 13:28:35
  • おお、そうは起きないかと思ったら、結構影響が大きいですね。直します (^^; -- henoheno 2005-04-14 (木) 22:29:24

(touch()のために)ファイル所有者の自動修正

  • chown(ファイル所有者の変更)を目的とするrenameを盛り込む場合、rename前にパーミッションをチェックしたり、copy/renameの手順を前後させたり(lock -> copy -> rename to 元のファイル?)、copyを作る場所を例えばcacheディレクトリの中にしたりした方が良いと思います。touchを使っているのはここだけではありませんから、もしやるのであればtouchのラッパーを書けば良いのでしょう。 -- henoheno 2005-04-14 (木) 22:30:19
  • ということで作ってみました。今後は、UIDが異なる場合は自動的に修正するようになります。お試し下さい。※余計な負荷がかかるのですから、あらかじめ直しておくに越した事はありません。 -- henoheno 2005-04-16 (土) 14:05:33
    • 確認したところ、posix_getuid() はWindowsでは使えません(そもそもposix エクステンションが無いようです)。また、Windows(IIS ISAPI)上のPHPから作成したファイルのUIDをstat()で調べても、現状必ず 0 が返るようです。= UIDにまつわる処理に関してはWindowsは対象にできないようです。と言ってもUIDにまつわる問題で困っているという話はUnix上の問題ですから、特に問題無いかもしれません -- henoheno 2005-04-16 (土) 14:09:09

「タイムスタンプを更新しない」にチェックして更新をかけたページについて、ファイルの owner がPHPのものではないとき、可能であれば(そのファイルが収められているディレクトリに、適切な書き込み権限があるならば) ファイルを再作成することによって owner を自動的に修正する。なお、ファイルのタイムスタンプは修正前のものを維持する。

  • cvs:lib/file.php (1.15-1.18)
    • 関数 pkwk_chown() を追加。可能であれば(ファイルを作り直すことで)ファイルのownerをPHPのものに修正する。元のファイルのタイムスタンプを保存する。Windows上ではUIDが適切に取得できないため、常にTRUEを返す。
    • 関数 pkwk_touch_file() を追加。pkwk_chown()を呼ぶtouch()のラッパー。
    • touch() の代わりに pkwk_touch_file() を呼ぶように修正

touch() の第三引数と マウント時の noatime オプション (r1.18)

  • 1.18試してみました。Debian/Woodyだとtouch()の第3引数の指定が何故か出来ない ようで、以下のようなエラーが出てしまいます。
    Warning: Wrong parameter count for touch() in lib/file.php on line 540
    pkwk_touch_file(): Invalid UID and (not writable for the directory or not a flie): 46726F6E7450616765.txt
    Sargeだと問題ないのですが… (^^; あと、mountオプションでnoatimeでmountされて いる場合も考えられるのでatime は指定しないほうが良いと思います。PukiWiki内部 でも参照している個所は無かったはずなので。あと、$tmpをコピーするとumaskが0022 の場合に実行権限が付いてしまうのでchmodも同時に行ったほうが良さそうです。 と言うことでパッチを書いてみました。 どうでしょうか? -- ishii 2005-04-17 (日) 05:21:50
    Index: lib/file.php
    ===================================================================
    RCS file: /cvsroot/pukiwiki/pukiwiki/lib/file.php,v
    retrieving revision 1.18
    diff -u -r1.18 file.php
    --- lib/file.php	16 Apr 2005 04:59:09 -0000	1.18
    +++ lib/file.php	16 Apr 2005 20:16:43 -0000
    @@ -537,8 +537,8 @@
     		// NOTE: @unlink() before rename() is for Windows but here's for Unix only
     		flock($ffile, LOCK_EX) or die('pkwk_chown(): flock() failed');
     		$result = copy($filename, $tmp) &&
    -			($preserve_time ? touch($tmp, $stat[9], $stat[8]) : TRUE) &&
    -			rename($tmp, $filename);
    +			($preserve_time ? touch($tmp, $stat[9]) : TRUE) &&
    +			chmod($tmp, 0666) && rename($tmp, $filename);
     		flock($ffile, LOCK_UN) or die('pkwk_chown(): flock() failed');
     
     		fclose($ffile) or die('pkwk_chown(): fclose() failed');
  • コメントありがとうございます :) まずは時間順に並べかえさせていただきました。 -- henoheno 2005-04-17 (日) 13:16:32
  • Debian woodyについてはもう少し PHP touch() について確認した方が良さそうです。PHPマニュアルに載っていない(undocumented)挙動なのかもしれませんね。 -- henoheno 2005-04-17 (日) 13:17:25
  • ファイルシステムのマウントオプション noatimeについてはそもそも「atime(アクセス時刻)の更新要求があってもそれを無視しろ」というもので、性能向上のために使われることがあるような代物ですから、テストはしていませんがatimeの変更要求をする事とはバッティングしないと思います(単に無視されるようになるだけで)。仮にnoatimeが問題になるとすればそれはPHPの実装の問題になると思います。 -- henoheno 2005-04-17 (日) 13:19:26
  • 一方で、今のところPHPマニュアルによればtouch()は第三引数まで存在することになっていて、pkwk_touch()も含めてそれをケアしてあります。それなのにpkwk_chownだけがatimeを無視するというのはお行儀が悪いので、本当にwoodyやPHP 4.1.x に恒久的にこの問題があるのだとしたら、代替案としては以下のようなものになると思います。 -- henoheno 2005-04-17 (日) 13:21:25
    - ($preserve_time ? touch($tmp, $stat[9], $stat[8]) : TRUE) &&
    + // touch() without atime for Debian woody or PHP 4.1.x or something
    + ($preserve_time ? (touch($tmp, $stat[9], $stat[8]) || touch($tmp, $stat[9])) : TRUE) &&
  • 久しぶりにVMwareの中のwoodyを引っ張り出して、折角なのでapt-getをかけて、cvs:../devel/release.sh で pukiwiki-HEADを取り出して、同じWarningが出ることを確認しました。ここで止まってしまうと、wikiディレクトリの中に移動中のファイルがゴミとして残ります。これを消すコードもいりそうです。 -- henoheno 2005-04-17 (日) 13:45:34
  • ふむ。テストコードを書きましたが、woody上のPHP 4.1.2 の touch() はFALSEではなくNULLを返しているようですね。 -- henoheno 2005-04-17 (日) 14:28:32
<?php
       $stat = stat(__FILE__);
       var_dump($stat);
       echo '<br>';
       var_dump(touch('test.txt', $stat[9], $stat[8]));
?>

apt-get source にてソースを引っ張り出しました。

該当のエラーを吐いている所:

./php4-4.1.2/Zend/zend_API.c:   zend_error(E_WARNING, "Wrong parameter count for %s()", get_active_function_name(TSRMLS_C));

PHP touch()関数だろう所:

./php4-4.1.2/ext/standard/filestat.c:PHP_FUNCTION(touch)
/* {{{ proto bool touch(string filename [, int time])
  Set modification time of file */
PHP_FUNCTION(touch)
{
       <snip>
       int ac = ZEND_NUM_ARGS();

       if (ac == 1 && zend_get_parameters_ex(1, &filename) != FAILURE) {
            <snip>
       } else if (ac == 2 && zend_get_parameters_ex(2, &filename, &filetime) != FAILURE) {
            <snip>
       } else {
               WRONG_PARAM_COUNT;
       }
  • 関数定義の先頭と、中にも書いてある通り、本当に三番目の引数には対応していないようです。PHPのCVSリポジトリでも確認しました。 -- henoheno 2005-04-17 (日) 15:00:18
  • 最初に実装されたのは filestat.c (revision 1.87) であるようです。このため、touch() の第三引数が利用できるようになったのは PHP 4.2.0 以降であるように見えます。(See http://cvs.php.net/php-src/ext/standard/filestat.c ) -- henoheno 2005-04-17 (日) 15:04:50
  • ということで発見者の ishii さんには http://jp.php.net/manual/en/function.touch.php にコメントする権利があると思います。どうしますか? :) -- henoheno 2005-04-17 (日) 15:09:05
    • ishiiさんお忙しくなってしまったかな? もう暫く反応がなければ、コメントしちゃいますね -- henoheno 2005-04-29 (金) 19:12:37
      • ああっ、すいません、コメントしちゃってください。*1 -- ishii 2005-04-30 (土) 22:27:15
    • コメントしてみました。採用されたとして、掲載されたり、日本のミラーに来るのは当分先でしょう。 -- henoheno 2005-07-10 (日) 22:41:43
    • この件、全然反映されていない気がする! -- henoheno 2007-08-31 (金) 23:49:02


  • 古いPHPの恒久的な問題であるようですので、先のコードを追加しました。 -- henoheno 2005-04-17 (日) 15:24:25
    • cvs:lib/file.php (1.20): (PHP 4 < PHP 4.2.0) touch() with the third argument is not implemented and retuns NULL and Warn (Notified by ishii)

chown

  • copy() で実行権がついてしまう件も確認しました。ただ読み取り・書き込み権限が意図しないものとなる事を嫌う管理者や環境もあるでしょうから、666固定でchmod() するよりもう少し綺麗な手がないか検討中です。 -- henoheno 2005-04-17 (日) 15:19:29
    • copy() する先のファイルをあらかじめtouch()で作成しておけば良いようですので、そうしておきます :) -- henoheno 2005-04-17 (日) 15:35:46
    • cvs:lib/file.php (1.21): touch() before copy() is for 'rw-r--r--' instead of 'rwxr-xr-x' (with umask 022). (Pointed out by ishii)


*1 GWって食べられるのかなぁ…(遠い目 orz

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2007-10-20 (土) 12:04:22
Site admin: PukiWiki Development Team

PukiWiki 1.5.2+ © 2001-2019 PukiWiki Development Team. Powered by PHP 5.6.40-0+deb8u7. HTML convert time: 0.318 sec.

OSDN