--- /dev/null
+--TEST--
+Bug #22362: combinations of fseek() and fwrite() produce unexpected results.
+--FILE--
+<?php # vim600:syn=php:
+$filename = tempnam("/tmp", "phpt");
+
+$fp = fopen($filename, "w+") or die("can't open $filename for append");
+fwrite($fp, "quxbar");
+fseek($fp, 3, SEEK_SET);
+fread($fp, 1);
+fseek($fp, 4, SEEK_SET);
+fwrite($fp, '!');
+fseek($fp, 0, SEEK_SET);
+var_dump(fread($fp, 4095));
+
+ftruncate($fp, 0);
+rewind($fp);
+
+fwrite($fp, "barfoo");
+fseek($fp, 3, SEEK_SET);
+fread($fp, 1);
+fwrite($fp, '!');
+fseek($fp, 0, SEEK_SET);
+var_dump(fread($fp, 4095));
+
+fclose($fp);
+unlink($filename);
+?>
+--EXPECT--
+string(6) "quxb!r"
+string(6) "barf!o"
if (buf == NULL || count == 0 || stream->ops->write == NULL)
return 0;
+ /* if we have a seekable stream we need to ensure that data is written at the
+ * current stream->position. This means invalidating the read buffer and then
+ * performing a low-level seek */
+ if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) {
+ stream->readpos = stream->writepos = 0;
+
+ stream->ops->seek(stream, stream->position, SEEK_SET, &stream->position TSRMLS_CC);
+ }
+
while (count > 0) {
towrite = count;
if (towrite > stream->chunk_size)
* buffered from fifos and sockets */
if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) {
stream->position += justwrote;
- stream->writepos = 0;
- stream->readpos = 0;
}
} else {
break;
PHPAPI int _php_stream_seek(php_stream *stream, off_t offset, int whence TSRMLS_DC)
{
- /* not moving anywhere */
- if ((offset == 0 && whence == SEEK_CUR) || (offset == stream->position && whence == SEEK_SET))
- return 0;
-
/* handle the case where we are in the buffer */
if ((stream->flags & PHP_STREAM_FLAG_NO_BUFFER) == 0) {
switch(whence) {
break;
}
}
-
- /* invalidate the buffer contents */
- stream->readpos = stream->writepos = 0;
if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) {
int ret;
if (((stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) || ret == 0) {
if (ret == 0)
stream->eof = 0;
+
+ /* invalidate the buffer contents */
+ stream->readpos = stream->writepos = 0;
+
return ret;
}
/* else the stream has decided that it can't support seeking after all;
return FAILURE;
#endif
- if (flags & PHP_STREAM_CAST_TRY_HARD) {
+ if (!stream->filterhead && stream->ops->cast && stream->ops->cast(stream, castas, NULL TSRMLS_CC) == SUCCESS) {
+ if (FAILURE == stream->ops->cast(stream, castas, ret TSRMLS_CC)) {
+ return FAILURE;
+ }
+ goto exit_success;
+ } else if (flags & PHP_STREAM_CAST_TRY_HARD) {
php_stream *newstream;
newstream = php_stream_fopen_tmpfile();
return php_stream_fopen_with_path_rel(path, mode, PG(include_path), opened_path, options);
}
- if (php_check_open_basedir(path TSRMLS_CC)) {
+ if ((options & STREAM_DISABLE_OPEN_BASEDIR == 0) && php_check_open_basedir(path TSRMLS_CC)) {
return NULL;
}