diff --git a/ext/zlib/tests/005.txt.gz b/ext/zlib/tests/005.txt.gz new file mode 100644 index 0000000000000..07805db755807 Binary files /dev/null and b/ext/zlib/tests/005.txt.gz differ diff --git a/ext/zlib/tests/zlib_lock_mandatory_windows.phpt b/ext/zlib/tests/zlib_lock_mandatory_windows.phpt new file mode 100644 index 0000000000000..04ed2ab251056 --- /dev/null +++ b/ext/zlib/tests/zlib_lock_mandatory_windows.phpt @@ -0,0 +1,52 @@ +--TEST-- +Test mandatory locking on Windows +--EXTENSIONS-- +zlib +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +without wrapper +bool(true) + +Notice: fread(): Read of 1 bytes failed with errno=13 Permission denied in %s on line %d +bool(false) +string(1) "W" + +with wrapper +bool(true) + +Notice: fread(): Read of 1 bytes failed with errno=13 Permission denied in %s on line %d +bool(false) +string(1) "W" diff --git a/ext/zlib/tests/zlib_wrapper_flock_basic.phpt b/ext/zlib/tests/zlib_wrapper_flock_basic.phpt index 95329dd003eb8..89656c7fca6bc 100644 --- a/ext/zlib/tests/zlib_wrapper_flock_basic.phpt +++ b/ext/zlib/tests/zlib_wrapper_flock_basic.phpt @@ -1,13 +1,13 @@ --TEST-- -Test function stream_get_meta_data on a zlib stream +Test function flock on a zlib stream --EXTENSIONS-- zlib --FILE-- --EXPECT-- -bool(false) +bool(true) diff --git a/ext/zlib/zlib_fopen_wrapper.c b/ext/zlib/zlib_fopen_wrapper.c index b414b33a8724e..4f07926e5e206 100644 --- a/ext/zlib/zlib_fopen_wrapper.c +++ b/ext/zlib/zlib_fopen_wrapper.c @@ -30,6 +30,18 @@ struct php_gz_stream_data_t { php_stream *stream; }; +static void php_gziop_report_errors(php_stream *stream, size_t count, const char *verb) +{ + if (!(stream->flags & PHP_STREAM_FLAG_SUPPRESS_ERRORS)) { + struct php_gz_stream_data_t *self = stream->abstract; + int error = 0; + gzerror(self->gz_file, &error); + if (error == Z_ERRNO) { + php_error_docref(NULL, E_NOTICE, "%s of %zu bytes failed with errno=%d %s", verb, count, errno, strerror(errno)); + } + } +} + static ssize_t php_gziop_read(php_stream *stream, char *buf, size_t count) { struct php_gz_stream_data_t *self = (struct php_gz_stream_data_t *) stream->abstract; @@ -38,6 +50,11 @@ static ssize_t php_gziop_read(php_stream *stream, char *buf, size_t count) /* XXX this needs to be looped for the case count > UINT_MAX */ read = gzread(self->gz_file, buf, count); + /* Notify user of error, like the standard file wrapper normally does (e.g. errno=13 on mandatory lock failure). */ + if (UNEXPECTED(read < 0)) { + php_gziop_report_errors(stream, count, "Read"); + } + if (gzeof(self->gz_file)) { stream->eof = 1; } @@ -50,7 +67,14 @@ static ssize_t php_gziop_write(php_stream *stream, const char *buf, size_t count struct php_gz_stream_data_t *self = (struct php_gz_stream_data_t *) stream->abstract; /* XXX this needs to be looped for the case count > UINT_MAX */ - return gzwrite(self->gz_file, (char *) buf, count); + int written = gzwrite(self->gz_file, (char *) buf, count); + + /* Notify user of error, like the standard file wrapper normally does (e.g. errno=13 on mandatory lock failure). */ + if (UNEXPECTED(written < 0)) { + php_gziop_report_errors(stream, count, "Write"); + } + + return written; } static int php_gziop_seek(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffs) @@ -95,6 +119,21 @@ static int php_gziop_flush(php_stream *stream) return gzflush(self->gz_file, Z_SYNC_FLUSH); } +static int php_gziop_set_option(php_stream *stream, int option, int value, void *ptrparam) +{ + struct php_gz_stream_data_t *self = stream->abstract; + + switch (option) { + case PHP_STREAM_OPTION_LOCKING: + case PHP_STREAM_OPTION_META_DATA_API: + return self->stream->ops->set_option(self->stream, option, value, ptrparam); + default: + break; + } + + return PHP_STREAM_OPTION_RETURN_NOTIMPL; +} + const php_stream_ops php_stream_gzio_ops = { php_gziop_write, php_gziop_read, php_gziop_close, php_gziop_flush, @@ -102,7 +141,7 @@ const php_stream_ops php_stream_gzio_ops = { php_gziop_seek, NULL, /* cast */ NULL, /* stat */ - NULL /* set_option */ + php_gziop_set_option /* set_option */ }; php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, const char *path, const char *mode, int options,