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