+
+// _If needed_, re-create the file to change/correct ownership into PHP's
+// NOTE: Not works for Windows
+function pkwk_chown($filename, $preserve_time = TRUE)
+{
+ static $php_uid; // PHP's UID
+
+ if (! isset($php_uid)) {
+ if (extension_loaded('posix')) {
+ $php_uid = posix_getuid(); // Unix
+ } else {
+ $php_uid = 0; // Windows
+ }
+ }
+
+ // Lock for pkwk_chown()
+ $lockfile = CACHE_DIR . 'pkwk_chown.lock';
+ $flock = fopen($lockfile, 'a') or
+ die('pkwk_chown(): fopen() failed for: CACHEDIR/' .
+ basename(htmlsc($lockfile)));
+ flock($flock, LOCK_EX) or die('pkwk_chown(): flock() failed for lock');
+
+ // Check owner
+ $stat = stat($filename) or
+ die('pkwk_chown(): stat() failed for: ' . basename(htmlsc($filename)));
+ if ($stat[4] === $php_uid) {
+ // NOTE: Windows always here
+ $result = TRUE; // Seems the same UID. Nothing to do
+ } else {
+ $tmp = $filename . '.' . getmypid() . '.tmp';
+
+ // Lock source $filename to avoid file corruption
+ // NOTE: Not 'r+'. Don't check write permission here
+ $ffile = fopen($filename, 'r') or
+ die('pkwk_chown(): fopen() failed for: ' .
+ basename(htmlsc($filename)));
+
+ // Try to chown by re-creating files
+ // NOTE:
+ // * touch() before copy() is for 'rw-r--r--' instead of 'rwxr-xr-x' (with umask 022).
+ // * (PHP 4 < PHP 4.2.0) touch() with the third argument is not implemented and retuns NULL and Warn.
+ // * @unlink() before rename() is for Windows but here's for Unix only
+ flock($ffile, LOCK_EX) or die('pkwk_chown(): flock() failed');
+ $result = touch($tmp) && copy($filename, $tmp) &&
+ ($preserve_time ? (touch($tmp, $stat[9], $stat[8]) || touch($tmp, $stat[9])) : TRUE) &&
+ rename($tmp, $filename);
+ flock($ffile, LOCK_UN) or die('pkwk_chown(): flock() failed');
+
+ fclose($ffile) or die('pkwk_chown(): fclose() failed');
+
+ if ($result === FALSE) @unlink($tmp);
+ }
+
+ // Unlock for pkwk_chown()
+ flock($flock, LOCK_UN) or die('pkwk_chown(): flock() failed for lock');
+ fclose($flock) or die('pkwk_chown(): fclose() failed for lock');
+
+ return $result;
+}
+
+// touch() with trying pkwk_chown()
+function pkwk_touch_file($filename, $time = FALSE, $atime = FALSE)
+{
+ // Is the owner incorrected and unable to correct?
+ if (! file_exists($filename) || pkwk_chown($filename)) {
+ if ($time === FALSE) {
+ $result = touch($filename);
+ } else if ($atime === FALSE) {
+ $result = touch($filename, $time);
+ } else {
+ $result = touch($filename, $time, $atime);
+ }
+ return $result;
+ } else {
+ die('pkwk_touch_file(): Invalid UID and (not writable for the directory or not a flie): ' .
+ htmlsc(basename($filename)));
+ }
+}
+
+/**
+ * Lock-enabled file_get_contents
+ *
+ * Require: PHP5+
+ */
+function pkwk_file_get_contents($filename) {
+ if (! file_exists($filename)) {
+ return false;
+ }
+ $fp = fopen($filename, 'rb');
+ flock($fp, LOCK_SH);
+ $file = file_get_contents($filename);
+ flock($fp, LOCK_UN);
+ return $file;
+}