Edit report at https://bugs.php.net/bug.php?id=65581&edit=1
ID: 65581 Updated by: ras...@php.net Reported by: ivan dot enderlin at hoa-project dot net Summary: stream_get_contents does not seek with a stream wrapper -Status: Closed +Status: Not a bug Type: Bug Package: *General Issues PHP Version: master-Git-2013-08-29 (Git) Assigned To: jpauli Block user comment: N Private report: N Previous Comments: ------------------------------------------------------------------------ [2013-08-29 13:36:06] ivan dot enderlin at hoa-project dot net Oh yes, I forgot that tell() returns 0 on success⦠That's solved my issue. Thanks! ------------------------------------------------------------------------ [2013-08-29 13:31:55] jpa...@php.net Thank you for taking the time to write to us, but this is not a bug. Please double-check the documentation available at http://www.php.net/manual/ and the instructions on how to report a bug at http://bugs.php.net/how-to-report.php This is because your stream_seek() function does not return the right value. stream_seek() should return TRUE if the seek has successed, you return the value of fseek(), which is 0 on success. Additionally, you have to implement stream_tell() so that the underlying layer can ask for it and know where the stream position is. stream_tell() is called just after stream_seek() has successed, thus it is needed, even if you never call ftell() on your own stream, the underlying layer does. Correct code is : <?php class StreamWrapper { protected $_stream = null; public function stream_open ( $path, $mode, $options, &$openedPath ) { $this->_stream = fopen(__FILE__, $mode); return true; } public function stream_seek ( $offset, $whence = SEEK_SET ) { var_dump('seek to ' . $offset); if (fseek($this->_stream, $offset, $whence) == 0) { return true; } return false; } public function stream_tell() { return ftell($this->_stream); } public function stream_read ( $count ) { return fread($this->_stream, $count); } public function stream_stat ( ) { return fstat($this->_stream); } public function stream_eof ( ) { return feof($this->_stream); } } stream_wrapper_register('foo', 'StreamWrapper'); $a = fopen('foo://bar', 'rb'); var_dump(stream_get_contents($a, 30, 4)); ------------------------------------------------------------------------ [2013-08-29 08:40:49] ivan dot enderlin at hoa-project dot net Oh also the bug disappears with: fseek($a, 4); stream_get_contents($a, 30); ------------------------------------------------------------------------ [2013-08-29 08:28:08] ivan dot enderlin at hoa-project dot net Description: ------------ When calling stream_get_contents() with $offset >= ftell() *through a stream wrapper*, the internal pointer of the stream is moved but stream_get_contents() throws an error: "Failed to seek to position $offset in the stream". While monitoring the source code (ext/standard/streamsfuncs.c, at line 404, no kidding ;-)), it appears that it is a normal behaviour since seek_res is set to -1 at line 426 (with the code bellow). I did not understand why (I looked at php_stream_seek implementation but I was not able to understand). Change fopen('foo://bar', 'rb') for fopen(__FILE__, 'rb') and the issue disappears. That's why I think it is related to stream wrapper, but I cannot ensure that. Test script: --------------- <?php class StreamWrapper { protected $_stream = null; public function stream_open ( $path, $mode, $options, &$openedPath ) { $this->_stream = fopen(__FILE__, $mode); return true; } public function stream_seek ( $offset, $whence = SEEK_SET ) { var_dump('seek to ' . $offset); return fseek($this->_stream, $offset, $whence); } public function stream_read ( $count ) { return fread($this->_stream, $count); } public function stream_stat ( ) { return fstat($this->_stream); } public function stream_eof ( ) { return feof($this->_stream); } } stream_wrapper_register('foo', 'StreamWrapper'); $a = fopen('foo://bar', 'rb'); var_dump(stream_get_contents($a, 30, 4)); Expected result: ---------------- no error Actual result: -------------- error ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=65581&edit=1