I've updated my patch to return null on EOF.

Index: streams/streams.c
===================================================================
--- streams/streams.c   (revision 289073)
+++ streams/streams.c   (working copy)
@@ -890,6 +890,9 @@
                size_t seek_len;

                seek_len = stream->writepos - stream->readpos;
+               if(!seek_len)
+                       return FALSE;
+
                if (seek_len > maxlen) {
                        seek_len = maxlen;
                }
@@ -901,10 +904,7 @@
                }

                if (!e) {
-                       if (seek_len < maxlen && !stream->eof) {
-                               return NULL;
-                       }
-                       toread = maxlen;
+                       toread = (seek_len < maxlen) ? seek_len : maxlen;
                } else {
                        toread = e - (char *) stream->readbuf - stream->readpos;
                        skip = 1;



And the test script for it:

--TEST--
Bug #49148 (combination of stream_get_line and fseek does not work correctly) 
--FILE--
<?php
// should give back "line 1" , false, false
$tmp = tmpfile();
fwrite($tmp, "line1\r\n");
fseek($tmp, 0);

var_dump(stream_get_line($tmp, null, "\r\n"));
var_dump(stream_get_line($tmp, null, "\r\n"));
var_dump(stream_get_line($tmp, null, "\r\n"));
fclose($tmp);

// should give back "line 1" , false, false
$tmp = tmpfile();
fwrite($tmp, "line1\r\n");
fseek($tmp, 0);

var_dump(stream_get_line($tmp, null, "\r\n"));
fseek($tmp, ftell($tmp)); // expected that this does not affect result.
var_dump(stream_get_line($tmp, null, "\r\n"));
var_dump(stream_get_line($tmp, null, "\r\n"));
fclose($tmp);

// should give back "line 1" , "line 2", false
$tmp = tmpfile();
fwrite($tmp, "line1\r\n");
fwrite($tmp, "line2");
fseek($tmp, 0);
var_dump(stream_get_line($tmp, null, "\r\n"));
var_dump(stream_get_line($tmp, null, "\r\n"));
var_dump(stream_get_line($tmp, null, "\r\n"));
fclose($tmp);

// should give back "line 1" , "line 2", false
$tmp = tmpfile();
fwrite($tmp, "line1\r\n");
fwrite($tmp, "line2");
fseek($tmp, 0);
var_dump(stream_get_line($tmp, null, "\r\n"));
fseek($tmp, ftell($tmp)); // expected that this does not affect result.
var_dump(stream_get_line($tmp, null, "\r\n"));
var_dump(stream_get_line($tmp, null, "\r\n"));
fclose($tmp);

// should give back "line 1" , "line 2", false
$tmp = tmpfile();
fwrite($tmp, "line1\r\n");
fwrite($tmp, "line2\r\n");
fseek($tmp, 0);
var_dump(stream_get_line($tmp, null, "\r\n"));
var_dump(stream_get_line($tmp, null, "\r\n"));
var_dump(stream_get_line($tmp, null, "\r\n"));
fclose($tmp);

// should give back "line 1" , "line 2", false
$tmp = tmpfile();
fwrite($tmp, "line1\r\n");
fwrite($tmp, "line2\r\n");
fseek($tmp, 0);
var_dump(stream_get_line($tmp, null, "\r\n"));
fseek($tmp, ftell($tmp)); // expected that this does not affect result.
var_dump(stream_get_line($tmp, null, "\r\n"));
var_dump(stream_get_line($tmp, null, "\r\n"));
fclose($tmp);
?>
--EXPECT--
string(5) "line1"
bool(false)
bool(false)
string(5) "line1"
bool(false)
bool(false)
string(5) "line1"
string(5) "line2"
bool(false)
string(5) "line1"
string(5) "line2"
bool(false)
string(5) "line1"
string(5) "line2"
bool(false)
string(5) "line1"
string(5) "line2"
bool(false)


-----Original Message-----
From: Stanislav Malyshev [mailto:s...@zend.com] 
Sent: Wednesday, September 09, 2009 2:59 PM
To: Garrett Serack
Cc: 'PHP Internals'
Subject: Re: [PHP-DEV] Fix for 49148 (combination of stream_get_line and fseek 
does not work correctly)

Hi!

> Well, that's a really good question.
> 
> Pre-patch, at the end of the stream (when you don't explicitly seek),
> you get empty strings:

I think it's a bug, docs say it's like fgets and fgets returns false on
EOF. Also, "" with this function can mean "delimiter, than another
delimititer" if I understand correctly, because it doesn't return the
delims - which means returning "" on EOF is even worse bug.

> Do you want to change the behavior so that it does return false? It's
> trivial to do (and I'd agree that it would be correct), but it does
> change the behavior from the current behavior.

I think it's a bug and should be changed to return false on EOF, just as 
fgets does. Of course, if there's data before EOF it should return it, 
and then next read should return false. The case where file ends with 
delim should return data before delim on first read, and false on the 
next after delim was read.
-- 
Stanislav Malyshev, Zend Software Architect
s...@zend.com   http://www.zend.com/
(408)253-8829   MSN: s...@zend.com


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to