summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlia Alshanetsky <iliaa@php.net>2003-02-25 01:39:06 +0000
committerIlia Alshanetsky <iliaa@php.net>2003-02-25 01:39:06 +0000
commit862634ffa582e111e9a30e02f6e268e3cfb241ac (patch)
tree99e913d69b46c13cb4973b53b2285d69e47d33f5
parent96563ce34f3cab5195762cc771e374419a67b29f (diff)
downloadphp-git-862634ffa582e111e9a30e02f6e268e3cfb241ac.tar.gz
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().
-rw-r--r--ext/standard/file.c17
-rwxr-xr-xmain/php_streams.h9
-rw-r--r--main/streams/plain_wrapper.c28
3 files changed, 45 insertions, 9 deletions
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 <stddef.h>
#include <fcntl.h>
#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;
}