From: Operating system: PHP version: trunk-SVN-2011-01-31 (SVN) Package: Filesystem function related Bug Type: Bug Bug description:ftruncate() does not work with user-defined stream wrappers
Description: ------------ Hey :-), Seems like ftruncate() does not reconized an user-defined stream (with stream wrapper) as a valid stream. When we use it, it raises the following error: âCan't truncate this stream!â. All the related subject about this error on the Web talks about stream wrappers. Thus, it's seem to be the real problem. Test script: --------------- <?php class StreamWrapper { private $_stream = null; private $_streamName = null; public $context = null; public static function realPath ( $path ) { return substr($path, 6); } public function stream_close ( ) { if(true === @fclose($this->getStream())) { $this->_stream = null; $this->_streamName = null; } return; } public function stream_eof ( ) { return feof($this->getStream()); } public function stream_flush ( ) { return fflush($this->getStream()); } public function stream_lock ( $operation ) { return flock($this->getStream(), $operation); } public function stream_open ( $path, $mode, $options, &$openedPath ) { $p = self::realPath($path); if(false === $p) return false; if(null === $this->context) $openedPath = fopen( $p, $mode, $options & STREAM_USE_PATH ); else $openedPath = fopen( $p, $mode, $options & STREAM_USE_PATH, $this->context ); $this->_stream = $openedPath; $this->_streamName = $p; return true; } public function stream_read ( $count ) { return fread($this->getStream(), $count); } public function stream_seek ( $offset, $whence = SEEK_SET ) { return fseek($this->getStream(), $offset, $whence); } public function stream_stat ( ) { return fstat($this->getStream()); } public function stream_tell ( ) { return ftell($this->getStream()); } public function stream_write ( $data ) { return fwrite($this->getStream(), $data); } public function dir_closedir ( ) { if(true === $handle = @closedir($this->getStream())) { $this->_stream = null; $this->_streamName = null; } return $handle; } public function dir_opendir ( $path, $options ) { $p = self::realPath($path); $handle = null; if(null === $this->context) $handle = @opendir($p); else $handle = @opendir($p, $this->context); if(false === $handle) return false; $this->_stream = $handle; $this->_streamName = $p; return true; } public function dir_readdir ( ) { return readdir($this->getStream()); } public function dir_rewinddir ( ) { return rewinddir($this->getStream()); } public function mkdir ( $path, $mode, $options ) { if(null === $this->context) return mkdir( self::realPath($path), $mode, $options | STREAM_MKDIR_RECURSIVE ); return mkdir( self::realPath($path), $mode, $options | STREAM_MKDIR_RECURSIVE, $this->context ); } public function rename ( $from, $to ) { if(null === $this->context) return rename(self::realPath($from), self::realPath($to)); return rename(self::realPath($from), self::realPath($to), $this->context); } public function rmdir ( $path, $options ) { if(null === $this->context) return rmdir(self::realPath($path)); return rmdir(self::realPath($path), $this->context); } public function unlink ( $path ) { if(null === $this->context) return unlink(self::realPath($path)); return unlink(self::realPath($path), $this->context); } public function url_stat ( $path, $flags ) { if(false === $p = self::realPath($path)) if($flags & STREAM_URL_STAT_QUIET) return array(); // Not sure⦠else return trigger_error( 'Path ' . $path . ' cannot be resolved.', E_WARNING ); if($flags & STREAM_URL_STAT_LINK) return @lstat($p); return @stat($p); } protected function getStream ( ) { return $this->_stream; } protected function getStreamName ( ) { return $this->_streamName; } } stream_wrapper_register('bug', 'StreamWrapper'); var_dump($fd = fopen('bug://Test.txt', 'w+')); var_dump(fwrite($fd, 'Foobar1' . "\n")); var_dump(fwrite($fd, 'Foobar2' . "\n")); var_dump(fwrite($fd, 'Foobar3' . "\n")); var_dump(ftruncate($fd, 3)); var_dump(fclose($fd)); Expected result: ---------------- Output: resource(7) of type (stream) int(8) int(8) int(8) bool(true) bool(true) Test.txt: Foo Actual result: -------------- Output: resource(7) of type (stream) int(8) int(8) int(8) PHP Warning: ftruncate(): Can't truncate this stream! in /Users/hywan/Development/Hoa/Laboratory/Bug/StreamWrapper.php on line 210 Warning: ftruncate(): Can't truncate this stream! in /Users/hywan/Development/Hoa/Laboratory/Bug/StreamWrapper.php on line 210 bool(false) bool(true) Test.txt: Foobar1 Foobar2 Foobar3 -- Edit bug report at http://bugs.php.net/bug.php?id=53888&edit=1 -- Try a snapshot (PHP 5.2): http://bugs.php.net/fix.php?id=53888&r=trysnapshot52 Try a snapshot (PHP 5.3): http://bugs.php.net/fix.php?id=53888&r=trysnapshot53 Try a snapshot (trunk): http://bugs.php.net/fix.php?id=53888&r=trysnapshottrunk Fixed in SVN: http://bugs.php.net/fix.php?id=53888&r=fixed Fixed in SVN and need be documented: http://bugs.php.net/fix.php?id=53888&r=needdocs Fixed in release: http://bugs.php.net/fix.php?id=53888&r=alreadyfixed Need backtrace: http://bugs.php.net/fix.php?id=53888&r=needtrace Need Reproduce Script: http://bugs.php.net/fix.php?id=53888&r=needscript Try newer version: http://bugs.php.net/fix.php?id=53888&r=oldversion Not developer issue: http://bugs.php.net/fix.php?id=53888&r=support Expected behavior: http://bugs.php.net/fix.php?id=53888&r=notwrong Not enough info: http://bugs.php.net/fix.php?id=53888&r=notenoughinfo Submitted twice: http://bugs.php.net/fix.php?id=53888&r=submittedtwice register_globals: http://bugs.php.net/fix.php?id=53888&r=globals PHP 4 support discontinued: http://bugs.php.net/fix.php?id=53888&r=php4 Daylight Savings: http://bugs.php.net/fix.php?id=53888&r=dst IIS Stability: http://bugs.php.net/fix.php?id=53888&r=isapi Install GNU Sed: http://bugs.php.net/fix.php?id=53888&r=gnused Floating point limitations: http://bugs.php.net/fix.php?id=53888&r=float No Zend Extensions: http://bugs.php.net/fix.php?id=53888&r=nozend MySQL Configuration Error: http://bugs.php.net/fix.php?id=53888&r=mysqlcfg