Skip to content

Commit 2a797f3

Browse files
committed
Better SplObjectFile::flock()
1 parent b972cbf commit 2a797f3

File tree

1 file changed

+36
-6
lines changed

1 file changed

+36
-6
lines changed

ext/spl/spl_directory.c

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "php_ini.h"
2323
#include "ext/standard/info.h"
2424
#include "ext/standard/file.h"
25+
#include "ext/standard/flock_compat.h"
2526
#include "ext/standard/scanf.h"
2627
#include "ext/standard/php_string.h"
2728
#include "zend_compile.h"
@@ -2547,18 +2548,47 @@ PHP_METHOD(SplFileObject, getCsvControl)
25472548
}
25482549
/* }}} */
25492550

2550-
/* {{{ Portable file locking */
2551+
/* {{{ Portable file locking, copy pasted from ext/standard/file.c flock() function.
2552+
* This is done to prevent this to fail if flock is disabled via disable_functions */
2553+
static int flock_values[] = { LOCK_SH, LOCK_EX, LOCK_UN };
2554+
25512555
PHP_METHOD(SplFileObject, flock)
25522556
{
25532557
spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
2554-
zend_function *func_ptr;
2558+
zval *wouldblock = NULL;
2559+
int act;
2560+
zend_long operation = 0;
25552561

2556-
func_ptr = (zend_function *)zend_hash_str_find_ptr(EG(function_table), "flock", sizeof("flock") - 1);
2557-
if (func_ptr == NULL) {
2558-
zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Internal error, function flock() not found. Please report");
2562+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|z", &operation, &wouldblock) == FAILURE) {
25592563
RETURN_THROWS();
25602564
}
2561-
spl_filesystem_file_call(intern, func_ptr, ZEND_NUM_ARGS(), return_value);
2565+
2566+
if(!intern->u.file.stream) {
2567+
zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
2568+
RETURN_THROWS();
2569+
}
2570+
2571+
act = operation & PHP_LOCK_UN;
2572+
// TODO doesn't this fail if operation is a bitmask with LOCK_NB?
2573+
//if (act != PHP_LOCK_SH && act != PHP_LOCK_EX && act != PHP_LOCK_UN) {
2574+
if (act < 1 || act > 3) {
2575+
zend_argument_value_error(1, "must be either LOCK_SH, LOCK_EX, or LOCK_UN");
2576+
RETURN_THROWS();
2577+
}
2578+
2579+
if (wouldblock) {
2580+
ZEND_TRY_ASSIGN_REF_LONG(wouldblock, 0);
2581+
}
2582+
2583+
/* flock_values contains all possible actions if (operation & PHP_LOCK_NB) we won't block on the lock */
2584+
act = flock_values[act - 1] | (operation & PHP_LOCK_NB ? LOCK_NB : 0);
2585+
if (php_stream_lock(intern->u.file.stream, act)) {
2586+
if (operation && errno == EWOULDBLOCK && wouldblock) {
2587+
ZEND_TRY_ASSIGN_REF_LONG(wouldblock, 1);
2588+
}
2589+
RETURN_FALSE;
2590+
}
2591+
RETURN_TRUE;
25622592
}
25632593
/* }}} */
25642594

0 commit comments

Comments
 (0)