PHP_FUNCTION(flock)
{
- zval *arg1, *arg3;
- int fd, act, ret;
+ zval *arg1, *arg3 = NULL;
+ int fd, act;
php_stream *stream;
long operation = 0;
/* 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;
}
/* }}} */
#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 */
#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
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
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);
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;
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);
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;
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;
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;
}