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

Reply via email to