From 3312e38f07c45095aee0458acf078e11b89426ff Mon Sep 17 00:00:00 2001 From: 8chan Date: Wed, 25 Feb 2015 17:12:25 -0800 Subject: [PATCH] Change from fopen/flock to dio_open/dio_fcntl in file_write 8chan uses NFS and flock() does not work over NFS. See http://0pointer.de/blog/projects/locking.html for more information. Without proper file locking, race conditions are possible in ?/settings and other pages. The one in ?/settings is particularly bad, too many successive writes can cause a PHP file with bad syntax to be written which breaks an entire board and many scripts that call openBoard(). You need to install the dio.so module if you merge this commit. --- README.md | 1 + inc/functions.php | 14 ++++++-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 82d78944..ecc9e239 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Basic requirements: A computer running a Unix or Unix-like OS(infinity has been specifically tested with and is known to work under Ubuntu 14.x), Apache, MySQL, and PHP * Make sure Apache has read/write access to the directory infinity resides in. * `install.php` is not maintained. Don't use it. +* As of February 22, 2015, you need the [DirectIO module (dio.so)](http://php.net/manual/en/ref.dio.php). Step 1. Create infinity's database from the included install.sql file. Enter mysql and create an empty database named 'infinity'. Then cd into the infinity base directory and run: ``` diff --git a/inc/functions.php b/inc/functions.php index 57d91cbb..44666b83 100755 --- a/inc/functions.php +++ b/inc/functions.php @@ -549,29 +549,27 @@ function file_write($path, $data, $simple = false, $skip_purge = false) { } } - if (!$fp = fopen($path, $simple ? 'w' : 'c')) + if (!$fp = dio_open($path, O_WRONLY | O_CREAT, 0644)) error('Unable to open file for writing: ' . $path); // File locking - if (!$simple && !flock($fp, LOCK_EX)) { + if (dio_fcntl($fp, F_SETLKW, array('type' => F_WRLCK)) === -1) { error('Unable to lock file: ' . $path); } // Truncate file - if (!$simple && !ftruncate($fp, 0)) + if (!dio_truncate($fp, 0)) error('Unable to truncate file: ' . $path); // Write data - if (($bytes = fwrite($fp, $data)) === false) + if (($bytes = dio_write($fp, $data)) === false) error('Unable to write to file: ' . $path); // Unlock - if (!$simple) - flock($fp, LOCK_UN); + dio_fcntl($fp, F_SETLK, array('type' => F_UNLCK)); // Close - if (!fclose($fp)) - error('Unable to close file: ' . $path); + dio_close($fp); /** * Create gzipped file.