cvs: php4 / README.STREAMS /main fopen_wrappers.h php_streams.h streams.c
| From: | Wez Furlong | Date: | Sun, 17 Mar 2002 14:21:01 +0000 |
| Subject: | cvs: php4 / README.STREAMS /main fopen_wrappers.h php_streams.h streams.c | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-10289@lists.php.net to get a copy of this message | ||
wez Sun Mar 17 09:21:01 2002 EDT
Modified files:
/php4 README.STREAMS
/php4/main fopen_wrappers.h php_streams.h streams.c
Log:
Fix for php_stream_gets when the implementation does not support it
natively (Thanks Marcus).
Implement php_stream_make_seekable() and add STREAM_MUST_SEEK as an
option to php_stream_open_wrapper().
See README.STREAMS for usage.
Index: php4/README.STREAMS diff -u php4/README.STREAMS:1.3 php4/README.STREAMS:1.4 --- php4/README.STREAMS:1.3 Sat Mar 16 08:54:03 2002 +++ php4/README.STREAMS Sun Mar 17 09:20:56 2002 @@ -1,6 +1,6 @@ An Overview of the PHP Streams abstraction ========================================== -$Id: README.STREAMS,v 1.3 2002/03/16 13:54:03 wez Exp $ +$Id: README.STREAMS,v 1.4 2002/03/17 14:20:56 wez Exp $ Please send comments to: Wez Furlong <wez@thebrainroom.com> @@ -51,7 +51,16 @@ IGNORE_URL - do not use plugin wrappers REPORT_ERRORS - show errors in a standard format if something goes wrong. - opened_path is used to return the path of the actual file opened. + STREAM_MUST_SEEK - If you really need to be able to seek the stream + and don't need to be able to write to the original + file/URL, use this option to arrange for the stream + to be copied (if needed) into a stream that can + be seek()ed. + + opened_path is used to return the path of the actual file opened, + but if you used STREAM_MUST_SEEK, may not be valid. You are + responsible for efree()ing opened_path. opened_path may be (and usually + is) NULL. If you need to open a specific stream, or convert standard resources into streams there are a range of functions to do this defined in php_streams.h. @@ -108,6 +117,39 @@ The buffer is allocated using pemalloc(); you need to call pefree() to release the memory when you are done. As with copy_to_stream, this function will try use mmap where it can. + +If you have an existing stream and need to be able to seek() it, you +can use this function to copy the contents into a new stream that can +be seek()ed: + +PHPAPI int php_stream_make_seekable(php_stream *origstream, php_stream **newstream); + +It returns one of the following values: +#define PHP_STREAM_UNCHANGED 0 /* orig stream was seekable anyway */ +#define PHP_STREAM_RELEASED 1 /* newstream should be used; origstream is no longer valid */ +#define PHP_STREAM_FAILED 2 /* an error occurred while attempting conversion */ +#define PHP_STREAM_CRITICAL 3 /* an error occurred; origstream is in an unknown state; you should close origstream */ + +make_seekable will always set newstream to be the stream that is valid +if the function succeeds. +When you have finished, remember to close the stream. + +NOTE: If you only need to seek forwards, there is no need to call this +function, as the php_stream_seek can emulate forward seeking when the +whence parameter is SEEK_CUR. + +NOTE: Writing to the stream may not affect the original source, so it +only makes sense to use this for read-only use. + +NOTE: If the origstream is network based, this function will block +until the whole contents have been downloaded. + +NOTE: Never call this function with an origstream that is referenced +as a resource! It will close the origstream on success, and this +can lead to a crash when the resource is later used/released. + +NOTE: If you are opening a stream and need it to be seekable, use the +STREAM_MUST_SEEK option to php_stream_open_wrapper(); Casting Streams =============== Index: php4/main/fopen_wrappers.h diff -u php4/main/fopen_wrappers.h:1.35 php4/main/fopen_wrappers.h:1.36 --- php4/main/fopen_wrappers.h:1.35 Sun Mar 17 08:29:44 2002 +++ php4/main/fopen_wrappers.h Sun Mar 17 09:21:00 2002 @@ -15,25 +15,12 @@ | Author: Jim Winstead <jimw@php.net> | +----------------------------------------------------------------------+ */ -/* $Id: fopen_wrappers.h,v 1.35 2002/03/17 13:29:44 wez Exp $ */ +/* $Id: fopen_wrappers.h,v 1.36 2002/03/17 14:21:00 wez Exp $ */ #ifndef FOPEN_WRAPPERS_H #define FOPEN_WRAPPERS_H #include "php_globals.h" - -#define IGNORE_PATH 0 -#define USE_PATH 1 -#define IGNORE_URL 2 -/* There's no USE_URL. */ -#define ENFORCE_SAFE_MODE 4 -#define REPORT_ERRORS 8 - -#ifdef PHP_WIN32 -# define IGNORE_URL_WIN IGNORE_URL -#else -# define IGNORE_URL_WIN 0 -#endif PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle TSRMLS_DC); PHPAPI char *expand_filepath(const char *filepath, char *real_path TSRMLS_DC); Index: php4/main/php_streams.h diff -u php4/main/php_streams.h:1.13 php4/main/php_streams.h:1.14 --- php4/main/php_streams.h:1.13 Sat Mar 16 09:39:51 2002 +++ php4/main/php_streams.h Sun Mar 17 09:21:01 2002 @@ -146,12 +146,35 @@ #define php_stream_is_persistent(stream) (stream)->is_persistent /* Wrappers support */ + +#define IGNORE_PATH 0 +#define USE_PATH 1 +#define IGNORE_URL 2 +/* There's no USE_URL. */ +#define ENFORCE_SAFE_MODE 4 +#define REPORT_ERRORS 8 +/* If you don't need to write to the stream, but really need to + * be able to seek, use this flag in your options. */ +#define STREAM_MUST_SEEK 16 + +#ifdef PHP_WIN32 +# define IGNORE_URL_WIN IGNORE_URL +#else +# define IGNORE_URL_WIN 0 +#endif + int php_init_stream_wrappers(TSRMLS_D); int php_shutdown_stream_wrappers(TSRMLS_D); PHPAPI int php_register_url_stream_wrapper(char *protocol, php_stream_wrapper *wrapper TSRMLS_DC); PHPAPI int php_unregister_url_stream_wrapper(char *protocol TSRMLS_DC); - PHPAPI php_stream *php_stream_open_wrapper(char *path, char *mode, int options, char **opened_path TSRMLS_DC); + +#define PHP_STREAM_UNCHANGED 0 /* orig stream was seekable anyway */ +#define PHP_STREAM_RELEASED 1 /* newstream should be used; origstream is no longer valid */ +#define PHP_STREAM_FAILED 2 /* an error occurred while attempting conversion */ +#define PHP_STREAM_CRITICAL 3 /* an error occurred; origstream is in an unknown state; you should close origstream */ +/* DO NOT call this on streams that are referenced by resources! */ +PHPAPI int php_stream_make_seekable(php_stream *origstream, php_stream **newstream); #endif Index: php4/main/streams.c diff -u php4/main/streams.c:1.25 php4/main/streams.c:1.26 --- php4/main/streams.c:1.25 Sun Mar 17 07:06:41 2002 +++ php4/main/streams.c Sun Mar 17 09:21:01 2002 @@ -166,7 +166,7 @@ return stream->ops->gets(stream, buf, maxlen); } else { /* unbuffered fgets - poor performance ! */ - size_t n = 0; + size_t n = 1; char *c = buf; /* TODO: look at error returns? */ @@ -944,7 +944,7 @@ goto out; } - if ((options & USE_PATH) && PG(include_path) != NULL) { + if ((options & USE_PATH) && PG(include_path) != NULL) { stream = php_stream_fopen_with_path(path, mode, PG(include_path), opened_path TSRMLS_CC); goto out; } @@ -954,7 +954,29 @@ stream = php_stream_fopen(path, mode, opened_path TSRMLS_CC); out: - if (stream == NULL && (options & REPORT_ERRORS)) { + if (stream != NULL && (options & STREAM_MUST_SEEK)) { + php_stream *newstream; + + switch(php_stream_make_seekable(stream, &newstream)) { + case PHP_STREAM_UNCHANGED: + return stream; + case PHP_STREAM_RELEASED: + return newstream; + default: + php_stream_close(stream); + stream = NULL; + if (options & REPORT_ERRORS) { + char *tmp = estrdup(path); + php_strip_url_passwd(tmp); + zend_error(E_WARNING, "%s(\"%s\") - could not make seekable - %s", + get_active_function_name(TSRMLS_C), tmp, strerror(errno)); + efree(tmp); + + options ^= REPORT_ERRORS; + } + } + } + if (stream == NULL && (options & REPORT_ERRORS)) { char *tmp = estrdup(path); php_strip_url_passwd(tmp); zend_error(E_WARNING, "%s(\"%s\") - %s", get_active_function_name(TSRMLS_C), tmp, strerror(errno)); @@ -963,6 +985,34 @@ return stream; } +PHPAPI int php_stream_make_seekable(php_stream *origstream, php_stream **newstream) +{ + assert(newstream != NULL); + + *newstream = NULL; + + if (origstream->ops->seek != NULL) { + *newstream = origstream; + return PHP_STREAM_UNCHANGED; + } + + /* Use a tmpfile and copy the old streams contents into it */ + + *newstream = php_stream_fopen_tmpfile(); + + if (*newstream == NULL) + return PHP_STREAM_FAILED; + + if (php_stream_copy_to_stream(origstream, *newstream, PHP_STREAM_COPY_ALL) == 0) { + php_stream_close(*newstream); + *newstream = NULL; + return PHP_STREAM_CRITICAL; + } + + php_stream_close(origstream); + + return PHP_STREAM_RELEASED; +} /* * Local variables:
Index: php4/README.STREAMS diff -u php4/README.STREAMS:1.3 php4/README.STREAMS:1.4 --- php4/README.STREAMS:1.3 Sat Mar 16 08:54:03 2002 +++ php4/README.STREAMS Sun Mar 17 09:20:56 2002 @@ -1,6 +1,6 @@ An Overview of the PHP Streams abstraction ========================================== -$Id: README.STREAMS,v 1.3 2002/03/16 13:54:03 wez Exp $ +$Id: README.STREAMS,v 1.4 2002/03/17 14:20:56 wez Exp $ Please send comments to: Wez Furlong <wez@thebrainroom.com> @@ -51,7 +51,16 @@ IGNORE_URL - do not use plugin wrappers REPORT_ERRORS - show errors in a standard format if something goes wrong. - opened_path is used to return the path of the actual file opened. + STREAM_MUST_SEEK - If you really need to be able to seek the stream + and don't need to be able to write to the original + file/URL, use this option to arrange for the stream + to be copied (if needed) into a stream that can + be seek()ed. + + opened_path is used to return the path of the actual file opened, + but if you used STREAM_MUST_SEEK, may not be valid. You are + responsible for efree()ing opened_path. opened_path may be (and usually + is) NULL. If you need to open a specific stream, or convert standard resources into streams there are a range of functions to do this defined in php_streams.h. @@ -108,6 +117,39 @@ The buffer is allocated using pemalloc(); you need to call pefree() to release the memory when you are done. As with copy_to_stream, this function will try use mmap where it can. + +If you have an existing stream and need to be able to seek() it, you +can use this function to copy the contents into a new stream that can +be seek()ed: + +PHPAPI int php_stream_make_seekable(php_stream *origstream, php_stream **newstream); + +It returns one of the following values: +#define PHP_STREAM_UNCHANGED 0 /* orig stream was seekable anyway */ +#define PHP_STREAM_RELEASED 1 /* newstream should be used; origstream is no longer valid */ +#define PHP_STREAM_FAILED 2 /* an error occurred while attempting conversion */ +#define PHP_STREAM_CRITICAL 3 /* an error occurred; origstream is in an unknown state; you should close origstream */ + +make_seekable will always set newstream to be the stream that is valid +if the function succeeds. +When you have finished, remember to close the stream. + +NOTE: If you only need to seek forwards, there is no need to call this +function, as the php_stream_seek can emulate forward seeking when the +whence parameter is SEEK_CUR. + +NOTE: Writing to the stream may not affect the original source, so it +only makes sense to use this for read-only use. + +NOTE: If the origstream is network based, this function will block +until the whole contents have been downloaded. + +NOTE: Never call this function with an origstream that is referenced +as a resource! It will close the origstream on success, and this +can lead to a crash when the resource is later used/released. + +NOTE: If you are opening a stream and need it to be seekable, use the +STREAM_MUST_SEEK option to php_stream_open_wrapper(); Casting Streams =============== Index: php4/main/fopen_wrappers.h diff -u php4/main/fopen_wrappers.h:1.35 php4/main/fopen_wrappers.h:1.36 --- php4/main/fopen_wrappers.h:1.35 Sun Mar 17 08:29:44 2002 +++ php4/main/fopen_wrappers.h Sun Mar 17 09:21:00 2002 @@ -15,25 +15,12 @@ | Author: Jim Winstead <jimw@php.net> | +----------------------------------------------------------------------+ */ -/* $Id: fopen_wrappers.h,v 1.35 2002/03/17 13:29:44 wez Exp $ */ +/* $Id: fopen_wrappers.h,v 1.36 2002/03/17 14:21:00 wez Exp $ */ #ifndef FOPEN_WRAPPERS_H #define FOPEN_WRAPPERS_H #include "php_globals.h" - -#define IGNORE_PATH 0 -#define USE_PATH 1 -#define IGNORE_URL 2 -/* There's no USE_URL. */ -#define ENFORCE_SAFE_MODE 4 -#define REPORT_ERRORS 8 - -#ifdef PHP_WIN32 -# define IGNORE_URL_WIN IGNORE_URL -#else -# define IGNORE_URL_WIN 0 -#endif PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle TSRMLS_DC); PHPAPI char *expand_filepath(const char *filepath, char *real_path TSRMLS_DC); Index: php4/main/php_streams.h diff -u php4/main/php_streams.h:1.13 php4/main/php_streams.h:1.14 --- php4/main/php_streams.h:1.13 Sat Mar 16 09:39:51 2002 +++ php4/main/php_streams.h Sun Mar 17 09:21:01 2002 @@ -146,12 +146,35 @@ #define php_stream_is_persistent(stream) (stream)->is_persistent /* Wrappers support */ + +#define IGNORE_PATH 0 +#define USE_PATH 1 +#define IGNORE_URL 2 +/* There's no USE_URL. */ +#define ENFORCE_SAFE_MODE 4 +#define REPORT_ERRORS 8 +/* If you don't need to write to the stream, but really need to + * be able to seek, use this flag in your options. */ +#define STREAM_MUST_SEEK 16 + +#ifdef PHP_WIN32 +# define IGNORE_URL_WIN IGNORE_URL +#else +# define IGNORE_URL_WIN 0 +#endif + int php_init_stream_wrappers(TSRMLS_D); int php_shutdown_stream_wrappers(TSRMLS_D); PHPAPI int php_register_url_stream_wrapper(char *protocol, php_stream_wrapper *wrapper TSRMLS_DC); PHPAPI int php_unregister_url_stream_wrapper(char *protocol TSRMLS_DC); - PHPAPI php_stream *php_stream_open_wrapper(char *path, char *mode, int options, char **opened_path TSRMLS_DC); + +#define PHP_STREAM_UNCHANGED 0 /* orig stream was seekable anyway */ +#define PHP_STREAM_RELEASED 1 /* newstream should be used; origstream is no longer valid */ +#define PHP_STREAM_FAILED 2 /* an error occurred while attempting conversion */ +#define PHP_STREAM_CRITICAL 3 /* an error occurred; origstream is in an unknown state; you should close origstream */ +/* DO NOT call this on streams that are referenced by resources! */ +PHPAPI int php_stream_make_seekable(php_stream *origstream, php_stream **newstream); #endif Index: php4/main/streams.c diff -u php4/main/streams.c:1.25 php4/main/streams.c:1.26 --- php4/main/streams.c:1.25 Sun Mar 17 07:06:41 2002 +++ php4/main/streams.c Sun Mar 17 09:21:01 2002 @@ -166,7 +166,7 @@ return stream->ops->gets(stream, buf, maxlen); } else { /* unbuffered fgets - poor performance ! */ - size_t n = 0; + size_t n = 1; char *c = buf; /* TODO: look at error returns? */ @@ -944,7 +944,7 @@ goto out; } - if ((options & USE_PATH) && PG(include_path) != NULL) { + if ((options & USE_PATH) && PG(include_path) != NULL) { stream = php_stream_fopen_with_path(path, mode, PG(include_path), opened_path TSRMLS_CC); goto out; } @@ -954,7 +954,29 @@ stream = php_stream_fopen(path, mode, opened_path TSRMLS_CC); out: - if (stream == NULL && (options & REPORT_ERRORS)) { + if (stream != NULL && (options & STREAM_MUST_SEEK)) { + php_stream *newstream; + + switch(php_stream_make_seekable(stream, &newstream)) { + case PHP_STREAM_UNCHANGED: + return stream; + case PHP_STREAM_RELEASED: + return newstream; + default: + php_stream_close(stream); + stream = NULL; + if (options & REPORT_ERRORS) { + char *tmp = estrdup(path); + php_strip_url_passwd(tmp); + zend_error(E_WARNING, "%s(\"%s\") - could not make seekable - %s", + get_active_function_name(TSRMLS_C), tmp, strerror(errno)); + efree(tmp); + + options ^= REPORT_ERRORS; + } + } + } + if (stream == NULL && (options & REPORT_ERRORS)) { char *tmp = estrdup(path); php_strip_url_passwd(tmp); zend_error(E_WARNING, "%s(\"%s\") - %s", get_active_function_name(TSRMLS_C), tmp, strerror(errno)); @@ -963,6 +985,34 @@ return stream; } +PHPAPI int php_stream_make_seekable(php_stream *origstream, php_stream **newstream) +{ + assert(newstream != NULL); + + *newstream = NULL; + + if (origstream->ops->seek != NULL) { + *newstream = origstream; + return PHP_STREAM_UNCHANGED; + } + + /* Use a tmpfile and copy the old streams contents into it */ + + *newstream = php_stream_fopen_tmpfile(); + + if (*newstream == NULL) + return PHP_STREAM_FAILED; + + if (php_stream_copy_to_stream(origstream, *newstream, PHP_STREAM_COPY_ALL) == 0) { + php_stream_close(*newstream); + *newstream = NULL; + return PHP_STREAM_CRITICAL; + } + + php_stream_close(origstream); + + return PHP_STREAM_RELEASED; +} /* * Local variables: