|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2001-09-09 06:13 UTC] sterling@php.net
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Oct 26 10:00:01 2025 UTC |
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)