* [owner] タイムスタンプを更新しない時にエラー [#y6b9799a]
-ページ: [[BugTrack2]]
-投稿者: [[ishii]]
-優先順位: 低
-状態: 完了
-カテゴリー: 本体バグ
-投稿日: 2005-04-12 (火) 05:41:16
-バージョン: 今朝のCVS版
** 修正 [#q6568821]
「タイムスタンプを更新しない」にチェックして更新をかけたページについて、ファイルの 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() を呼ぶように修正
----
**メッセージ [#j216a019]
データファイルのオーナーがウェブサーバーの実行ユーザーではない時に凍結、凍結
解除、タイムスタンプを更新しないにチェックして更新すると以下のようなエラーが
出て終了してしまいます。
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]] &new{2005-04-12 (火) 13:12:12};
-http://jp2.php.net/manual/ja/ref.posix.php ここを見るとどうやらWindowsではPOSIX 関数が使えないみたいだけど…Windowsだとtouch()でエラーになったりしないのだろうか… -- [[ishii]] &new{2005-04-12 (火) 13:28:35};
-おお、そうは起きないかと思ったら、結構影響が大きいですね。直します (^^; -- [[henoheno]] &new{2005-04-14 (木) 22:29:24};
------------------
** (touch()のために)ファイル所有者の自動修正 [#z4b245a9]
-chown(ファイル所有者の変更)を目的とするrenameを盛り込む場合、rename前にパーミッションをチェックしたり、copy/renameの手順を前後させたり(lock -> copy -> rename to 元のファイル?)、copyを作る場所を例えばcacheディレクトリの中にしたりした方が良いと思います。touchを使っているのはここだけではありませんから、もしやるのであればtouchのラッパーを書けば良いのでしょう。 -- [[henoheno]] &new{2005-04-14 (木) 22:30:19};
-ということで作ってみました。今後は、UIDが異なる場合は自動的に修正するようになります。お試し下さい。※余計な負荷がかかるのですから、あらかじめ直しておくに越した事はありません。 -- [[henoheno]] &new{2005-04-16 (土) 14:05:33};
-- 確認したところ、posix_getuid() はWindowsでは使えません(そもそもposix エクステンションが無いようです)。また、Windows(IIS ISAPI)上のPHPから作成したファイルのUIDをstat()で調べても、現状必ず 0 が返るようです。= UIDにまつわる処理に関してはWindowsは対象にできないようです。と言ってもUIDにまつわる問題で困っているという話はUnix上の問題ですから、特に問題無いかもしれません -- [[henoheno]] &new{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() を呼ぶように修正
- 同じ件: [[BugTrack/124]]
------------
** touch() の第三引数と マウント時の noatime オプション (r1.18) [#d27713aa]
-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]] &new{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]] &new{2005-04-17 (日) 13:16:32};
-Debian woodyについてはもう少し PHP touch() について確認した方が良さそうです。PHPマニュアルに載っていない(undocumented)挙動なのかもしれませんね。 -- [[henoheno]] &new{2005-04-17 (日) 13:17:25};
-ファイルシステムのマウントオプション noatimeについてはそもそも「atime(アクセス時刻)の更新要求があってもそれを''無視しろ''」というもので、性能向上のために使われることがあるような代物ですから、テストはしていませんがatimeの変更要求をする事とはバッティングしないと思います(単に無視されるようになるだけで)。仮にnoatimeが問題になるとすればそれはPHPの実装の問題になると思います。 -- [[henoheno]] &new{2005-04-17 (日) 13:19:26};
-一方で、今のところPHPマニュアルによればtouch()は第三引数まで存在することになっていて、pkwk_touch()も含めてそれをケアしてあります。それなのにpkwk_chownだけがatimeを無視するというのはお行儀が悪いので、本当にwoodyやPHP 4.1.x に恒久的にこの問題があるのだとしたら、代替案としては以下のようなものになると思います。 -- [[henoheno]] &new{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]] &new{2005-04-17 (日) 13:45:34};
-- [[cvs:lib/file.php]] (1.19): Clean temporary file if failed
-ふむ。テストコードを書きましたが、woody上のPHP 4.1.2 の touch() はFALSEではなくNULLを返しているようですね。 -- [[henoheno]] &new{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]] &new{2005-04-17 (日) 15:00:18};
- Add three-parameter touch() which enables users to set
mtime/atime to different values.
-- http://cvs.php.net/diff.php/php-src/ext/standard/filestat.c?r1=1.86&r2=1.87&ty=h
-最初に実装されたのは filestat.c (revision 1.87) であるようです。このため、touch() の第三引数が利用できるようになったのは PHP 4.2.0 以降であるように見えます。(See http://cvs.php.net/php-src/ext/standard/filestat.c ) -- [[henoheno]] &new{2005-04-17 (日) 15:04:50};
-ということで発見者の [[ishii]] さんには http://jp.php.net/manual/en/function.touch.php にコメントする権利があると思います。どうしますか? :) -- [[henoheno]] &new{2005-04-17 (日) 15:09:05};
-- [[ishii]]さんお忙しくなってしまったかな? もう暫く反応がなければ、コメントしちゃいますね -- [[henoheno]] &new{2005-04-29 (金) 19:12:37};
---ああっ、すいません、コメントしちゃってください。((GWって食べられるのかなぁ…(遠い目 orz)) -- [[ishii]] &new{2005-04-30 (土) 22:27:15};
-- コメントしてみました。採用されたとして、掲載されたり、日本のミラーに来るのは当分先でしょう。 -- [[henoheno]] &new{2005-07-10 (日) 22:41:43};
-- この件、全然反映されていない気がする! -- [[henoheno]] &new{2007-08-31 (金) 23:49:02};
#comment
------------
-古いPHPの恒久的な問題であるようですので、先のコードを追加しました。 -- [[henoheno]] &new{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 [#p0d6038c]
-copy() で実行権がついてしまう件も確認しました。ただ読み取り・書き込み権限が意図しないものとなる事を嫌う管理者や環境もあるでしょうから、666固定でchmod() するよりもう少し綺麗な手がないか検討中です。 -- [[henoheno]] &new{2005-04-17 (日) 15:19:29};
-- copy() する先のファイルをあらかじめtouch()で作成しておけば良いようですので、そうしておきます :) -- [[henoheno]] &new{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)
#comment