wez Sat Oct 5 06:35:14 2002 EDT
Modified files:
/php4/ext/standard php_fopen_wrapper.c
/php4/ext/standard/tests/file userstreams.phpt
/php4/ext/zlib zlib_fopen_wrapper.c
/php4/main memory_streams.c network.c php_streams.h streams.c
user_streams.c
Log:
This seems to resolve the issues with fgets.
I've moved EOF detection into the streams layer; a stream reader
implementation should set stream->eof when it detects EOF.
Fixed test for user streams - it still fails but that is due to an output
buffering bug.
Index: php4/ext/standard/php_fopen_wrapper.c
diff -u php4/ext/standard/php_fopen_wrapper.c:1.25
php4/ext/standard/php_fopen_wrapper.c:1.26
--- php4/ext/standard/php_fopen_wrapper.c:1.25 Thu Sep 26 06:14:41 2002
+++ php4/ext/standard/php_fopen_wrapper.c Sat Oct 5 06:35:12 2002
@@ -17,7 +17,7 @@
| Hartmut Holzgraefe <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
*/
-/* $Id: php_fopen_wrapper.c,v 1.25 2002/09/26 10:14:41 wez Exp $ */
+/* $Id: php_fopen_wrapper.c,v 1.26 2002/10/05 10:35:12 wez Exp $ */
#include <stdio.h>
#include <stdlib.h>
@@ -39,6 +39,7 @@
static size_t php_stream_output_read(php_stream *stream, char *buf, size_t count
TSRMLS_DC)
{
+ stream->eof = 1;
return 0;
}
Index: php4/ext/standard/tests/file/userstreams.phpt
diff -u php4/ext/standard/tests/file/userstreams.phpt:1.3
php4/ext/standard/tests/file/userstreams.phpt:1.4
--- php4/ext/standard/tests/file/userstreams.phpt:1.3 Sat Sep 28 18:14:21 2002
+++ php4/ext/standard/tests/file/userstreams.phpt Sat Oct 5 06:35:13 2002
@@ -243,11 +243,12 @@
printf("\n--[%d] whence=%s offset=%d line_length=%d
position_should_be=%d --\n",
$j, $whence_names[$whence], $offset, $line_length, $position);
- printf("REAL: pos=(%d,%d,%d) ret=%d line=`%s'\n", $rpb, $rpa,
ftell($tf), $rr, $rline);
- printf("USER: pos=(%d,%d,%d) ret=%d line=`%s'\n", $upb, $upa,
ftell($fp), $ur, $uline);
+ printf("REAL: pos=(%d,%d,%d) ret=%d line[%d]=`%s'\n", $rpb, $rpa,
+ftell($tf), $rr, strlen($rline), $rline);
+ printf("USER: pos=(%d,%d,%d) ret=%d line[%d]=`%s'\n", $upb, $upa,
+ftell($fp), $ur, strlen($uline), $uline);
if ($rr != $ur || $rline != $uline || $rpa != $position || $upa !=
$position) {
$fail_count++;
+ echo "###################################### FAIL!\n";
$dat = stream_get_meta_data($fp);
var_dump($dat);
break;
@@ -273,7 +274,7 @@
while(!feof($fp)) {
$uline = fgets($fp, 1024);
- $rline = fgets($fp, 1024);
+ $rline = fgets($tf, 1024);
if ($uline != $rline) {
echo "FGETS: FAIL\nuser=$uline\nreal=$rline\n";
Index: php4/ext/zlib/zlib_fopen_wrapper.c
diff -u php4/ext/zlib/zlib_fopen_wrapper.c:1.30 php4/ext/zlib/zlib_fopen_wrapper.c:1.31
--- php4/ext/zlib/zlib_fopen_wrapper.c:1.30 Thu Sep 26 06:14:41 2002
+++ php4/ext/zlib/zlib_fopen_wrapper.c Sat Oct 5 06:35:13 2002
@@ -16,7 +16,7 @@
| Hartmut Holzgraefe <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
*/
-/* $Id: zlib_fopen_wrapper.c,v 1.30 2002/09/26 10:14:41 wez Exp $ */
+/* $Id: zlib_fopen_wrapper.c,v 1.31 2002/10/05 10:35:13 wez Exp $ */
#define IS_EXT_MODULE
#define _GNU_SOURCE
@@ -32,14 +32,14 @@
static size_t php_gziop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
{
struct php_gz_stream_data_t *self = (struct php_gz_stream_data_t
*)stream->abstract;
+ size_t ret;
+
+ ret = gzread(self->gz_file, buf, count);
- if (buf == NULL && count == 0) {
- if (gzeof(self->gz_file))
- return EOF;
- return 0;
- }
+ if (ret == 0 && gzeof(self->gz_file))
+ stream->eof = 1;
- return gzread(self->gz_file, buf, count);
+ return ret;
}
static size_t php_gziop_write(php_stream *stream, const char *buf, size_t count
TSRMLS_DC)
Index: php4/main/memory_streams.c
diff -u php4/main/memory_streams.c:1.18 php4/main/memory_streams.c:1.19
--- php4/main/memory_streams.c:1.18 Mon Sep 23 09:22:10 2002
+++ php4/main/memory_streams.c Sat Oct 5 06:35:13 2002
@@ -89,14 +89,6 @@
ms = stream->abstract;
assert(ms != NULL);
- if (buf == NULL && count == 0) {
- /* check for EOF condition */
- if (ms->fpos >= ms->fsize) {
- return EOF;
- }
- return 0;
- }
-
if (ms->fpos + count > ms->fsize) {
count = ms->fsize - ms->fpos;
}
@@ -105,6 +97,8 @@
assert(buf!= NULL);
memcpy(buf, ms->data+ms->fpos, count);
ms->fpos += count;
+ } else {
+ stream->eof = 1;
}
return count;
}
Index: php4/main/network.c
diff -u php4/main/network.c:1.73 php4/main/network.c:1.74
--- php4/main/network.c:1.73 Fri Oct 4 15:08:43 2002
+++ php4/main/network.c Sat Oct 5 06:35:13 2002
@@ -16,7 +16,7 @@
| Streams work by Wez Furlong <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
*/
-/* $Id: network.c,v 1.73 2002/10/04 19:08:43 sas Exp $ */
+/* $Id: network.c,v 1.74 2002/10/05 10:35:13 wez Exp $ */
/*#define DEBUG_MAIN_NETWORK 1*/
@@ -767,32 +767,6 @@
php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;
size_t nr_bytes = 0;
- if (buf == NULL && count == 0) {
- /* check for EOF condition */
-
-DUMP_SOCK_STATE("check for EOF", sock);
-
- if (sock->eof)
- return EOF;
-
- /* no data in the buffer - lets examine the socket */
-#if HAVE_SYS_POLL_H && HAVE_POLL
- {
- struct pollfd topoll;
-
- topoll.fd = sock->socket;
- topoll.events = POLLIN;
- topoll.revents = 0;
-
- if (poll(&topoll, 1, 0) == 1) {
- return topoll.revents & POLLHUP ? EOF : 0;
- }
- }
-#endif
- /* presume that we are not yet at the eof */
- return 0;
- }
-
if(sock->is_blocked) {
php_sock_stream_wait_for_data(stream, sock TSRMLS_CC);
if (sock->timeout_event)
@@ -811,7 +785,7 @@
php_stream_notify_progress_increment(stream->context, nr_bytes, 0);
if(nr_bytes == 0 || (nr_bytes < 0 && streams_socket_errno != EWOULDBLOCK)) {
- sock->eof = 1;
+ stream->eof = 1;
}
return nr_bytes;
Index: php4/main/php_streams.h
diff -u php4/main/php_streams.h:1.53 php4/main/php_streams.h:1.54
--- php4/main/php_streams.h:1.53 Fri Oct 4 14:59:34 2002
+++ php4/main/php_streams.h Sat Oct 5 06:35:13 2002
@@ -269,6 +269,8 @@
/* how much data to read when filling buffer */
size_t chunk_size;
+ int eof;
+
}; /* php_stream */
/* state definitions when closing down; these are private to streams.c */
#define PHP_STREAM_FCLOSE_NONE 0
Index: php4/main/streams.c
diff -u php4/main/streams.c:1.95 php4/main/streams.c:1.96
--- php4/main/streams.c:1.95 Fri Oct 4 15:48:59 2002
+++ php4/main/streams.c Sat Oct 5 06:35:13 2002
@@ -20,7 +20,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: streams.c,v 1.95 2002/10/04 19:48:59 sas Exp $ */
+/* $Id: streams.c,v 1.96 2002/10/05 10:35:13 wez Exp $ */
#define _GNU_SOURCE
#include "php.h"
@@ -462,8 +462,8 @@
/* allocate/fill the buffer */
/* is there enough data in the buffer ? */
- while (stream->writepos - stream->readpos < (off_t)size) {
- size_t justread;
+ if (stream->writepos - stream->readpos < (off_t)size) {
+ size_t justread = 0;
/* no; so lets fetch more data */
@@ -491,21 +491,21 @@
stream->readbuflen - stream->writepos
TSRMLS_CC);
}
-
- if (justread <= 0)
- break;
-
- stream->writepos += justread;
-
- if (stream->flags & PHP_STREAM_FLAG_AVOID_BLOCKING)
- break;
+
+ if (justread > 0) {
+ stream->writepos += justread;
+ }
}
+
}
PHPAPI size_t _php_stream_read(php_stream *stream, char *buf, size_t size TSRMLS_DC)
{
size_t toread, didread = 0;
+ if (size == 0)
+ return 0;
+
/* take from the read buffer first.
* It is possible that a buffered stream was switched to non-buffered, so we
* drain the remainder of the buffer before using the "raw" read mode for
@@ -525,6 +525,10 @@
if (size == 0) {
stream->position += didread;
+
+ if (didread == 0)
+ stream->eof = 1;
+
return didread;
}
@@ -549,6 +553,10 @@
}
}
stream->position += size;
+
+ if (didread == 0)
+ stream->eof = 1;
+
return didread;
}
@@ -558,6 +566,8 @@
if (stream->writepos - stream->readpos > 0)
return 0;
+ return stream->eof;
+
/* we define our stream reading function so that it
must return EOF when an EOF condition occurs, when
working in unbuffered mode and called with these args */
@@ -657,7 +667,7 @@
{
size_t avail = 0;
int did_copy = 0;
-
+
if (maxlen == 0)
return NULL;
@@ -779,6 +789,7 @@
if (offset > 0 && offset < stream->writepos - stream->readpos)
{
stream->readpos += offset;
stream->position += offset;
+ stream->eof = 0;
return 0;
}
break;
@@ -787,6 +798,7 @@
offset < stream->position + stream->writepos -
stream->readpos) {
stream->readpos += offset - stream->position;
stream->position = offset;
+ stream->eof = 0;
return 0;
}
break;
@@ -809,8 +821,11 @@
}
ret = stream->ops->seek(stream, offset, whence, &stream->position
TSRMLS_CC);
- if (((stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) || ret == 0)
+ if (((stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) || ret == 0) {
+ if (ret == 0)
+ stream->eof = 0;
return ret;
+ }
/* else the stream has decided that it can't support seeking after all;
* fall through to attempt emulation */
}
@@ -827,6 +842,7 @@
if (php_stream_read(stream, tmp, offset) == 0)
return -1;
}
+ stream->eof = 0;
return 0;
}
@@ -1100,6 +1116,7 @@
typedef struct {
FILE *file;
+ int fd; /* underlying file descriptor */
int is_process_pipe; /* use pclose instead of fclose */
int is_pipe; /* don't try and seek */
#if HAVE_FLUSHIO
@@ -1149,21 +1166,19 @@
PHPAPI php_stream *_php_stream_fopen_from_file(FILE *file, const char *mode
STREAMS_DC TSRMLS_DC)
{
php_stdio_stream_data *self;
-#ifdef S_ISFIFO
- int fd;
-#endif
self = emalloc_rel_orig(sizeof(*self));
self->file = file;
self->is_pipe = 0;
self->is_process_pipe = 0;
+ self->fd = fileno(file);
+
#ifdef S_ISFIFO
/* detect if this is a pipe */
- fd = fileno(file);
- if (fd >= 0) {
+ if (self->fd >= 0) {
struct stat sb;
- self->is_pipe = (fstat(fd, &sb) == 0 && S_ISFIFO(sb.st_mode)) ? 1 : 0;
+ self->is_pipe = (fstat(self->fd, &sb) == 0 && S_ISFIFO(sb.st_mode)) ?
+1 : 0;
}
#endif
@@ -1178,6 +1193,8 @@
self->file = file;
self->is_pipe = 1;
self->is_process_pipe = 1;
+ self->fd = fileno(file);
+
return php_stream_alloc_rel(&php_stream_stdio_ops, self, 0, mode);
}
@@ -1187,37 +1204,48 @@
assert(data != NULL);
+ if (data->fd >= 0) {
+
+ return write(data->fd, buf, count);
+
+ } else {
+
#if HAVE_FLUSHIO
- if (!data->is_pipe && data->last_op == 'r') {
- fseek(data->file, 0, SEEK_CUR);
- }
- data->last_op = 'w';
+ if (!data->is_pipe && data->last_op == 'r') {
+ fseek(data->file, 0, SEEK_CUR);
+ }
+ data->last_op = 'w';
#endif
- return fwrite(buf, 1, count, data->file);
+ return fwrite(buf, 1, count, data->file);
+ }
}
static size_t php_stdiop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
{
php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract;
+ size_t ret;
assert(data != NULL);
- if (buf == NULL && count == 0) {
- /* check for EOF condition */
- if (feof(data->file)) {
- return EOF;
- }
- return 0;
- }
-
+ if (data->fd >= 0) {
+ ret = read(data->fd, buf, count);
+
+ if (ret == 0 || (ret < 0 && errno != EWOULDBLOCK))
+ stream->eof = 1;
+
+ } else {
#if HAVE_FLUSHIO
- if (!data->is_pipe && data->last_op == 'w')
- fseek(data->file, 0, SEEK_CUR);
- data->last_op = 'r';
+ if (!data->is_pipe && data->last_op == 'w')
+ fseek(data->file, 0, SEEK_CUR);
+ data->last_op = 'r';
#endif
- return fread(buf, 1, count, data->file);
+ ret = fread(buf, 1, count, data->file);
+
+ if (ret == 0 && feof(data->file))
+ stream->eof = 1;
+ }
}
static int php_stdiop_close(php_stream *stream, int close_handle TSRMLS_DC)
@@ -1249,7 +1277,11 @@
assert(data != NULL);
- return fflush(data->file);
+ if (data->fd >= 0) {
+ return fsync(data->fd);
+ } else {
+ return fflush(data->file);
+ }
}
static int php_stdiop_seek(php_stream *stream, off_t offset, int whence, off_t
*newoffset TSRMLS_DC)
@@ -1263,10 +1295,22 @@
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot seek on a pipe");
return -1;
}
-
- ret = fseek(data->file, offset, whence);
- *newoffset = ftell(data->file);
- return ret;
+
+ if (data->fd >= 0) {
+ off_t result;
+
+ result = lseek(data->fd, offset, whence);
+ if (result == (off_t)-1)
+ return -1;
+
+ *newoffset = result;
+ return 0;
+
+ } else {
+ ret = fseek(data->file, offset, whence);
+ *newoffset = ftell(data->file);
+ return ret;
+ }
}
static int php_stdiop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC)
@@ -1275,15 +1319,22 @@
php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract;
assert(data != NULL);
+
+ /* as soon as someone touches the stdio layer, buffering may ensue,
+ * so we need to stop using the fd directly in that case */
switch (castas) {
case PHP_STREAM_AS_STDIO:
if (ret) {
*ret = data->file;
+ data->fd = -1;
}
return SUCCESS;
case PHP_STREAM_AS_FD:
+ /* fetch the fileno rather than using data->fd, since we may
+ * have zeroed that member if someone requested the FILE*
+ * first (see above case) */
fd = fileno(data->file);
if (fd < 0) {
return FAILURE;
Index: php4/main/user_streams.c
diff -u php4/main/user_streams.c:1.25 php4/main/user_streams.c:1.26
--- php4/main/user_streams.c:1.25 Sat Sep 28 18:14:21 2002
+++ php4/main/user_streams.c Sat Oct 5 06:35:13 2002
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: user_streams.c,v 1.25 2002/09/28 22:14:21 wez Exp $ */
+/* $Id: user_streams.c,v 1.26 2002/10/05 10:35:13 wez Exp $ */
#include "php.h"
#include "php_globals.h"
@@ -431,65 +431,61 @@
int call_result;
size_t didread = 0;
php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
+ zval *zcount;
assert(us != NULL);
- if (buf == NULL && count == 0) {
- ZVAL_STRINGL(&func_name, USERSTREAM_EOF, sizeof(USERSTREAM_EOF)-1, 0);
+ ZVAL_STRINGL(&func_name, USERSTREAM_READ, sizeof(USERSTREAM_READ)-1, 0);
- call_result = call_user_function_ex(NULL,
+ MAKE_STD_ZVAL(zcount);
+ ZVAL_LONG(zcount, count);
+ args[0] = &zcount;
+
+ call_result = call_user_function_ex(NULL,
&us->object,
&func_name,
&retval,
- 0, NULL, 0, NULL TSRMLS_CC);
-
- if (call_result == SUCCESS && retval != NULL && zval_is_true(retval))
- didread = 0;
- else {
- if (call_result == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::"
USERSTREAM_EOF " is not implemented! Assuming EOF",
- us->wrapper->classname);
- }
+ 1, args,
+ 0, NULL TSRMLS_CC);
- didread = EOF;
+ if (call_result == SUCCESS && retval != NULL) {
+ convert_to_string(retval);
+ didread = Z_STRLEN_P(retval);
+ if (didread > count) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::"
+USERSTREAM_READ " - read %d bytes more data than requested (%d read, %d max) - excess
+data will be lost",
+ us->wrapper->classname, didread - count,
+didread, count);
+ didread = count;
}
+ if (didread > 0)
+ memcpy(buf, Z_STRVAL_P(retval), didread);
+ } else if (call_result == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_READ "
+is not implemented!",
+ us->wrapper->classname);
+ }
+ zval_ptr_dtor(&zcount);
- } else {
- zval *zcount;
+ if (retval)
+ zval_ptr_dtor(&retval);
- ZVAL_STRINGL(&func_name, USERSTREAM_READ, sizeof(USERSTREAM_READ)-1,
0);
+ /* since the user stream has no way of setting the eof flag directly, we need
+to ask it if we hit eof */
- MAKE_STD_ZVAL(zcount);
- ZVAL_LONG(zcount, count);
- args[0] = &zcount;
-
- call_result = call_user_function_ex(NULL,
- &us->object,
- &func_name,
- &retval,
- 1, args,
- 0, NULL TSRMLS_CC);
-
- if (call_result == SUCCESS && retval != NULL) {
- convert_to_string(retval);
- didread = Z_STRLEN_P(retval);
- if (didread > count) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::"
USERSTREAM_READ " - read %d bytes more data than requested (%d read, %d max) - excess
data will be lost",
- us->wrapper->classname, didread -
count, didread, count);
- didread = count;
- }
- if (didread > 0)
- memcpy(buf, Z_STRVAL_P(retval), didread);
- } else if (call_result == FAILURE) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::"
USERSTREAM_READ " is not implemented!",
+ ZVAL_STRINGL(&func_name, USERSTREAM_EOF, sizeof(USERSTREAM_EOF)-1, 0);
+
+ call_result = call_user_function_ex(NULL,
+ &us->object,
+ &func_name,
+ &retval,
+ 0, NULL, 0, NULL TSRMLS_CC);
+
+ if (!(call_result == SUCCESS && retval != NULL && zval_is_true(retval))) {
+ if (call_result == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::"
+USERSTREAM_EOF " is not implemented! Assuming EOF",
us->wrapper->classname);
}
- zval_ptr_dtor(&zcount);
+
+ stream->eof = 1;
}
-
- if (retval)
- zval_ptr_dtor(&retval);
-
+
return didread;
}
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php