php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #10236 ftruncate problem
Submitted: 2001-04-08 21:05 UTC Modified: 2001-09-09 06:13 UTC
From: nissler at fdns-services dot de Assigned:
Status: Not a bug Package: Filesystem function related
PHP Version: 4.0.4 OS: Linux 2.2.5 / glibc 2.0.7
Private report: No CVE-ID: None
 [2001-04-08 21:05 UTC] nissler at fdns-services dot de
I've had a little problem with ftruncate, here is a sample
script that misbehaves for me:

<?
function movedata ($fd, $count)
{
  $p = ftell($fd);
  if ( $count < 0 )
  {
    $p += $count;
  }
  $r = 1024;
  if ($count > 0 && $r < $count)
  {
    $r = $count;
  }
  else if ($count < 0 && $r < -$count)
  {
    $r = -$count;
  }
  $c1 = strlen($buf1 = fread($fd,$r));
  $eof = false;
  while ( !$eof )
  {
    $c2 = strlen($buf2 = fread($fd,$r));
    $eof = feof($fd);
    fseek($fd,-$c2-$c1+$count,SEEK_CUR);
    fwrite($fd,$buf1,$c1);
    fseek($fd,$c2-$count,SEEK_CUR);
    $buf1 = $buf2;
    $c1 = $c2;
  }
  fseek($fd,-$c1+$count,SEEK_CUR);
  fwrite($fd,$buf1,$c1);
  ftruncate($fd,ftell($fd));
  // **** Uncomment the fflush to get it working ****
//  fflush($fd);
  fseek($fd,$p,SEEK_SET);
};

header("Content-type: text/plain");

$fd = fopen('test','w+') or die("Couldn't open file.\n");
$file = <<<EOL
<aaaaaa>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
</aaaaaa>
<bbbbb>
BBBBBBBBBB
</bbbbb>

EOL;
fputs($fd,$file);
fclose($fd);

$fd = fopen('test','r+') or die("Couldn't open file.\n");
$str =
"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n";
fseek($fd,9+strlen($str),SEEK_SET);
movedata($fd,-strlen($str));
movedata($fd,strlen($str));
fseek($fd,9,SEEK_SET);
fputs($fd,$str);
fseek($fd,0,SEEK_SET);
fpassthru($fd);

?>

Here is the output:
<aaaaaa>
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
</aaaaaa>
<bbbbb>
BBBBBBBBBB
</bbbbb>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
</aaaaaa>
<bbbbb>
BBBBBBBBBB
</bbbbb>

I think it should be:

<aaaaaa>
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
</aaaaaa>
<bbbbb>
BBBBBBBBBB
</bbbbb>


What I found is that the second movedata call doesn't work
the way I want it to. As you can see in the output there is
some garbage data that seems to come from the first movedata
call.
I'm not really sure if the thing I found is really a bug,
since the above code might also be buggy. Furthermore this
is really the only case I found to reproduce the problem
(simpler test programs worked fine). The problem might also
be caused by linux/glibc (I know the given versions are
quite old, I'll upgrade soon :-)).
I think there might be a problem with buffered i/o so that
eof doesn't know about the new file size set by ftruncate
since the libc buffered i/o layered isn't flushed and php
source only calls fileno to find out the fd, but the stream
isn't flushed, and the ftruncate libc call isn't in sync
with the buffered i/o layer.
I think php function ftruncate should do a fflush libc call
before doing the ftruncate library call, so that everything
works fine and the php programmer won't have to care about that.

Have fun.

Mattias Nissler (nissler@fdns-services.de)


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2001-09-09 06:13 UTC] sterling@php.net
wow :)

No this is not a bug... and no we shouldn't be doing an
fflush(), you can do a fflush() in the PHP code if you want.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 08:01:28 2024 UTC