diff options
author | Wez Furlong <wez@php.net> | 2002-11-18 11:39:42 +0000 |
---|---|---|
committer | Wez Furlong <wez@php.net> | 2002-11-18 11:39:42 +0000 |
commit | ca58966a0d12c21599edb25281ace01caf12f5c1 (patch) | |
tree | 8690ded800b6923baf3f2d5190952076a28999dc | |
parent | a94a2266917a69d50aba2ee402ae1ca8a659bd7c (diff) | |
download | php-git-ca58966a0d12c21599edb25281ace01caf12f5c1.tar.gz |
Merge streams changes from branch.
-rw-r--r-- | acinclude.m4 | 16 | ||||
-rw-r--r-- | ext/zlib/zlib.c | 1 | ||||
-rwxr-xr-x | main/php_streams.h | 13 | ||||
-rwxr-xr-x | main/streams.c | 162 |
4 files changed, 136 insertions, 56 deletions
diff --git a/acinclude.m4 b/acinclude.m4 index 811030b558..b86185f6e0 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -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 diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index 0238d2fd1a..54fb078691 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -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(); diff --git a/main/php_streams.h b/main/php_streams.h index 8e94f0949b..093d2a48ae 100755 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -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) diff --git a/main/streams.c b/main/streams.c index 6d8d02d989..43b6ab080f 100755 --- a/main/streams.c +++ b/main/streams.c @@ -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; } |