From: Ilia Alshanetsky Date: Tue, 25 Feb 2003 01:39:06 +0000 (+0000) Subject: Added locking to streams. X-Git-Tag: RELEASE_0_5~769 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=862634ffa582e111e9a30e02f6e268e3cfb241ac;p=php Added locking to streams. Allow PHP to automatically release locks on files when terminating the stream. Fixed bugs in the handling of the 3rd optional parameter to flock(). --- diff --git a/ext/standard/file.c b/ext/standard/file.c index 24739957b9..5fafdce431 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -218,8 +218,8 @@ static int flock_values[] = { LOCK_SH, LOCK_EX, LOCK_UN }; PHP_FUNCTION(flock) { - zval *arg1, *arg3; - int fd, act, ret; + zval *arg1, *arg3 = NULL; + int fd, act; php_stream *stream; long operation = 0; @@ -241,15 +241,14 @@ PHP_FUNCTION(flock) /* flock_values contains all possible actions if (operation & 4) we won't block on the lock */ act = flock_values[act - 1] | (operation & 4 ? LOCK_NB : 0); - if ((ret = flock(fd, act)) == -1) { - if (errno == EWOULDBLOCK && operation) { - convert_to_long(arg3); - Z_LVAL_P(arg3) = 1; - RETURN_TRUE; + if (!php_stream_lock(stream, act)) { + if (operation && errno == EWOULDBLOCK && arg3 && PZVAL_IS_REF(arg3)) { + convert_to_long_ex(&arg3); + ZVAL_LONG(arg3, 1); } - RETURN_FALSE; + RETURN_TRUE; } - RETURN_TRUE; + RETURN_FALSE; } /* }}} */ diff --git a/main/php_streams.h b/main/php_streams.h index 194172c1c3..2bc6468cfc 100755 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -326,6 +326,15 @@ PHPAPI int _php_stream_set_option(php_stream *stream, int option, int value, voi #define PHP_STREAM_OPTION_READ_TIMEOUT 4 #define PHP_STREAM_OPTION_SET_CHUNK_SIZE 5 +/* set or release lock on a stream */ +#define PHP_STREAM_OPTION_LOCKING 6 + +/* whether or not locking is supported */ +#define PHP_STREAM_LOCK_SUPPORTED 1 + +#define php_stream_supports_lock(stream) php_stream_set_option((stream), PHP_STREAM_OPTION_LOCKING, 0, (void *) PHP_STREAM_LOCK_SUPPORTED TSRMLS_CC) == 0 ? 1 : 0 +#define php_stream_lock(stream, mode) php_stream_set_option((stream), PHP_STREAM_OPTION_LOCKING, (mode), (void *) NULL TSRMLS_CC) + #define PHP_STREAM_OPTION_RETURN_OK 0 /* option set OK */ #define PHP_STREAM_OPTION_RETURN_ERR -1 /* problem setting option */ #define PHP_STREAM_OPTION_RETURN_NOTIMPL -2 /* underlying stream does not implement; streams can handle it instead */ diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index cf85586d78..18dd1ef77b 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -23,6 +23,7 @@ #include "php_network.h" #include "php_open_temporary_file.h" #include "ext/standard/file.h" +#include "ext/standard/flock_compat.h" #include #include #if HAVE_SYS_WAIT_H @@ -131,6 +132,7 @@ typedef struct { int fd; /* underlying file descriptor */ int is_process_pipe; /* use pclose instead of fclose */ int is_pipe; /* don't try and seek */ + int lock_flag; /* stores the lock state */ char *temp_file_name; /* if non-null, this is the path to a temporary file that * is to be deleted when the stream is closed */ #if HAVE_FLUSHIO @@ -167,6 +169,8 @@ PHPAPI php_stream *_php_stream_fopen_tmpfile(int dummy STREAMS_DC TSRMLS_DC) php_stdio_stream_data *self = (php_stdio_stream_data*)stream->abstract; self->temp_file_name = opened_path; + self->lock_flag = LOCK_UN; + return stream; } fclose(fp); @@ -186,6 +190,7 @@ PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode STREAMS_DC self = emalloc_rel_orig(sizeof(*self)); self->file = NULL; self->is_pipe = 0; + self->lock_flag = LOCK_UN; self->is_process_pipe = 0; self->temp_file_name = NULL; self->fd = fd; @@ -228,6 +233,7 @@ PHPAPI php_stream *_php_stream_fopen_from_file(FILE *file, const char *mode STRE self = emalloc_rel_orig(sizeof(*self)); self->file = file; self->is_pipe = 0; + self->lock_flag = LOCK_UN; self->is_process_pipe = 0; self->temp_file_name = NULL; self->fd = fileno(file); @@ -270,6 +276,7 @@ PHPAPI php_stream *_php_stream_fopen_from_pipe(FILE *file, const char *mode STRE self = emalloc_rel_orig(sizeof(*self)); self->file = file; self->is_pipe = 1; + self->lock_flag = LOCK_UN; self->is_process_pipe = 1; self->fd = fileno(file); self->temp_file_name = NULL; @@ -340,6 +347,9 @@ static int php_stdiop_close(php_stream *stream, int close_handle TSRMLS_DC) assert(data != NULL); if (close_handle) { + if (data->lock_flag != LOCK_UN) { + php_stream_lock(stream, LOCK_UN); + } if (data->file) { if (data->is_process_pipe) { errno = 0; @@ -541,6 +551,24 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void return -1; } break; + + case PHP_STREAM_OPTION_LOCKING: + if (fd == -1) { + return -1; + } + + if ((int) ptrparam == PHP_STREAM_LOCK_SUPPORTED) { + return 0; + } + + if (!php_flock(fd, value) || (errno == EWOULDBLOCK && value & LOCK_NB)) { + data->lock_flag = value; + return 0; + } else { + return -1; + } + break; + default: return -1; }