]> granicus.if.org Git - php/commitdiff
Merge streams changes from branch.
authorWez Furlong <wez@php.net>
Mon, 18 Nov 2002 11:39:42 +0000 (11:39 +0000)
committerWez Furlong <wez@php.net>
Mon, 18 Nov 2002 11:39:42 +0000 (11:39 +0000)
acinclude.m4
ext/zlib/zlib.c
main/php_streams.h
main/streams.c

index 811030b5588bf85f4743fae4ccf258e438344c09..b86185f6e0c925286df32acdda76575098dc34ac 100644 (file)
@@ -1480,16 +1480,16 @@ AC_DEFUN([PHP_FOPENCOOKIE],[
 #include <stdio.h>
 
 struct cookiedata {
-       fpos_t pos;
+       __off64_t pos;
 };
 
-size_t reader(void *cookie, char *buffer, size_t size)
+__ssize_t reader(void *cookie, char *buffer, size_t size)
 { return size; }
-size_t writer(void *cookie, const char *buffer, size_t size)
+__ssize_t writer(void *cookie, const char *buffer, size_t size)
 { return size; }
 int closer(void *cookie)
 { return 0; }
-int seeker(void *cookie, fpos_t *position, int whence)
+int seeker(void *cookie, __off64_t *position, int whence)
 { ((struct cookiedata*)cookie)->pos = *position; return 0; }
 
 cookie_io_functions_t funcs = {reader, writer, seeker, closer};
@@ -1498,13 +1498,13 @@ main() {
   struct cookiedata g = { 0 };
   FILE *fp = fopencookie(&g, "r", funcs);
 
-  if (fp && fseek(fp, 69, SEEK_SET) == 0 && g.pos == 69)
+  if (fp && fseek(fp, 8192, SEEK_SET) == 0 && g.pos == 8192)
          exit(0);
   exit(1);
 }
 
                                           ],
-                                          [ cookie_io_functions_use_fpos_t=yes ],
+                                          [ cookie_io_functions_use_off64_t=yes ],
                                           [ ] )
                
       else
@@ -1525,8 +1525,8 @@ main() {
       if test "$have_fopen_cookie" = "yes" ; then
         AC_DEFINE(HAVE_FOPENCOOKIE, 1, [ ])
         AC_DEFINE_UNQUOTED(COOKIE_IO_FUNCTIONS_T, $cookie_io_functions_t, [ ])
-               if test "$cookie_io_functions_use_fpos_t" = "yes" ; then
-          AC_DEFINE(COOKIE_SEEKER_USES_FPOS_T, 1, [ ])
+               if test "$cookie_io_functions_use_off64_t" = "yes" ; then
+          AC_DEFINE(COOKIE_SEEKER_USES_OFF64_T, 1, [ ])
                fi
       fi      
 
index 0238d2fd1ad276bd2e41da9827123c43d520e8cd..54fb0786913fd749e0d7e36405114c35e8079405 100644 (file)
@@ -258,7 +258,6 @@ PHP_MINFO_FUNCTION(zlib)
 {
        php_info_print_table_start();
        php_info_print_table_row(2, "ZLib Support", "enabled");
-       php_info_print_table_row(2, "'zlib:' fopen wrapper", "enabled");
        php_info_print_table_row(2, "Compiled Version", ZLIB_VERSION );
        php_info_print_table_row(2, "Linked Version", (char *)zlibVersion() );
        php_info_print_table_end();
index 8e94f0949b62a9ef5a74095f488bb62f272bd975..093d2a48aefea7f2900e5ede3f0861ab1f40ca8f 100755 (executable)
@@ -16,6 +16,8 @@
    +----------------------------------------------------------------------+
  */
 
+/* $Id$ */
+
 #ifndef PHP_STREAMS_H
 #define PHP_STREAMS_H
 
@@ -329,6 +331,7 @@ PHPAPI int php_stream_from_persistent_id(const char *persistent_id, php_stream *
 #define PHP_STREAM_FREE_PRESERVE_HANDLE                4 /* tell ops->close to not close it's underlying handle */
 #define PHP_STREAM_FREE_RSRC_DTOR                      8 /* called from the resource list dtor */
 #define PHP_STREAM_FREE_CLOSE                          (PHP_STREAM_FREE_CALL_DTOR | PHP_STREAM_FREE_RELEASE_STREAM)
+#define PHP_STREAM_FREE_CLOSE_CASTED           (PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_PRESERVE_HANDLE)
 PHPAPI int _php_stream_free(php_stream *stream, int close_options TSRMLS_DC);
 #define php_stream_free(stream, close_options) _php_stream_free((stream), (close_options) TSRMLS_CC)
 #define php_stream_close(stream)       _php_stream_free((stream), PHP_STREAM_FREE_CLOSE TSRMLS_CC)
@@ -456,7 +459,7 @@ PHPAPI php_stream *_php_stream_fopen_temporary_file(const char *dir, const char
 /* cast as a socketd */
 #define PHP_STREAM_AS_SOCKETD  2
 
-/* try really, really hard to make sure the cast happens (socketpair) */
+/* try really, really hard to make sure the cast happens (avoid using this flag if possible) */
 #define PHP_STREAM_CAST_TRY_HARD       0x80000000
 #define PHP_STREAM_CAST_RELEASE                0x40000000      /* stream becomes invalid on success */
 #define PHP_STREAM_CAST_INTERNAL       0x20000000      /* stream cast for internal use */
@@ -499,11 +502,8 @@ PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show
 /* this flag is only used by include/require functions */
 #define STREAM_OPEN_FOR_INCLUDE                128
 
-#ifdef PHP_WIN32
-# define IGNORE_URL_WIN STREAM_MUST_SEEK
-#else
-# define IGNORE_URL_WIN 0
-#endif
+/* Antique - no longer has meaning */
+#define IGNORE_URL_WIN 0
 
 int php_init_stream_wrappers(int module_number TSRMLS_DC);
 int php_shutdown_stream_wrappers(int module_number TSRMLS_DC);
@@ -528,6 +528,7 @@ PHPAPI void php_stream_wrapper_log_error(php_stream_wrapper *wrapper, int option
 #define PHP_STREAM_CRITICAL            3 /* an error occurred; origstream is in an unknown state; you should close origstream */
 #define PHP_STREAM_NO_PREFERENCE       0
 #define PHP_STREAM_PREFER_STDIO                1
+#define PHP_STREAM_FORCE_CONVERSION    2
 /* DO NOT call this on streams that are referenced by resources! */
 PHPAPI int _php_stream_make_seekable(php_stream *origstream, php_stream **newstream, int flags STREAMS_DC TSRMLS_DC);
 #define php_stream_make_seekable(origstream, newstream, flags) _php_stream_make_seekable((origstream), (newstream), (flags) STREAMS_CC TSRMLS_CC)
index 6d8d02d9894e07bba8f3e98ff781e12ae713777f..43b6ab080f65bf5baffaacf66074d507bd6fa081 100755 (executable)
@@ -48,7 +48,6 @@
 #endif
 
 #define STREAM_DEBUG 0
-
 #define STREAM_WRAPPER_PLAIN_FILES     ((php_stream_wrapper*)-1)
 
 /* {{{ some macros to help track leaks */
@@ -243,24 +242,55 @@ fprintf(stderr, "stream_alloc: %s:%p persistent=%s\n", ops->label, ret, persiste
 PHPAPI int _php_stream_free(php_stream *stream, int close_options TSRMLS_DC) /* {{{ */
 {
        int ret = 1;
+       int remove_rsrc = 1;
+       int preserve_handle = close_options & PHP_STREAM_FREE_PRESERVE_HANDLE ? 1 : 0;
+       int release_cast = 1;
 
 #if STREAM_DEBUG
 fprintf(stderr, "stream_free: %s:%p[%s] in_free=%d opts=%08x\n", stream->ops->label, stream, stream->__orig_path, stream->in_free, close_options);
 #endif
        
+       /* recursion protection */
        if (stream->in_free)
                return 1;
 
        stream->in_free++;
 
-       _php_stream_flush(stream, 1 TSRMLS_CC);
+       /* if we are releasing the stream only (and preserving the underlying handle),
+        * we need to do things a little differently.
+        * We are only ever called like this when the stream is cast to a FILE*
+        * for include (or other similar) purposes.
+        * */
+       if (preserve_handle) {
+               if (stream->fclose_stdiocast == PHP_STREAM_FCLOSE_FOPENCOOKIE) {
+                       /* If the stream was fopencookied, we must NOT touch anything
+                        * here, as the cookied stream relies on it all.
+                        * Instead, mark the stream as OK to auto-clean */
+                       php_stream_auto_cleanup(stream);
+                       stream->in_free--;
+                       return 0;
+               }
+               /* otherwise, make sure that we don't close the FILE* from a cast */
+               release_cast = 0;
+       }
+
+#if STREAM_DEBUG
+fprintf(stderr, "stream_free: %s:%p[%s] preserve_handle=%d release_cast=%d remove_rsrc=%d\n",
+               stream->ops->label, stream, stream->__orig_path, preserve_handle, release_cast, remove_rsrc);
+#endif
        
-       if ((close_options & PHP_STREAM_FREE_RSRC_DTOR) == 0) {
-               /* Remove entry from the resource list */
+       /* make sure everything is saved */
+       _php_stream_flush(stream, 1 TSRMLS_CC);
+               
+       /* If not called from the resource dtor, remove the stream
+     * from the resource list.
+        * */
+       if ((close_options & PHP_STREAM_FREE_RSRC_DTOR) == 0 && remove_rsrc) {
                zend_list_delete(stream->rsrc_id);
        }
+       
        if (close_options & PHP_STREAM_FREE_CALL_DTOR) {
-               if (stream->fclose_stdiocast == PHP_STREAM_FCLOSE_FOPENCOOKIE) {
+               if (release_cast && stream->fclose_stdiocast == PHP_STREAM_FCLOSE_FOPENCOOKIE) {
                        /* calling fclose on an fopencookied stream will ultimately
                                call this very same function.  If we were called via fclose,
                                the cookie_closer unsets the fclose_stdiocast flags, so
@@ -272,13 +302,14 @@ fprintf(stderr, "stream_free: %s:%p[%s] in_free=%d opts=%08x\n", stream->ops->la
                        return fclose(stream->stdiocast);
                }
 
-               ret = stream->ops->close(stream, close_options & PHP_STREAM_FREE_PRESERVE_HANDLE ? 0 : 1 TSRMLS_CC);
+               ret = stream->ops->close(stream, preserve_handle ? 0 : 1 TSRMLS_CC);
                stream->abstract = NULL;
 
                /* tidy up any FILE* that might have been fdopened */
-               if (stream->fclose_stdiocast == PHP_STREAM_FCLOSE_FDOPEN && stream->stdiocast) {
+               if (release_cast && stream->fclose_stdiocast == PHP_STREAM_FCLOSE_FDOPEN && stream->stdiocast) {
                        fclose(stream->stdiocast);
                        stream->stdiocast = NULL;
+                       stream->fclose_stdiocast = PHP_STREAM_FCLOSE_NONE;
                }
        }
 
@@ -1193,6 +1224,8 @@ typedef struct {
        int fd;                                 /* underlying file descriptor */
        int is_process_pipe;    /* use pclose instead of fclose */
        int is_pipe;                    /* don't try and seek */
+       char *temp_file_name;   /* if non-null, this is the path to a temporary file that
+                                                        * is to be deleted when the stream is closed */
 #if HAVE_FLUSHIO
        char last_op;
 #endif
@@ -1218,21 +1251,24 @@ PHPAPI php_stream *_php_stream_fopen_temporary_file(const char *dir, const char
 
 PHPAPI php_stream *_php_stream_fopen_tmpfile(int dummy STREAMS_DC TSRMLS_DC)
 {
-       FILE *fp;
-       php_stream *stream;
+       char *opened_path = NULL;
+       FILE *fp = php_open_temporary_file(NULL, "php", &opened_path TSRMLS_CC);
 
-       fp = tmpfile();
-       if (fp == NULL) {
-               php_error_docref(NULL TSRMLS_CC, E_WARNING, "tmpfile(): %s", strerror(errno));
-               return NULL;
-       }
-       stream = php_stream_fopen_from_file_rel(fp, "r+");
-       if (stream == NULL)     {
-               php_error_docref(NULL TSRMLS_CC, E_WARNING, "tmpfile(): %s", strerror(errno));
+       if (fp) {
+               php_stream *stream = php_stream_fopen_from_file_rel(fp, "r+b");
+               if (stream) {
+                       php_stdio_stream_data *self = (php_stdio_stream_data*)stream->abstract;
+
+                       self->temp_file_name = opened_path;
+                       return stream;
+               }
                fclose(fp);
+
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to allocate stream");
+
                return NULL;
        }
-       return stream;
+       return NULL;
 }
 
 
@@ -1245,7 +1281,7 @@ PHPAPI php_stream *_php_stream_fopen_from_file(FILE *file, const char *mode STRE
        self->file = file;
        self->is_pipe = 0;
        self->is_process_pipe = 0;
-
+       self->temp_file_name = NULL;
        self->fd = fileno(file);
 
 #ifdef S_ISFIFO
@@ -1268,6 +1304,7 @@ PHPAPI php_stream *_php_stream_fopen_from_pipe(FILE *file, const char *mode STRE
        self->is_pipe = 1;
        self->is_process_pipe = 1;
        self->fd = fileno(file);
+       self->temp_file_name = NULL;
 
        return php_stream_alloc_rel(&php_stream_stdio_ops, self, 0, mode);
 }
@@ -1331,13 +1368,20 @@ static int php_stdiop_close(php_stream *stream, int close_handle TSRMLS_DC)
        assert(data != NULL);
 
        if (close_handle) {
-               if (data->is_process_pipe) {
-                       ret = pclose(data->file);
-               } else {
-                       ret = fclose(data->file);
+               if (data->file) {
+                       if (data->is_process_pipe) {
+                               ret = pclose(data->file);
+                       } else {
+                               ret = fclose(data->file);
+                       }
+               }
+               if (data->temp_file_name) {
+                       unlink(data->temp_file_name);
+                       efree(data->temp_file_name);
                }
        } else {
                ret = 0;
+               data->file = NULL;
        }
 
        /* STDIO streams are never persistent! */
@@ -1720,7 +1764,7 @@ PHPAPI php_stream *_php_stream_fopen(const char *filename, const char *mode, cha
 
                        return ret;
                }
-               err:
+err:
                fclose(fp);
        }
        efree(realpath);
@@ -1744,12 +1788,12 @@ static ssize_t stream_cookie_writer(void *cookie, const char *buffer, size_t siz
        return php_stream_write(((php_stream *)cookie), (char *)buffer, size);
 }
 
-#ifdef COOKIE_SEEKER_USES_FPOS_T
-static int stream_cookie_seeker(void *cookie, fpos_t *position, int whence)
+#ifdef COOKIE_SEEKER_USES_OFF64_T
+static int stream_cookie_seeker(void *cookie, __off64_t *position, int whence)
 {
        TSRMLS_FETCH();
 
-       *position = php_stream_seek((php_stream *)cookie, *position, whence);
+       *position = php_stream_seek((php_stream *)cookie, (off_t)*position, whence);
 
        if (*position == -1)
                return -1;
@@ -1850,15 +1894,38 @@ PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show
                return FAILURE;
 #endif
 
+               if (flags & PHP_STREAM_CAST_TRY_HARD) {
+                       php_stream *newstream;
+
+                       newstream = php_stream_fopen_tmpfile();
+                       if (newstream) {
+                               size_t copied = php_stream_copy_to_stream(stream, newstream, PHP_STREAM_COPY_ALL);
+
+                               if (copied == 0) {
+                                       php_stream_close(newstream);
+                               } else {
+                                       int retcode = php_stream_cast(newstream, castas | flags, ret, show_err);
+
+                                       if (retcode == SUCCESS)
+                                               rewind((FILE*)*ret);
+                                       
+                                       /* do some specialized cleanup */
+                                       if ((flags & PHP_STREAM_CAST_RELEASE)) {
+                                               php_stream_free(stream, PHP_STREAM_FREE_CLOSE_CASTED);
+                                       }
+
+                                       return retcode;
+                               }
+                       }
+               }
        }
 
        if (stream->filterhead) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot cast a filtered stream on this system");
                return FAILURE;
-       }
-       
-       if (stream->ops->cast && stream->ops->cast(stream, castas, ret TSRMLS_CC) == SUCCESS)
+       } else if (stream->ops->cast && stream->ops->cast(stream, castas, ret TSRMLS_CC) == SUCCESS) {
                goto exit_success;
+       }
 
        if (show_err) {
                /* these names depend on the values of the PHP_STREAM_AS_XXX defines in php_streams.h */
@@ -1892,16 +1959,7 @@ exit_success:
                stream->stdiocast = *ret;
        
        if (flags & PHP_STREAM_CAST_RELEASE) {
-               /* Something other than php_stream_close will be closing
-                * the underlying handle, so we should free the stream handle/data
-                * here now.  The stream may not be freed immediately (in the case
-                * of fopencookie), but the caller should still not touch their
-                * original stream pointer in any case. */
-               if (stream->fclose_stdiocast != PHP_STREAM_FCLOSE_FOPENCOOKIE) {
-                       /* ask the implementation to release resources other than
-                        * the underlying handle */
-                       php_stream_free(stream, PHP_STREAM_FREE_PRESERVE_HANDLE | PHP_STREAM_FREE_CLOSE);
-               }
+               php_stream_free(stream, PHP_STREAM_FREE_CLOSE_CASTED);
        }
 
        return SUCCESS;
@@ -2296,6 +2354,28 @@ PHPAPI FILE * _php_stream_open_wrapper_as_file(char *path, char *mode, int optio
 
        if (stream == NULL)
                return NULL;
+
+#ifdef PHP_WIN32
+       /* Avoid possible strange problems when working with socket based streams */
+       if ((options & STREAM_OPEN_FOR_INCLUDE) && php_stream_is(stream, PHP_STREAM_IS_SOCKET)) {
+               char buf[CHUNK_SIZE];
+
+               fp = php_open_temporary_file(NULL, "php", NULL TSRMLS_CC);
+               if (fp) {
+                       while (!php_stream_eof(stream)) {
+                               size_t didread = php_stream_read(stream, buf, sizeof(buf));
+                               if (didread > 0) {
+                                       fwrite(buf, 1, didread, fp);
+                               } else {
+                                       break;
+                               }
+                       }
+                       php_stream_close(stream);
+                       rewind(fp);
+                       return fp;
+               }
+       }
+#endif
        
        if (php_stream_cast(stream, PHP_STREAM_AS_STDIO|PHP_STREAM_CAST_TRY_HARD|PHP_STREAM_CAST_RELEASE,
                                (void**)&fp, REPORT_ERRORS) == FAILURE)
@@ -2316,7 +2396,7 @@ PHPAPI int _php_stream_make_seekable(php_stream *origstream, php_stream **newstr
 
        *newstream = NULL;
        
-       if (origstream->ops->seek != NULL) {
+       if (((flags & PHP_STREAM_FORCE_CONVERSION) == 0) && origstream->ops->seek != NULL) {
                *newstream = origstream;
                return PHP_STREAM_UNCHANGED;
        }