Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:55000 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 95111 invoked from network); 28 Aug 2011 21:54:23 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 28 Aug 2011 21:54:23 -0000 Authentication-Results: pb1.pair.com header.from=christian.kaps@mohiva.com; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=christian.kaps@mohiva.com; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain mohiva.com from 178.63.228.54 cause and error) X-PHP-List-Original-Sender: christian.kaps@mohiva.com X-Host-Fingerprint: 178.63.228.54 elvis.mohiva.com Linux 2.6 Received: from [178.63.228.54] ([178.63.228.54:39869] helo=elvis.mohiva.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id BA/60-21947-D09BA5E4 for ; Sun, 28 Aug 2011 17:54:22 -0400 Received: from localhost (localhost.localdomain [127.0.0.1]) by elvis.mohiva.com (Postfix) with ESMTP id C6FE31D24859 for ; Sun, 28 Aug 2011 23:54:17 +0200 (CEST) X-Virus-Scanned: amavisd-new at mohiva.com Received: from elvis.mohiva.com ([127.0.0.1]) by localhost (elvis.mohiva.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id AKRpB5vl1vq2 for ; Sun, 28 Aug 2011 23:54:13 +0200 (CEST) Received: from [192.168.0.3] (p57B5244C.dip.t-dialin.net [87.181.36.76]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) (Authenticated sender: christian.kaps@mohiva.com) by elvis.mohiva.com (Postfix) with ESMTPSA id 6F0DF1D24858 for ; Sun, 28 Aug 2011 23:54:12 +0200 (CEST) Message-ID: <4E5AB903.9090602@mohiva.com> Date: Sun, 28 Aug 2011 23:54:11 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:6.0) Gecko/20110824 Thunderbird/6.0 MIME-Version: 1.0 To: PHPMailingList References: <4E5A42B8.20600@mohiva.com> In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] Problems with the stream API From: christian.kaps@mohiva.com (Christian Kaps) Hi Gustavo, thanks for your detailed explanation. Nevertheless it might be useful to document these inconsistent(from the userland point of view) behavior. Please see my comments inline. Am 28.08.2011 17:22, schrieb Gustavo Lopes: > On Sun, 28 Aug 2011 14:29:28 +0100, Christian Kaps > wrote: > >> I have some problems with the stream API. The methods stream_tell and >> stream_seek works not as expected in some cases. >> >> Before reading the next lines, please look at the short >> gist(https://gist.github.com/1176641). >> >> First example: >> >> $fp = fopen('mfx://test1', 'w'); >> fwrite($fp, '12345678'); >> fseek($fp, -1, SEEK_CUR); >> fclose($fp); >> // stream_seek: $offset = 7 >> >> If you call fseek with the arguments (-1, SEEK_CUR) then the $offset >> parameter in the method stream_seek is 7. It seems that the internal API >> takes the written bytes returned by fwrite and then it subtracts the >> argument (-1) from it before passing it to stream_seek. For the >> constants SEEK_SET and SEEK_END, the passed value is the same as defined >> for the fseek call. > > SEEK_CUR seeks are internally converted to SEEK_SET seeks. It's been > this way since at least 2002: > > http://svn.php.net/viewvc/php/php-src/trunk/main/streams.c?annotate=96547&pathrev=96547#l582 > > > The first thing you should know is that PHP keeps track internally of > the position of the stream. That's why PHP knows how to convert SEEK_CUR > -1 to SEEK_SET 7. > > The seek type conversion is an arguable decision, but changing this has > some risks. Consider that some some streams might not respond to > SEEK_CUR seeks or that they do so defectively. The only advantages I see > is that it could mitigate the problems of an inaccurate internal > position (though this happens mostly with internal code that casts the > stream into e.g. a FILE* and then manipulates the pointer); it would > also save stream implementations that only support SEEK_CUR from having > to reconvert the SEEK_SET to SEEK_CUR. > This behavior should be documented. The possible values for the "whence" parameter of the "stream_seek" method should only be SEEK_SET and SEEK_END. And there should be a hint that the SEEK_CUR seeks are internally converted to SEEK_SET seeks. >> The second example: >> >> $fp = fopen('mfx://test2', 'w'); >> fwrite($fp, '12345678'); >> fread($fp, 2); >> fseek($fp, 1, SEEK_CUR); >> fclose($fp); >> >> For this example the stream_seek method gets never be called. The >> difference here is that fread is called before fseek. > > No bug here. This is by design. PHP doesn't read only two bytes from the > stream, it reads an entire chunk. Once PHP has data buffered and you > tell it to skip one byte, it can just advance its internal pointer on > the buffered data; no need to actually call fseek. > > It should be documented that, in some circumstances, the "stream_seek" method isn't called in response to fseek. >> The third example: >> >> $fp = fopen('mfx://test3', 'w'); >> fwrite($fp, '12345678'); >> fread($fp, 3); >> ftell($fp); >> fclose($fp); >> >> For this example the stream_tell method gets never be called. It is >> documented(http://www.php.net/manual/en/streamwrapper.stream-tell.php) >> that the stream_tell method is called in response to ftell(). But it >> seems that this method is only be called internally by the stream API. >> >> There exists a Bug report at https://bugs.php.net/bug.php?id=30157 >> >> In one of the comments Pierre says: There is no bug but a feature >> request which seems to be very discutable. >> > > Again, as the comment on the bug report says, this is by design. PHP > keeps track internally of the position, so it can just return the > information it has. > > But yes, the documentation is wrong in this respect. stream_tell is only > called after a seek in order to determine where the seek ended up. In > the C standard library, you're allowed to seek past the end of the file > and then write, zeroing everything in between the end of the position > sought to (or failing to write). In PHP, this convention doesn't apply; > you're not always allowed to seek to any position. > The documentation for "stream_tell" is wrong. This method gets only be called internally. What do you think about my suggestions? Christian