diff options
Diffstat (limited to 'main/streams')
-rw-r--r-- | main/streams/cast.c | 350 | ||||
-rw-r--r-- | main/streams/filter.c | 339 | ||||
-rw-r--r-- | main/streams/memory.c | 473 | ||||
-rw-r--r-- | main/streams/mmap.c | 57 | ||||
-rw-r--r-- | main/streams/php_stream_context.h | 132 | ||||
-rw-r--r-- | main/streams/php_stream_filter_api.h | 143 | ||||
-rw-r--r-- | main/streams/php_stream_mmap.h | 82 | ||||
-rw-r--r-- | main/streams/php_stream_plain_wrapper.h | 61 | ||||
-rw-r--r-- | main/streams/php_stream_transport.h | 188 | ||||
-rw-r--r-- | main/streams/php_stream_userspace.h | 35 | ||||
-rw-r--r-- | main/streams/php_streams_int.h | 61 | ||||
-rw-r--r-- | main/streams/plain_wrapper.c | 1281 | ||||
-rwxr-xr-x | main/streams/streams.c | 1844 | ||||
-rw-r--r-- | main/streams/transports.c | 487 | ||||
-rw-r--r-- | main/streams/userspace.c | 1245 | ||||
-rw-r--r-- | main/streams/xp_socket.c | 751 |
16 files changed, 0 insertions, 7529 deletions
diff --git a/main/streams/cast.c b/main/streams/cast.c deleted file mode 100644 index 1a1d99101c..0000000000 --- a/main/streams/cast.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Wez Furlong <wez@thebrainroom.com> | - +----------------------------------------------------------------------+ - */ - -/* $Id$ */ - -#define _GNU_SOURCE -#include "php.h" -#include "php_globals.h" -#include "php_network.h" -#include "php_open_temporary_file.h" -#include "ext/standard/file.h" -#include <stddef.h> -#include <fcntl.h> - -#include "php_streams_int.h" - -/* Under BSD, emulate fopencookie using funopen */ -#if HAVE_FUNOPEN -typedef struct { - int (*reader)(void *, char *, int); - int (*writer)(void *, const char *, int); - fpos_t (*seeker)(void *, fpos_t, int); - int (*closer)(void *); -} COOKIE_IO_FUNCTIONS_T; - -FILE *fopencookie(void *cookie, const char *mode, COOKIE_IO_FUNCTIONS_T *funcs) -{ - return funopen(cookie, funcs->reader, funcs->writer, funcs->seeker, funcs->closer); -} -# define HAVE_FOPENCOOKIE 1 -# define PHP_STREAM_COOKIE_FUNCTIONS &stream_cookie_functions -#elif HAVE_FOPENCOOKIE -# define PHP_STREAM_COOKIE_FUNCTIONS stream_cookie_functions -#endif - -/* {{{ STDIO with fopencookie */ -#if HAVE_FUNOPEN -/* use our fopencookie emulation */ -static int stream_cookie_reader(void *cookie, char *buffer, int size) -{ - int ret; - TSRMLS_FETCH(); - ret = php_stream_read((php_stream*)cookie, buffer, size); - return ret; -} - -static int stream_cookie_writer(void *cookie, const char *buffer, int size) -{ - TSRMLS_FETCH(); - return php_stream_write((php_stream *)cookie, (char *)buffer, size); -} - -static fpos_t stream_cookie_seeker(void *cookie, off_t position, int whence) -{ - TSRMLS_FETCH(); - return (fpos_t)php_stream_seek((php_stream *)cookie, position, whence); -} - -static int stream_cookie_closer(void *cookie) -{ - php_stream *stream = (php_stream*)cookie; - TSRMLS_FETCH(); - - /* prevent recursion */ - stream->fclose_stdiocast = PHP_STREAM_FCLOSE_NONE; - return php_stream_close(stream); -} - -#elif HAVE_FOPENCOOKIE -static ssize_t stream_cookie_reader(void *cookie, char *buffer, size_t size) -{ - ssize_t ret; - TSRMLS_FETCH(); - ret = php_stream_read(((php_stream *)cookie), buffer, size); - return ret; -} - -static ssize_t stream_cookie_writer(void *cookie, const char *buffer, size_t size) -{ - TSRMLS_FETCH(); - return php_stream_write(((php_stream *)cookie), (char *)buffer, size); -} - -#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, (off_t)*position, whence); - - if (*position == -1) - return -1; - return 0; -} -#else -static int stream_cookie_seeker(void *cookie, off_t position, int whence) -{ - TSRMLS_FETCH(); - return php_stream_seek((php_stream *)cookie, position, whence); -} -#endif - -static int stream_cookie_closer(void *cookie) -{ - php_stream *stream = (php_stream*)cookie; - TSRMLS_FETCH(); - - /* prevent recursion */ - stream->fclose_stdiocast = PHP_STREAM_FCLOSE_NONE; - return php_stream_close(stream); -} -#endif /* elif HAVE_FOPENCOOKIE */ - -#if HAVE_FOPENCOOKIE -static COOKIE_IO_FUNCTIONS_T stream_cookie_functions = -{ - stream_cookie_reader, stream_cookie_writer, - stream_cookie_seeker, stream_cookie_closer -}; -#else -/* TODO: use socketpair() to emulate fopencookie, as suggested by Hartmut ? */ -#endif -/* }}} */ - -/* {{{ php_stream_cast */ -PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show_err TSRMLS_DC) -{ - int flags = castas & PHP_STREAM_CAST_MASK; - castas &= ~PHP_STREAM_CAST_MASK; - - /* synchronize our buffer (if possible) */ - if (ret && castas != PHP_STREAM_AS_FD_FOR_SELECT) { - php_stream_flush(stream); - if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) { - off_t dummy; - - stream->ops->seek(stream, stream->position, SEEK_SET, &dummy TSRMLS_CC); - stream->readpos = stream->writepos = 0; - } - } - - /* filtered streams can only be cast as stdio, and only when fopencookie is present */ - - if (castas == PHP_STREAM_AS_STDIO) { - if (stream->stdiocast) { - if (ret) { - *(FILE**)ret = stream->stdiocast; - } - goto exit_success; - } - - /* if the stream is a stdio stream let's give it a chance to respond - * first, to avoid doubling up the layers of stdio with an fopencookie */ - if (php_stream_is(stream, PHP_STREAM_IS_STDIO) && - stream->ops->cast && - !php_stream_is_filtered(stream) && - stream->ops->cast(stream, castas, ret TSRMLS_CC) == SUCCESS) - { - goto exit_success; - } - -#if HAVE_FOPENCOOKIE - /* if just checking, say yes we can be a FILE*, but don't actually create it yet */ - if (ret == NULL) - goto exit_success; - - *(FILE**)ret = fopencookie(stream, stream->mode, PHP_STREAM_COOKIE_FUNCTIONS); - - if (*ret != NULL) { - off_t pos; - - stream->fclose_stdiocast = PHP_STREAM_FCLOSE_FOPENCOOKIE; - - /* If the stream position is not at the start, we need to force - * the stdio layer to believe it's real location. */ - pos = php_stream_tell(stream); - if (pos > 0) - fseek(*ret, pos, SEEK_SET); - - goto exit_success; - } - - /* must be either: - a) programmer error - b) no memory - -> lets bail - */ - php_error_docref(NULL TSRMLS_CC, E_ERROR, "fopencookie failed"); - return FAILURE; -#endif - - if (!php_stream_is_filtered(stream) && stream->ops->cast && stream->ops->cast(stream, castas, NULL TSRMLS_CC) == SUCCESS) { - if (FAILURE == stream->ops->cast(stream, castas, ret TSRMLS_CC)) { - return FAILURE; - } - goto exit_success; - } else 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 (php_stream_is_filtered(stream)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot cast a filtered stream on this system"); - return FAILURE; - } 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 */ - static const char *cast_names[4] = { - "STDIO FILE*", "File Descriptor", "Socket Descriptor", "select()able descriptor" - }; - - php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot represent a stream of type %s as a %s", - stream->ops->label, - cast_names[castas] - ); - } - - return FAILURE; - -exit_success: - - if ((stream->writepos - stream->readpos) > 0 && - stream->fclose_stdiocast != PHP_STREAM_FCLOSE_FOPENCOOKIE && - (flags & PHP_STREAM_CAST_INTERNAL) == 0) { - /* the data we have buffered will be lost to the third party library that - * will be accessing the stream. Emit a warning so that the end-user will - * know that they should try something else */ - - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "%ld bytes of buffered data lost during stream conversion!", - stream->writepos - stream->readpos); - } - - if (castas == PHP_STREAM_AS_STDIO && ret) - stream->stdiocast = *(FILE**)ret; - - if (flags & PHP_STREAM_CAST_RELEASE) { - php_stream_free(stream, PHP_STREAM_FREE_CLOSE_CASTED); - } - - return SUCCESS; - -} -/* }}} */ - -/* {{{ php_stream_open_wrapper_as_file */ -PHPAPI FILE * _php_stream_open_wrapper_as_file(char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC) -{ - FILE *fp = NULL; - php_stream *stream = NULL; - - stream = php_stream_open_wrapper_rel(path, mode, options|STREAM_WILL_CAST, opened_path); - - if (stream == NULL) - return NULL; - - if (php_stream_cast(stream, PHP_STREAM_AS_STDIO|PHP_STREAM_CAST_TRY_HARD|PHP_STREAM_CAST_RELEASE, - (void**)&fp, REPORT_ERRORS) == FAILURE) - { - php_stream_close(stream); - if (opened_path && *opened_path) - efree(*opened_path); - return NULL; - } - return fp; -} -/* }}} */ - -/* {{{ php_stream_make_seekable */ -PHPAPI int _php_stream_make_seekable(php_stream *origstream, php_stream **newstream, int flags STREAMS_DC TSRMLS_DC) -{ - assert(newstream != NULL); - - *newstream = NULL; - - if (((flags & PHP_STREAM_FORCE_CONVERSION) == 0) && origstream->ops->seek != NULL) { - *newstream = origstream; - return PHP_STREAM_UNCHANGED; - } - - /* Use a tmpfile and copy the old streams contents into it */ - - if (flags & PHP_STREAM_PREFER_STDIO) - *newstream = php_stream_fopen_tmpfile(); - else - *newstream = php_stream_temp_new(); - - 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); - php_stream_seek(*newstream, 0, SEEK_SET); - - return PHP_STREAM_RELEASED; -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/main/streams/filter.c b/main/streams/filter.c deleted file mode 100644 index ff0549972c..0000000000 --- a/main/streams/filter.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Wez Furlong <wez@thebrainroom.com> | - +----------------------------------------------------------------------+ - */ - -/* $Id$ */ - -#include "php.h" -#include "php_globals.h" -#include "php_network.h" -#include "php_open_temporary_file.h" -#include "ext/standard/file.h" -#include <stddef.h> -#include <fcntl.h> - -#include "php_streams_int.h" - -static HashTable stream_filters_hash; - -PHPAPI HashTable *php_get_stream_filters_hash() -{ - return &stream_filters_hash; -} - -PHPAPI int php_stream_filter_register_factory(const char *filterpattern, php_stream_filter_factory *factory TSRMLS_DC) -{ - return zend_hash_add(&stream_filters_hash, (char*)filterpattern, strlen(filterpattern), factory, sizeof(*factory), NULL); -} - -PHPAPI int php_stream_filter_unregister_factory(const char *filterpattern TSRMLS_DC) -{ - return zend_hash_del(&stream_filters_hash, (char*)filterpattern, strlen(filterpattern)); -} - -/* Buckets */ - -PHPAPI php_stream_bucket *php_stream_bucket_new(php_stream *stream, char *buf, size_t buflen, int own_buf, int buf_persistent TSRMLS_DC) -{ - int is_persistent = php_stream_is_persistent(stream); - php_stream_bucket *bucket; - - bucket = (php_stream_bucket*)pemalloc(sizeof(php_stream_bucket), is_persistent); - - if (bucket == NULL) { - return NULL; - } - - bucket->next = bucket->prev = NULL; - - if (is_persistent && !buf_persistent) { - /* all data in a persistent bucket must also be persistent */ - bucket->buf = pemalloc(buflen, 1); - - if (bucket->buf == NULL) { - pefree(bucket, 1); - return NULL; - } - - memcpy(bucket->buf, buf, buflen); - bucket->buflen = buflen; - bucket->own_buf = 1; - } else { - bucket->buf = buf; - bucket->buflen = buflen; - bucket->own_buf = own_buf; - } - bucket->is_persistent = is_persistent; - bucket->refcount = 1; - - return bucket; -} - -/* Given a bucket, returns a version of that bucket with a writeable buffer. - * If the original bucket has a refcount of 1 and owns its buffer, then it - * is returned unchanged. - * Otherwise, a copy of the buffer is made. - * In both cases, the original bucket is unlinked from its brigade. - * If a copy is made, the original bucket is delref'd. - * */ -PHPAPI php_stream_bucket *php_stream_bucket_make_writeable(php_stream_bucket *bucket TSRMLS_DC) -{ - php_stream_bucket *retval; - - php_stream_bucket_unlink(bucket TSRMLS_CC); - - if (bucket->refcount == 1 && bucket->own_buf) { - return bucket; - } - - retval = (php_stream_bucket*)pemalloc(sizeof(php_stream_bucket), bucket->is_persistent); - memcpy(retval, bucket, sizeof(*retval)); - - retval->buf = pemalloc(retval->buflen, retval->is_persistent); - memcpy(retval->buf, bucket->buf, retval->buflen); - - retval->refcount = 1; - retval->own_buf = 1; - - php_stream_bucket_delref(bucket TSRMLS_CC); - - return retval; -} - -PHPAPI int php_stream_bucket_split(php_stream_bucket *in, php_stream_bucket **left, php_stream_bucket **right, size_t length TSRMLS_DC) -{ - *left = (php_stream_bucket*)pecalloc(1, sizeof(php_stream_bucket), in->is_persistent); - *right = (php_stream_bucket*)pecalloc(1, sizeof(php_stream_bucket), in->is_persistent); - - if (*left == NULL || *right == NULL) { - goto exit_fail; - } - - (*left)->buf = pemalloc(length, in->is_persistent); - (*left)->buflen = length; - memcpy((*left)->buf, in->buf, length); - (*left)->refcount = 1; - (*left)->own_buf = 1; - (*left)->is_persistent = in->is_persistent; - - (*right)->buflen = in->buflen - length; - (*right)->buf = pemalloc((*right)->buflen, in->is_persistent); - memcpy((*right)->buf, in->buf + length, (*right)->buflen); - (*right)->refcount = 1; - (*right)->own_buf = 1; - (*right)->is_persistent = in->is_persistent; - - return SUCCESS; - -exit_fail: - if (*right) { - if ((*right)->buf) { - pefree((*right)->buf, in->is_persistent); - } - pefree(*right, in->is_persistent); - } - if (*left) { - if ((*left)->buf) { - pefree((*left)->buf, in->is_persistent); - } - pefree(*left, in->is_persistent); - } - return FAILURE; -} - -PHPAPI void php_stream_bucket_delref(php_stream_bucket *bucket TSRMLS_DC) -{ - if (--bucket->refcount == 0) { - if (bucket->own_buf) { - pefree(bucket->buf, bucket->is_persistent); - } - pefree(bucket, bucket->is_persistent); - } -} - -PHPAPI void php_stream_bucket_prepend(php_stream_bucket_brigade *brigade, php_stream_bucket *bucket TSRMLS_DC) -{ - bucket->next = brigade->head; - bucket->prev = NULL; - - if (brigade->head) { - brigade->head->prev = bucket; - } else { - brigade->tail = bucket; - } - brigade->head = bucket; - bucket->brigade = brigade; -} - -PHPAPI void php_stream_bucket_append(php_stream_bucket_brigade *brigade, php_stream_bucket *bucket TSRMLS_DC) -{ - bucket->prev = brigade->tail; - bucket->next = NULL; - - if (brigade->tail) { - brigade->tail->next = bucket; - } else { - brigade->head = bucket; - } - brigade->tail = bucket; - bucket->brigade = brigade; -} - -PHPAPI void php_stream_bucket_unlink(php_stream_bucket *bucket TSRMLS_DC) -{ - if (bucket->prev) { - bucket->prev->next = bucket->next; - } else { - bucket->brigade->head = bucket->next; - } - if (bucket->next) { - bucket->next->prev = bucket->prev; - } else { - bucket->brigade->tail = bucket->prev; - } - bucket->brigade = NULL; - bucket->next = bucket->prev = NULL; -} - - - - - - - - -/* We allow very simple pattern matching for filter factories: - * if "convert.charset.utf-8/sjis" is requested, we search first for an exact - * match. If that fails, we try "convert.charset.*", then "convert.*" - * This means that we don't need to clog up the hashtable with a zillion - * charsets (for example) but still be able to provide them all as filters */ -PHPAPI php_stream_filter *php_stream_filter_create(const char *filtername, zval *filterparams, int persistent TSRMLS_DC) -{ - php_stream_filter_factory *factory; - php_stream_filter *filter = NULL; - int n; - char *period; - - n = strlen(filtername); - - if (SUCCESS == zend_hash_find(&stream_filters_hash, (char*)filtername, n, (void**)&factory)) { - filter = factory->create_filter(filtername, filterparams, persistent TSRMLS_CC); - } else if ((period = strrchr(filtername, '.'))) { - /* try a wildcard */ - char *wildname; - - wildname = estrdup(filtername); - period = wildname + (period - filtername); - while (period && !filter) { - *period = '\0'; - strcat(wildname, ".*"); - if (SUCCESS == zend_hash_find(&stream_filters_hash, wildname, strlen(wildname), (void**)&factory)) { - filter = factory->create_filter(filtername, filterparams, persistent TSRMLS_CC); - } - - *period = '\0'; - period = strrchr(wildname, '.'); - } - efree(wildname); - } - - if (filter == NULL) { - /* TODO: these need correct docrefs */ - if (factory == NULL) - php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to locate filter \"%s\"", filtername); - else - php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to create or locate filter \"%s\"", filtername); - } - - return filter; -} - -PHPAPI php_stream_filter *_php_stream_filter_alloc(php_stream_filter_ops *fops, void *abstract, int persistent STREAMS_DC TSRMLS_DC) -{ - php_stream_filter *filter; - - filter = (php_stream_filter*) pemalloc_rel_orig(sizeof(php_stream_filter), persistent); - memset(filter, 0, sizeof(php_stream_filter)); - - filter->fops = fops; - filter->abstract = abstract; - filter->is_persistent = persistent; - - return filter; -} - -PHPAPI void php_stream_filter_free(php_stream_filter *filter TSRMLS_DC) -{ - if (filter->fops->dtor) - filter->fops->dtor(filter TSRMLS_CC); - pefree(filter, filter->is_persistent); -} - -PHPAPI void php_stream_filter_prepend(php_stream_filter_chain *chain, php_stream_filter *filter) -{ - filter->next = chain->head; - filter->prev = NULL; - - if (chain->head) { - chain->head->prev = filter; - } else { - chain->tail = filter; - } - chain->head = filter; - filter->chain = chain; -} - -PHPAPI void php_stream_filter_append(php_stream_filter_chain *chain, php_stream_filter *filter) -{ - filter->prev = chain->tail; - filter->next = NULL; - if (chain->tail) { - chain->tail->next = filter; - } else { - chain->head = filter; - } - chain->tail = filter; - filter->chain = chain; -} - -PHPAPI php_stream_filter *php_stream_filter_remove(php_stream_filter *filter, int call_dtor TSRMLS_DC) -{ - if (filter->prev) { - filter->prev->next = filter->next; - } else { - filter->chain->head = filter->next; - } - if (filter->next) { - filter->next->prev = filter->prev; - } else { - filter->chain->tail = filter->prev; - } - if (call_dtor) { - php_stream_filter_free(filter TSRMLS_CC); - return NULL; - } - return filter; -} - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/main/streams/memory.c b/main/streams/memory.c deleted file mode 100644 index a61bd6619e..0000000000 --- a/main/streams/memory.c +++ /dev/null @@ -1,473 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Marcus Boerger <helly@php.net> | - +----------------------------------------------------------------------+ - */ - -/* $Id$ */ - -#define _GNU_SOURCE -#include "php.h" - -/* Memory streams use a dynamic memory buffer to emulate a stream. - * You can use php_stream_memory_open to create a readonly stream - * from an existing memory buffer. - */ - -/* Temp streams are streams that uses memory streams as long their - * size is less than a given memory amount. When a write operation - * exceeds that limit the content is written to a temporary file. - */ - -/* {{{ ------- MEMORY stream implementation -------*/ - -typedef struct { - char *data; - size_t fpos; - size_t fsize; - size_t smax; - int mode; -} php_stream_memory_data; - - -/* {{{ */ -static size_t php_stream_memory_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) -{ - php_stream_memory_data *ms; - - assert(stream != NULL); - ms = stream->abstract; - assert(ms != NULL); - - if (ms->mode & TEMP_STREAM_READONLY) { - return 0; - } - if (ms->fpos + count > ms->fsize) { - char *tmp; - - if (!ms->data) { - tmp = emalloc(ms->fpos + count); - } else { - tmp = erealloc(ms->data, ms->fpos + count); - } - if (!tmp) { - count = ms->fsize - ms->fpos + 1; - } else { - ms->data = tmp; - ms->fsize = ms->fpos + count; - } - } - if (!ms->data) - count = 0; - if (count) { - assert(buf!= NULL); - memcpy(ms->data+ms->fpos, (char*)buf, count); - ms->fpos += count; - } - return count; -} -/* }}} */ - - -/* {{{ */ -static size_t php_stream_memory_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) -{ - php_stream_memory_data *ms; - - assert(stream != NULL); - ms = stream->abstract; - assert(ms != NULL); - - if (ms->fpos + count > ms->fsize) { - count = ms->fsize - ms->fpos; - } - if (count) { - assert(ms->data!= NULL); - assert(buf!= NULL); - memcpy(buf, ms->data+ms->fpos, count); - ms->fpos += count; - } else { - stream->eof = 1; - } - return count; -} -/* }}} */ - - -/* {{{ */ -static int php_stream_memory_close(php_stream *stream, int close_handle TSRMLS_DC) -{ - php_stream_memory_data *ms; - - assert(stream != NULL); - ms = stream->abstract; - assert(ms != NULL); - - if (ms->data && close_handle && ms->mode != TEMP_STREAM_READONLY) { - efree(ms->data); - } - efree(ms); - return 0; -} -/* }}} */ - - -/* {{{ */ -static int php_stream_memory_flush(php_stream *stream TSRMLS_DC) -{ - /* nothing to do here */ - return 0; -} -/* }}} */ - - -/* {{{ */ -static int php_stream_memory_seek(php_stream *stream, off_t offset, int whence, off_t *newoffs TSRMLS_DC) -{ - php_stream_memory_data *ms; - - assert(stream != NULL); - ms = stream->abstract; - assert(ms != NULL); - - switch(whence) { - case SEEK_CUR: - if (offset < 0) { - if (ms->fpos < (size_t)(-offset)) { - ms->fpos = 0; - /*return EINVAL;*/ - } else { - ms->fpos = ms->fpos + offset; - } - } else { - if (ms->fpos < (size_t)(offset)) { - ms->fpos = ms->fsize; - /*return EINVAL;*/ - } else { - ms->fpos = ms->fpos + offset; - } - } - *newoffs = ms->fpos; - return 0; - case SEEK_SET: - if (ms->fsize < (size_t)(offset)) { - ms->fpos = ms->fsize; - /*return EINVAL;*/ - } else { - ms->fpos = offset; - } - *newoffs = ms->fpos; - return 0; - case SEEK_END: - if (offset > 0) { - ms->fpos = ms->fsize; - /*return EINVAL;*/ - } else if (ms->fpos < (size_t)(-offset)) { - ms->fpos = 0; - /*return EINVAL;*/ - } else { - ms->fpos = ms->fsize + offset; - } - *newoffs = ms->fpos; - return 0; - default: - return 0; - /*return EINVAL;*/ - } -} -/* }}} */ - -/* {{{ */ -static int php_stream_memory_cast(php_stream *stream, int castas, void **ret TSRMLS_DC) -{ - return FAILURE; -} -/* }}} */ - - -php_stream_ops php_stream_memory_ops = { - php_stream_memory_write, php_stream_memory_read, - php_stream_memory_close, php_stream_memory_flush, - "MEMORY", - php_stream_memory_seek, - php_stream_memory_cast, - NULL, /* stat */ - NULL /* set_option */ -}; - - -/* {{{ */ -PHPAPI php_stream *_php_stream_memory_create(int mode STREAMS_DC TSRMLS_DC) -{ - php_stream_memory_data *self; - php_stream *stream; - - self = emalloc(sizeof(*self)); - self->data = NULL; - self->fpos = 0; - self->fsize = 0; - self->smax = -1; - self->mode = mode; - - stream = php_stream_alloc(&php_stream_memory_ops, self, 0, "r+b"); - stream->flags |= PHP_STREAM_FLAG_NO_BUFFER; - return stream; -} -/* }}} */ - - -/* {{{ */ -PHPAPI php_stream *_php_stream_memory_open(int mode, char *buf, size_t length STREAMS_DC TSRMLS_DC) -{ - php_stream *stream; - php_stream_memory_data *ms; - - if ((stream = php_stream_memory_create_rel(mode)) != NULL) { - ms = stream->abstract; - - if (mode == TEMP_STREAM_READONLY) { - /* use the buffer directly */ - ms->data = buf; - ms->fsize = length; - } else { - if (length) { - assert(buf != NULL); - php_stream_write(stream, buf, length); - } - } - } - return stream; -} -/* }}} */ - - -/* {{{ */ -PHPAPI char *_php_stream_memory_get_buffer(php_stream *stream, size_t *length STREAMS_DC TSRMLS_DC) -{ - php_stream_memory_data *ms; - - assert(stream != NULL); - ms = stream->abstract; - assert(ms != NULL); - assert(length != 0); - - *length = ms->fsize; - return ms->data; -} -/* }}} */ - -/* }}} */ - -/* {{{ ------- TEMP stream implementation -------*/ - -typedef struct { - php_stream *innerstream; - size_t smax; - int mode; -} php_stream_temp_data; - - -/* {{{ */ -static size_t php_stream_temp_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) -{ - php_stream_temp_data *ts; - - assert(stream != NULL); - ts = stream->abstract; - assert(ts != NULL); - - if (php_stream_is(ts->innerstream, PHP_STREAM_IS_MEMORY)) { - size_t memsize; - char *membuf = php_stream_memory_get_buffer(ts->innerstream, &memsize); - - if (memsize + count >= ts->smax) { - php_stream *file = php_stream_fopen_tmpfile(); - php_stream_write(file, membuf, memsize); - php_stream_close(ts->innerstream); - ts->innerstream = file; - } - } - return php_stream_write(ts->innerstream, buf, count); -} -/* }}} */ - - -/* {{{ */ -static size_t php_stream_temp_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) -{ - php_stream_temp_data *ts; - - assert(stream != NULL); - ts = stream->abstract; - assert(ts != NULL); - - return php_stream_read(ts->innerstream, buf, count); -} -/* }}} */ - - -/* {{{ */ -static int php_stream_temp_close(php_stream *stream, int close_handle TSRMLS_DC) -{ - php_stream_temp_data *ts; - int ret; - - assert(stream != NULL); - ts = stream->abstract; - assert(ts != NULL); - - ret = php_stream_free(ts->innerstream, PHP_STREAM_FREE_CLOSE | (close_handle ? 0 : PHP_STREAM_FREE_PRESERVE_HANDLE)); - - efree(ts); - - return ret; -} -/* }}} */ - - -/* {{{ */ -static int php_stream_temp_flush(php_stream *stream TSRMLS_DC) -{ - php_stream_temp_data *ts; - - assert(stream != NULL); - ts = stream->abstract; - assert(ts != NULL); - - return php_stream_flush(ts->innerstream); -} -/* }}} */ - - -/* {{{ */ -static int php_stream_temp_seek(php_stream *stream, off_t offset, int whence, off_t *newoffs TSRMLS_DC) -{ - php_stream_temp_data *ts; - int ret; - - assert(stream != NULL); - ts = stream->abstract; - assert(ts != NULL); - - ret = php_stream_seek(ts->innerstream, offset, whence); - *newoffs = php_stream_tell(ts->innerstream); - - return ret; -} -/* }}} */ - -/* {{{ */ -static int php_stream_temp_cast(php_stream *stream, int castas, void **ret TSRMLS_DC) -{ - php_stream_temp_data *ts; - php_stream *file; - size_t memsize; - char *membuf; - off_t pos; - - assert(stream != NULL); - ts = stream->abstract; - assert(ts != NULL); - - if (php_stream_is(ts->innerstream, PHP_STREAM_IS_STDIO)) { - return php_stream_cast(ts->innerstream, castas, ret, 0); - } - - /* we are still using a memory based backing. If they are if we can be - * a FILE*, say yes because we can perform the conversion. - * If they actually want to perform the conversion, we need to switch - * the memory stream to a tmpfile stream */ - - if (ret == NULL && castas == PHP_STREAM_AS_STDIO) { - return SUCCESS; - } - - /* say "no" to other stream forms */ - if (ret == NULL) { - return FAILURE; - } - - /* perform the conversion and then pass the request on to the innerstream */ - membuf = php_stream_memory_get_buffer(ts->innerstream, &memsize); - file = php_stream_fopen_tmpfile(); - php_stream_write(file, membuf, memsize); - pos = php_stream_tell(ts->innerstream); - - php_stream_close(ts->innerstream); - ts->innerstream = file; - php_stream_seek(ts->innerstream, pos, SEEK_SET); - - return php_stream_cast(ts->innerstream, castas, ret, 1); -} -/* }}} */ - -php_stream_ops php_stream_temp_ops = { - php_stream_temp_write, php_stream_temp_read, - php_stream_temp_close, php_stream_temp_flush, - "TEMP", - php_stream_temp_seek, - php_stream_temp_cast, - NULL, /* stat */ - NULL /* set_option */ -}; - -/* }}} */ - -/* {{{ _php_stream_temp_create */ -PHPAPI php_stream *_php_stream_temp_create(int mode, size_t max_memory_usage STREAMS_DC TSRMLS_DC) -{ - php_stream_temp_data *self; - php_stream *stream; - - self = ecalloc(1, sizeof(*self)); - self->smax = max_memory_usage; - self->mode = mode; - stream = php_stream_alloc(&php_stream_temp_ops, self, 0, "r+b"); - stream->flags |= PHP_STREAM_FLAG_NO_BUFFER; - self->innerstream = php_stream_memory_create(mode); - - return stream; -} -/* }}} */ - - -/* {{{ _php_stream_temp_open */ -PHPAPI php_stream *_php_stream_temp_open(int mode, size_t max_memory_usage, char *buf, size_t length STREAMS_DC TSRMLS_DC) -{ - php_stream *stream; - php_stream_temp_data *ms; - - if ((stream = php_stream_temp_create_rel(mode & ~TEMP_STREAM_READONLY, max_memory_usage)) != NULL) { - if (length) { - assert(buf != NULL); - php_stream_temp_write(stream, buf, length TSRMLS_CC); - } - ms = stream->abstract; - assert(ms != NULL); - ms->mode = mode; - } - return stream; -} -/* }}} */ - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/main/streams/mmap.c b/main/streams/mmap.c deleted file mode 100644 index 443faf384d..0000000000 --- a/main/streams/mmap.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong <wez@thebrainroom.com> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -/* Memory Mapping interface for streams */ -#include "php.h" -#include "php_streams_int.h" - -PHPAPI char *_php_stream_mmap_range(php_stream *stream, size_t offset, size_t length, php_stream_mmap_operation_t mode, size_t *mapped_len TSRMLS_DC) -{ - php_stream_mmap_range range; - - range.offset = offset; - range.length = length; - range.mode = mode; - range.mapped = NULL; - - /* TODO: Enforce system policy and limits for mmap sizes ? */ - - if (PHP_STREAM_OPTION_RETURN_OK == php_stream_set_option(stream, PHP_STREAM_OPTION_MMAP_API, PHP_STREAM_MMAP_MAP_RANGE, &range)) { - if (mapped_len) { - *mapped_len = range.length; - } - return range.mapped; - } - return NULL; -} - -PHPAPI int _php_stream_mmap_unmap(php_stream *stream TSRMLS_DC) -{ - return php_stream_set_option(stream, PHP_STREAM_OPTION_MMAP_API, PHP_STREAM_MMAP_UNMAP, NULL) == PHP_STREAM_OPTION_RETURN_OK ? 1 : 0; -} - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/main/streams/php_stream_context.h b/main/streams/php_stream_context.h deleted file mode 100644 index eb8b404cfb..0000000000 --- a/main/streams/php_stream_context.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong <wez@thebrainroom.com> | - +----------------------------------------------------------------------+ - */ - -/* $Id$ */ - -/* Stream context and status notification related definitions */ - -/* callback for status notifications */ -typedef void (*php_stream_notification_func)(php_stream_context *context, - int notifycode, int severity, - char *xmsg, int xcode, - size_t bytes_sofar, size_t bytes_max, - void * ptr TSRMLS_DC); - -#define PHP_STREAM_NOTIFIER_PROGRESS 1 - -/* Attempt to fetch context from the zval passed, - If no context was passed, use the default context - The the default context has not yet been created, do it now. */ -#define php_stream_context_from_zval(zcontext, nocontext) ( \ - (zcontext) ? zend_fetch_resource(&(zcontext) TSRMLS_CC, -1, "Stream-Context", NULL, 1, php_le_stream_context()) : \ - (nocontext) ? NULL : \ - FG(default_context) ? FG(default_context) : \ - (FG(default_context) = php_stream_context_alloc()) ) - -#define php_stream_context_to_zval(context, zval) { ZVAL_RESOURCE(zval, (context)->rsrc_id); } - -typedef struct _php_stream_notifier php_stream_notifier; - -struct _php_stream_notifier { - php_stream_notification_func func; - void (*dtor)(php_stream_notifier *notifier); - void *ptr; - int mask; - size_t progress, progress_max; /* position for progress notification */ -}; - -struct _php_stream_context { - php_stream_notifier *notifier; - zval *options; /* hash keyed by wrapper family or specific wrapper */ - zval *links; /* hash keyed by hostent for connection pooling */ - int rsrc_id; /* used for auto-cleanup */ -}; - -PHPAPI void php_stream_context_free(php_stream_context *context); -PHPAPI php_stream_context *php_stream_context_alloc(void); -PHPAPI int php_stream_context_get_option(php_stream_context *context, - const char *wrappername, const char *optionname, zval ***optionvalue); -PHPAPI int php_stream_context_set_option(php_stream_context *context, - const char *wrappername, const char *optionname, zval *optionvalue); - -PHPAPI int php_stream_context_get_link(php_stream_context *context, - const char *hostent, php_stream **stream); -PHPAPI int php_stream_context_set_link(php_stream_context *context, - const char *hostent, php_stream *stream); -PHPAPI int php_stream_context_del_link(php_stream_context *context, - php_stream *stream); - -PHPAPI php_stream_notifier *php_stream_notification_alloc(void); -PHPAPI void php_stream_notification_free(php_stream_notifier *notifier); - -/* not all notification codes are implemented */ -#define PHP_STREAM_NOTIFY_RESOLVE 1 -#define PHP_STREAM_NOTIFY_CONNECT 2 -#define PHP_STREAM_NOTIFY_AUTH_REQUIRED 3 -#define PHP_STREAM_NOTIFY_MIME_TYPE_IS 4 -#define PHP_STREAM_NOTIFY_FILE_SIZE_IS 5 -#define PHP_STREAM_NOTIFY_REDIRECTED 6 -#define PHP_STREAM_NOTIFY_PROGRESS 7 -#define PHP_STREAM_NOTIFY_COMPLETED 8 -#define PHP_STREAM_NOTIFY_FAILURE 9 -#define PHP_STREAM_NOTIFY_AUTH_RESULT 10 - -#define PHP_STREAM_NOTIFY_SEVERITY_INFO 0 -#define PHP_STREAM_NOTIFY_SEVERITY_WARN 1 -#define PHP_STREAM_NOTIFY_SEVERITY_ERR 2 - -PHPAPI void php_stream_notification_notify(php_stream_context *context, int notifycode, int severity, - char *xmsg, int xcode, size_t bytes_sofar, size_t bytes_max, void * ptr TSRMLS_DC); -PHPAPI php_stream_context *php_stream_context_set(php_stream *stream, php_stream_context *context); - -#define php_stream_notify_info(context, code, xmsg, xcode) do { if ((context) && (context)->notifier) { \ - php_stream_notification_notify((context), (code), PHP_STREAM_NOTIFY_SEVERITY_INFO, \ - (xmsg), (xcode), 0, 0, NULL TSRMLS_CC); } } while (0) - -#define php_stream_notify_progress(context, bsofar, bmax) do { if ((context) && (context)->notifier) { \ - php_stream_notification_notify((context), PHP_STREAM_NOTIFY_PROGRESS, PHP_STREAM_NOTIFY_SEVERITY_INFO, \ - NULL, 0, (bsofar), (bmax), NULL TSRMLS_CC); } } while(0) - -#define php_stream_notify_progress_init(context, sofar, bmax) do { if ((context) && (context)->notifier) { \ - (context)->notifier->progress = (sofar); \ - (context)->notifier->progress_max = (bmax); \ - (context)->notifier->mask |= PHP_STREAM_NOTIFIER_PROGRESS; \ - php_stream_notify_progress((context), (sofar), (bmax)); } } while (0) - -#define php_stream_notify_progress_increment(context, dsofar, dmax) do { if ((context) && (context)->notifier && (context)->notifier->mask & PHP_STREAM_NOTIFIER_PROGRESS) { \ - (context)->notifier->progress += (dsofar); \ - (context)->notifier->progress_max += (dmax); \ - php_stream_notify_progress((context), (context)->notifier->progress, (context)->notifier->progress_max); } } while (0) - -#define php_stream_notify_file_size(context, file_size, xmsg, xcode) do { if ((context) && (context)->notifier) { \ - php_stream_notification_notify((context), PHP_STREAM_NOTIFY_FILE_SIZE_IS, PHP_STREAM_NOTIFY_SEVERITY_INFO, \ - (xmsg), (xcode), 0, (file_size), NULL TSRMLS_CC); } } while(0) - -#define php_stream_notify_error(context, code, xmsg, xcode) do { if ((context) && (context)->notifier) {\ - php_stream_notification_notify((context), (code), PHP_STREAM_NOTIFY_SEVERITY_ERR, \ - (xmsg), (xcode), 0, 0, NULL TSRMLS_CC); } } while(0) - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/main/streams/php_stream_filter_api.h b/main/streams/php_stream_filter_api.h deleted file mode 100644 index b5b129e968..0000000000 --- a/main/streams/php_stream_filter_api.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong <wez@thebrainroom.com> | - | With suggestions from: | - | Moriyoshi Koizumi <moriyoshi@at.wakwak.com> | - | Sara Golemon <pollita@php.net> | - +----------------------------------------------------------------------+ - */ - -/* $Id$ */ - -/* The filter API works on the principle of "Bucket-Brigades". This is - * partially inspired by the Apache 2 method of doing things, although - * it is intentially a light-weight implementation. - * - * Each stream can have a chain of filters for reading and another for writing. - * - * When data is written to the stream, is is placed into a bucket and placed at - * the start of the input brigade. - * - * The first filter in the chain is invoked on the brigade and (depending on - * it's return value), the next filter is invoked and so on. - * */ - -#define PHP_STREAM_FILTER_READ 0x0001 -#define PHP_STREAM_FILTER_WRITE 0x0002 -#define PHP_STREAM_FILTER_ALL (PHP_STREAM_FILTER_READ | PHP_STREAM_FILTER_WRITE) - -typedef struct _php_stream_bucket php_stream_bucket; -typedef struct _php_stream_bucket_brigade php_stream_bucket_brigade; - -struct _php_stream_bucket { - php_stream_bucket *next, *prev; - php_stream_bucket_brigade *brigade; - - char *buf; - size_t buflen; - /* if non-zero, buf should be pefreed when the bucket is destroyed */ - int own_buf; - int is_persistent; - - /* destroy this struct when refcount falls to zero */ - int refcount; -}; - -struct _php_stream_bucket_brigade { - php_stream_bucket *head, *tail; -}; - -typedef enum { - PSFS_ERR_FATAL, /* error in data stream */ - PSFS_FEED_ME, /* filter needs more data; stop processing chain until more is available */ - PSFS_PASS_ON, /* filter generated output buckets; pass them on to next in chain */ -} php_stream_filter_status_t; - -/* Buckets API. */ -PHPAPI php_stream_bucket *php_stream_bucket_new(php_stream *stream, char *buf, size_t buflen, int own_buf, int buf_persistent TSRMLS_DC); -PHPAPI int php_stream_bucket_split(php_stream_bucket *in, php_stream_bucket **left, php_stream_bucket **right, size_t length TSRMLS_DC); -PHPAPI void php_stream_bucket_delref(php_stream_bucket *bucket TSRMLS_DC); -#define php_stream_bucket_addref(bucket) (bucket)->refcount++ -PHPAPI void php_stream_bucket_prepend(php_stream_bucket_brigade *brigade, php_stream_bucket *bucket TSRMLS_DC); -PHPAPI void php_stream_bucket_append(php_stream_bucket_brigade *brigade, php_stream_bucket *bucket TSRMLS_DC); -PHPAPI void php_stream_bucket_unlink(php_stream_bucket *bucket TSRMLS_DC); -PHPAPI php_stream_bucket *php_stream_bucket_make_writeable(php_stream_bucket *bucket TSRMLS_DC); - -#define PSFS_FLAG_NORMAL 0 /* regular read/write */ -#define PSFS_FLAG_FLUSH_INC 1 /* an incremental flush */ -#define PSFS_FLAG_FLUSH_CLOSE 2 /* final flush prior to closing */ - -typedef struct _php_stream_filter_ops { - - php_stream_filter_status_t (*filter)( - php_stream *stream, - php_stream_filter *thisfilter, - php_stream_bucket_brigade *buckets_in, - php_stream_bucket_brigade *buckets_out, - size_t *bytes_consumed, - int flags - TSRMLS_DC); - - void (*dtor)(php_stream_filter *thisfilter TSRMLS_DC); - - const char *label; - -} php_stream_filter_ops; - -typedef struct _php_stream_filter_chain { - php_stream_filter *head, *tail; -} php_stream_filter_chain; - -struct _php_stream_filter { - php_stream_filter_ops *fops; - void *abstract; /* for use by filter implementation */ - php_stream_filter *next; - php_stream_filter *prev; - int is_persistent; - - /* link into stream and chain */ - php_stream_filter_chain *chain; - - /* buffered buckets */ - php_stream_bucket_brigade buffer; -}; - -/* stack filter onto a stream */ -PHPAPI void php_stream_filter_prepend(php_stream_filter_chain *chain, php_stream_filter *filter); -PHPAPI void php_stream_filter_append(php_stream_filter_chain *chain, php_stream_filter *filter); -PHPAPI php_stream_filter *php_stream_filter_remove(php_stream_filter *filter, int call_dtor TSRMLS_DC); -PHPAPI void php_stream_filter_free(php_stream_filter *filter TSRMLS_DC); -PHPAPI php_stream_filter *_php_stream_filter_alloc(php_stream_filter_ops *fops, void *abstract, int persistent STREAMS_DC TSRMLS_DC); -#define php_stream_filter_alloc(fops, thisptr, persistent) _php_stream_filter_alloc((fops), (thisptr), (persistent) STREAMS_CC TSRMLS_CC) -#define php_stream_filter_alloc_rel(fops, thisptr, persistent) _php_stream_filter_alloc((fops), (thisptr), (persistent) STREAMS_REL_CC TSRMLS_CC) - -#define php_stream_is_filtered(stream) ((stream)->readfilters.head || (stream)->writefilters.head) - -typedef struct _php_stream_filter_factory { - php_stream_filter *(*create_filter)(const char *filtername, zval *filterparams, int persistent TSRMLS_DC); -} php_stream_filter_factory; - -PHPAPI int php_stream_filter_register_factory(const char *filterpattern, php_stream_filter_factory *factory TSRMLS_DC); -PHPAPI int php_stream_filter_unregister_factory(const char *filterpattern TSRMLS_DC); -PHPAPI php_stream_filter *php_stream_filter_create(const char *filtername, zval *filterparams, int persistent TSRMLS_DC); - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/main/streams/php_stream_mmap.h b/main/streams/php_stream_mmap.h deleted file mode 100644 index 024eb7c6d2..0000000000 --- a/main/streams/php_stream_mmap.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong <wez@thebrainroom.com> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -/* Memory Mapping interface for streams. - * The intention is to provide a uniform interface over the most common - * operations that are used within PHP itself, rather than a complete - * API for all memory mapping needs. - * - * ATM, we support only mmap(), but win32 memory mapping support will - * follow soon. - * */ - -typedef enum { - /* Does the stream support mmap ? */ - PHP_STREAM_MMAP_SUPPORTED, - /* Request a range and offset to be mapped; - * while mapped, you MUST NOT use any read/write functions - * on the stream (win9x compatibility) */ - PHP_STREAM_MMAP_MAP_RANGE, - /* Unmap the last range that was mapped for the stream */ - PHP_STREAM_MMAP_UNMAP -} php_stream_mmap_operation_t; - -typedef enum { - PHP_STREAM_MAP_MODE_READONLY, - PHP_STREAM_MAP_MODE_READWRITE, - PHP_STREAM_MAP_MODE_SHARED_READONLY, - PHP_STREAM_MAP_MODE_SHARED_READWRITE -} php_stream_mmap_access_t; - -typedef struct { - /* requested offset and length. - * If length is 0, the whole file is mapped */ - size_t offset; - size_t length; - - php_stream_mmap_access_t mode; - - /* returned mapped address */ - char *mapped; - -} php_stream_mmap_range; - -#define php_stream_mmap_supported(stream) (_php_stream_set_option((stream), PHP_STREAM_OPTION_MMAP_API, PHP_STREAM_MMAP_SUPPORTED, NULL TSRMLS_CC) == 0 ? 1 : 0) - -/* Returns 1 if the stream in its current state can be memory mapped, - * 0 otherwise */ -#define php_stream_mmap_possible(stream) (!php_stream_is_filtered((stream)) && php_stream_mmap_supported((stream))) - -PHPAPI char *_php_stream_mmap_range(php_stream *stream, size_t offset, size_t length, php_stream_mmap_operation_t mode, size_t *mapped_len TSRMLS_DC); -#define php_stream_mmap_range(stream, offset, length, mode, mapped_len) _php_stream_mmap_range((stream), (offset), (length), (mode), (mapped_len) TSRMLS_CC) - -/* un-maps the last mapped range */ -PHPAPI int _php_stream_mmap_unmap(php_stream *stream TSRMLS_DC); -#define php_stream_mmap_unmap(stream) _php_stream_mmap_unmap((stream) TSRMLS_CC) - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/main/streams/php_stream_plain_wrapper.h b/main/streams/php_stream_plain_wrapper.h deleted file mode 100644 index 9a23527532..0000000000 --- a/main/streams/php_stream_plain_wrapper.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong <wez@thebrainroom.com> | - +----------------------------------------------------------------------+ - */ - -/* $Id$ */ - -/* definitions for the plain files wrapper */ - -/* operations for a plain file; use the php_stream_fopen_XXX funcs below */ -PHPAPI extern php_stream_ops php_stream_stdio_ops; - -/* like fopen, but returns a stream */ -PHPAPI php_stream *_php_stream_fopen(const char *filename, const char *mode, char **opened_path, int options STREAMS_DC TSRMLS_DC); -#define php_stream_fopen(filename, mode, opened) _php_stream_fopen((filename), (mode), (opened), 0 STREAMS_CC TSRMLS_CC) - -PHPAPI php_stream *_php_stream_fopen_with_path(char *filename, char *mode, char *path, char **opened_path, int options STREAMS_DC TSRMLS_DC); -#define php_stream_fopen_with_path(filename, mode, path, opened) _php_stream_fopen_with_path((filename), (mode), (path), (opened) STREAMS_CC TSRMLS_CC) - -PHPAPI php_stream *_php_stream_fopen_from_file(FILE *file, const char *mode STREAMS_DC TSRMLS_DC); -#define php_stream_fopen_from_file(file, mode) _php_stream_fopen_from_file((file), (mode) STREAMS_CC TSRMLS_CC) - -PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const char *persistent_id STREAMS_DC TSRMLS_DC); -#define php_stream_fopen_from_fd(fd, mode, persistent_id) _php_stream_fopen_from_fd((fd), (mode), (persistent_id) STREAMS_CC TSRMLS_CC) - -PHPAPI php_stream *_php_stream_fopen_from_pipe(FILE *file, const char *mode STREAMS_DC TSRMLS_DC); -#define php_stream_fopen_from_pipe(file, mode) _php_stream_fopen_from_pipe((file), (mode) STREAMS_CC TSRMLS_CC) - -PHPAPI php_stream *_php_stream_fopen_tmpfile(int dummy STREAMS_DC TSRMLS_DC); -#define php_stream_fopen_tmpfile() _php_stream_fopen_tmpfile(0 STREAMS_CC TSRMLS_CC) - -PHPAPI php_stream *_php_stream_fopen_temporary_file(const char *dir, const char *pfx, char **opened_path STREAMS_DC TSRMLS_DC); -#define php_stream_fopen_temporary_file(dir, pfx, opened_path) _php_stream_fopen_temporary_file((dir), (pfx), (opened_path) STREAMS_CC TSRMLS_CC) - -/* This is a utility API for extensions that are opening a stream, converting it - * to a FILE* and then closing it again. Be warned that fileno() on the result - * will most likely fail on systems with fopencookie. */ -PHPAPI FILE * _php_stream_open_wrapper_as_file(char * path, char * mode, int options, char **opened_path STREAMS_DC TSRMLS_DC); -#define php_stream_open_wrapper_as_file(path, mode, options, opened_path) _php_stream_open_wrapper_as_file((path), (mode), (options), (opened_path) STREAMS_CC TSRMLS_CC) - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/main/streams/php_stream_transport.h b/main/streams/php_stream_transport.h deleted file mode 100644 index d1fbb273f1..0000000000 --- a/main/streams/php_stream_transport.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong <wez@thebrainroom.com> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#if HAVE_SYS_SOCKET_H -# include <sys/socket.h> -#endif - -typedef php_stream *(php_stream_transport_factory_func)(const char *proto, long protolen, - char *resourcename, long resourcenamelen, - const char *persistent_id, int options, int flags, - struct timeval *timeout, - php_stream_context *context STREAMS_DC TSRMLS_DC); -typedef php_stream_transport_factory_func *php_stream_transport_factory; - -PHPAPI int php_stream_xport_register(char *protocol, php_stream_transport_factory factory TSRMLS_DC); -PHPAPI int php_stream_xport_unregister(char *protocol TSRMLS_DC); - -#define STREAM_XPORT_CLIENT 0 -#define STREAM_XPORT_SERVER 1 - -#define STREAM_XPORT_CONNECT 2 -#define STREAM_XPORT_BIND 4 -#define STREAM_XPORT_LISTEN 8 -#define STREAM_XPORT_CONNECT_ASYNC 16 - -/* Open a client or server socket connection */ -PHPAPI php_stream *_php_stream_xport_create(const char *name, long namelen, int options, - int flags, const char *persistent_id, - struct timeval *timeout, - php_stream_context *context, - char **error_string, - int *error_code - STREAMS_DC TSRMLS_DC); - -#define php_stream_xport_create(name, namelen, options, flags, persistent_id, timeout, context, estr, ecode) \ - _php_stream_xport_create(name, namelen, options, flags, persistent_id, timeout, context, estr, ecode STREAMS_CC TSRMLS_CC) - -/* Bind the stream to a local address */ -PHPAPI int php_stream_xport_bind(php_stream *stream, - const char *name, long namelen, - char **error_text - TSRMLS_DC); - -/* Connect to a remote address */ -PHPAPI int php_stream_xport_connect(php_stream *stream, - const char *name, long namelen, - int asynchronous, - struct timeval *timeout, - char **error_text, - int *error_code - TSRMLS_DC); - -/* Prepare to listen */ -PHPAPI int php_stream_xport_listen(php_stream *stream, - int backlog, - char **error_text - TSRMLS_DC); - -/* Get the next client and their address as a string, or the underlying address - * structure. You must efree either of these if you request them */ -PHPAPI int php_stream_xport_accept(php_stream *stream, php_stream **client, - char **textaddr, int *textaddrlen, - void **addr, socklen_t *addrlen, - struct timeval *timeout, - char **error_text - TSRMLS_DC); - -/* Get the name of either the socket or it's peer */ -PHPAPI int php_stream_xport_get_name(php_stream *stream, int want_peer, - char **textaddr, int *textaddrlen, - void **addr, socklen_t *addrlen - TSRMLS_DC); - -enum php_stream_xport_send_recv_flags { - STREAM_OOB = 1, - STREAM_PEEK = 2 -}; - -/* Similar to recv() system call; read data from the stream, optionally - * peeking, optionally retrieving OOB data */ -PHPAPI int php_stream_xport_recvfrom(php_stream *stream, char *buf, size_t buflen, - long flags, void **addr, socklen_t *addrlen, - char **textaddr, int *textaddrlen TSRMLS_DC); - -/* Similar to send() system call; send data to the stream, optionally - * sending it as OOB data */ -PHPAPI int php_stream_xport_sendto(php_stream *stream, const char *buf, size_t buflen, - long flags, void *addr, socklen_t addrlen TSRMLS_DC); - -/* Structure definition for the set_option interface that the above functions wrap */ - -typedef struct _php_stream_xport_param { - enum { - STREAM_XPORT_OP_BIND, STREAM_XPORT_OP_CONNECT, - STREAM_XPORT_OP_LISTEN, STREAM_XPORT_OP_ACCEPT, - STREAM_XPORT_OP_CONNECT_ASYNC, - STREAM_XPORT_OP_GET_NAME, - STREAM_XPORT_OP_GET_PEER_NAME, - STREAM_XPORT_OP_RECV, - STREAM_XPORT_OP_SEND - } op; - unsigned int want_addr:1; - unsigned int want_textaddr:1; - unsigned int want_errortext:1; - - struct { - char *name; - long namelen; - int backlog; - struct timeval *timeout; - struct sockaddr *addr; - socklen_t addrlen; - char *buf; - size_t buflen; - long flags; - } inputs; - struct { - php_stream *client; - int returncode; - struct sockaddr *addr; - socklen_t addrlen; - char *textaddr; - long textaddrlen; - - char *error_text; - int error_code; - } outputs; -} php_stream_xport_param; - - -/* These functions provide crypto support on the underlying transport */ -typedef enum { - STREAM_CRYPTO_METHOD_SSLv2_CLIENT, - STREAM_CRYPTO_METHOD_SSLv3_CLIENT, - STREAM_CRYPTO_METHOD_SSLv23_CLIENT, - STREAM_CRYPTO_METHOD_TLS_CLIENT, - STREAM_CRYPTO_METHOD_SSLv2_SERVER, - STREAM_CRYPTO_METHOD_SSLv3_SERVER, - STREAM_CRYPTO_METHOD_SSLv23_SERVER, - STREAM_CRYPTO_METHOD_TLS_SERVER -} php_stream_xport_crypt_method_t; - -PHPAPI int php_stream_xport_crypto_setup(php_stream *stream, php_stream_xport_crypt_method_t crypto_method, php_stream *session_stream TSRMLS_DC); -PHPAPI int php_stream_xport_crypto_enable(php_stream *stream, int activate TSRMLS_DC); - -typedef struct _php_stream_xport_crypto_param { - enum { - STREAM_XPORT_CRYPTO_OP_SETUP, - STREAM_XPORT_CRYPTO_OP_ENABLE - } op; - struct { - int activate; - php_stream_xport_crypt_method_t method; - php_stream *session; - } inputs; - struct { - int returncode; - } outputs; -} php_stream_xport_crypto_param; - -PHPAPI HashTable *php_stream_xport_get_hash(void); -PHPAPI php_stream_transport_factory_func php_stream_generic_socket_factory; - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/main/streams/php_stream_userspace.h b/main/streams/php_stream_userspace.h deleted file mode 100644 index a5b59ffb74..0000000000 --- a/main/streams/php_stream_userspace.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong <wez@thebrainroom.com> | - +----------------------------------------------------------------------+ - */ - -/* $Id$ */ - - -/* for user-space streams */ -PHPAPI extern php_stream_ops php_stream_userspace_ops; -PHPAPI extern php_stream_ops php_stream_userspace_dir_ops; -#define PHP_STREAM_IS_USERSPACE &php_stream_userspace_ops -#define PHP_STREAM_IS_USERSPACE_DIR &php_stream_userspace_dir_ops - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/main/streams/php_streams_int.h b/main/streams/php_streams_int.h deleted file mode 100644 index a753343463..0000000000 --- a/main/streams/php_streams_int.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong <wez@thebrainroom.com> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#if ZEND_DEBUG -#define emalloc_rel_orig(size) \ - ( __php_stream_call_depth == 0 \ - ? _emalloc((size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_RELAY_CC) \ - : _emalloc((size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC) ) - -#define erealloc_rel_orig(ptr, size) \ - ( __php_stream_call_depth == 0 \ - ? _erealloc((ptr), (size), 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_RELAY_CC) \ - : _erealloc((ptr), (size), 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC) ) - - -#define pemalloc_rel_orig(size, persistent) ((persistent) ? malloc((size)) : emalloc_rel_orig((size))) -#define perealloc_rel_orig(ptr, size, persistent) ((persistent) ? realloc((ptr), (size)) : erealloc_rel_orig((ptr), (size))) -#else -# define pemalloc_rel_orig(size, persistent) pemalloc((size), (persistent)) -# define perealloc_rel_orig(ptr, size, persistent) perealloc((ptr), (size), (persistent)) -# define emalloc_rel_orig(size) emalloc((size)) -#endif - -#define STREAM_DEBUG 0 -#define STREAM_WRAPPER_PLAIN_FILES ((php_stream_wrapper*)-1) -extern php_stream_wrapper php_plain_files_wrapper; - -#ifndef MAP_FAILED -#define MAP_FAILED ((void *) -1) -#endif - -#define CHUNK_SIZE 8192 - -#ifdef PHP_WIN32 -#define EWOULDBLOCK WSAEWOULDBLOCK -#endif - -#ifndef S_ISREG -#define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG) -#endif - -void php_stream_tidy_wrapper_error_log(php_stream_wrapper *wrapper TSRMLS_DC); -void php_stream_display_wrapper_errors(php_stream_wrapper *wrapper, const char *path, const char *caption TSRMLS_DC); - diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c deleted file mode 100644 index c60063f355..0000000000 --- a/main/streams/plain_wrapper.c +++ /dev/null @@ -1,1281 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Wez Furlong <wez@thebrainroom.com> | - +----------------------------------------------------------------------+ - */ - -/* $Id$ */ - -#include "php.h" -#include "php_globals.h" -#include "php_network.h" -#include "php_open_temporary_file.h" -#include "ext/standard/file.h" -#include "ext/standard/flock_compat.h" -#include <stddef.h> -#include <fcntl.h> -#if HAVE_SYS_WAIT_H -#include <sys/wait.h> -#endif -#if HAVE_SYS_FILE_H -#include <sys/file.h> -#endif -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif - -#include "php_streams_int.h" - -/* parse standard "fopen" modes into open() flags */ -PHPAPI int php_stream_parse_fopen_modes(const char *mode, int *open_flags) -{ - int flags; - - switch (mode[0]) { - case 'r': - flags = 0; - break; - case 'w': - flags = O_TRUNC|O_CREAT; - break; - case 'a': - flags = O_CREAT|O_APPEND; - break; - case 'x': - flags = O_CREAT|O_EXCL; - break; - default: - /* unknown mode */ - return FAILURE; - } - - if (strchr(mode, '+')) { - flags |= O_RDWR; - } else if (flags) { - flags |= O_WRONLY; - } else { - flags |= O_RDONLY; - } - -#if defined(_O_TEXT) && defined(O_BINARY) - if (strchr(mode, 't')) { - flags |= _O_TEXT; - } else { - flags |= O_BINARY; - } -#endif - - *open_flags = flags; - return SUCCESS; -} - - -/* {{{ php_stream_fopen */ -PHPAPI php_stream *_php_stream_fopen(const char *filename, const char *mode, char **opened_path, int options STREAMS_DC TSRMLS_DC) -{ - char *realpath = NULL; - struct stat st; - int open_flags; - int fd; - php_stream *ret; - int persistent = options & STREAM_OPEN_PERSISTENT; - char *persistent_id = NULL; - - if (FAILURE == php_stream_parse_fopen_modes(mode, &open_flags)) { - if (options & REPORT_ERRORS) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "`%s' is not a valid mode for fopen", mode); - } - return NULL; - } - - if ((realpath = expand_filepath(filename, NULL TSRMLS_CC)) == NULL) { - return NULL; - } - - if (persistent) { - spprintf(&persistent_id, 0, "streams_stdio_%d_%s", open_flags, realpath); - switch (php_stream_from_persistent_id(persistent_id, &ret TSRMLS_CC)) { - case PHP_STREAM_PERSISTENT_SUCCESS: - if (opened_path) { - *opened_path = realpath; - realpath = NULL; - } - if (realpath) { - efree(realpath); - } - /* fall through */ - - case PHP_STREAM_PERSISTENT_FAILURE: - efree(persistent_id);; - return ret; - } - } - - fd = open(realpath, open_flags, 0666); - - if (fd != -1) { - /* sanity checks for include/require */ - if (options & STREAM_OPEN_FOR_INCLUDE && (fstat(fd, &st) == -1 || !S_ISREG(st.st_mode))) { -#ifdef PHP_WIN32 - /* skip the sanity check; fstat doesn't appear to work on - * UNC paths */ - if (!IS_UNC_PATH(filename, strlen(filename))) -#endif - goto err; - } - - ret = php_stream_fopen_from_fd_rel(fd, mode, persistent_id); - - if (ret) { - if (opened_path) { - *opened_path = realpath; - realpath = NULL; - } - if (realpath) { - efree(realpath); - } - if (persistent_id) { - efree(persistent_id); - } - return ret; - } -err: - close(fd); - } - efree(realpath); - if (persistent_id) { - efree(persistent_id); - } - return NULL; -} -/* }}} */ - -/* {{{ ------- STDIO stream implementation -------*/ - -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 */ - int lock_flag; /* stores the lock state */ - 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 - -#if HAVE_MMAP - char *last_mapped_addr; - size_t last_mapped_len; -#endif -#ifdef PHP_WIN32 - char *last_mapped_addr; - HANDLE file_mapping; -#endif -} php_stdio_stream_data; - -PHPAPI php_stream *_php_stream_fopen_temporary_file(const char *dir, const char *pfx, char **opened_path STREAMS_DC TSRMLS_DC) -{ - int fd = php_open_temporary_fd(dir, pfx, opened_path TSRMLS_CC); - - if (fd != -1) { - php_stream *stream = php_stream_fopen_from_fd_rel(fd, "r+b", NULL); - if (stream) { - return stream; - } - close(fd); - - php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to allocate stream"); - - return NULL; - } - return NULL; -} - -PHPAPI php_stream *_php_stream_fopen_tmpfile(int dummy STREAMS_DC TSRMLS_DC) -{ - char *opened_path = NULL; - int fd = php_open_temporary_fd(NULL, "php", &opened_path TSRMLS_CC); - - if (fd != -1) { - php_stream *stream = php_stream_fopen_from_fd_rel(fd, "r+b", NULL); - if (stream) { - php_stdio_stream_data *self = (php_stdio_stream_data*)stream->abstract; - - self->temp_file_name = opened_path; - self->lock_flag = LOCK_UN; - - return stream; - } - close(fd); - - php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to allocate stream"); - - return NULL; - } - return NULL; -} - -PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const char *persistent_id STREAMS_DC TSRMLS_DC) -{ - php_stdio_stream_data *self; - php_stream *stream; - - self = pemalloc_rel_orig(sizeof(*self), persistent_id); - memset(self, 0, sizeof(*self)); - self->file = NULL; - self->is_pipe = 0; - self->lock_flag = LOCK_UN; - self->is_process_pipe = 0; - self->temp_file_name = NULL; - self->fd = fd; - -#ifdef S_ISFIFO - /* detect if this is a pipe */ - if (self->fd >= 0) { - struct stat sb; - self->is_pipe = (fstat(self->fd, &sb) == 0 && S_ISFIFO(sb.st_mode)) ? 1 : 0; - } -#elif defined(PHP_WIN32) - { - long handle = _get_osfhandle(self->fd); - DWORD in_buf_size, out_buf_size; - - if (handle != 0xFFFFFFFF) { - self->is_pipe = GetNamedPipeInfo((HANDLE)handle, NULL, &out_buf_size, &in_buf_size, NULL); - } - } -#endif - - stream = php_stream_alloc_rel(&php_stream_stdio_ops, self, persistent_id, mode); - - if (stream) { - if (self->is_pipe) { - stream->flags |= PHP_STREAM_FLAG_NO_SEEK; - } else { - stream->position = lseek(self->fd, 0, SEEK_CUR); - } - } - - return stream; -} - -PHPAPI php_stream *_php_stream_fopen_from_file(FILE *file, const char *mode STREAMS_DC TSRMLS_DC) -{ - php_stdio_stream_data *self; - php_stream *stream; - - self = emalloc_rel_orig(sizeof(*self)); - memset(self, 0, sizeof(*self)); - self->file = file; - self->is_pipe = 0; - self->lock_flag = LOCK_UN; - self->is_process_pipe = 0; - self->temp_file_name = NULL; - self->fd = fileno(file); - -#ifdef S_ISFIFO - /* detect if this is a pipe */ - if (self->fd >= 0) { - struct stat sb; - self->is_pipe = (fstat(self->fd, &sb) == 0 && S_ISFIFO(sb.st_mode)) ? 1 : 0; - } -#elif defined(PHP_WIN32) - { - long handle = _get_osfhandle(self->fd); - DWORD in_buf_size, out_buf_size; - - if (handle != 0xFFFFFFFF) { - self->is_pipe = GetNamedPipeInfo((HANDLE)handle, NULL, &out_buf_size, &in_buf_size, NULL); - } - } -#endif - - stream = php_stream_alloc_rel(&php_stream_stdio_ops, self, 0, mode); - - if (stream) { - if (self->is_pipe) { - stream->flags |= PHP_STREAM_FLAG_NO_SEEK; - } else { - stream->position = ftell(file); - } - } - - return stream; -} - -PHPAPI php_stream *_php_stream_fopen_from_pipe(FILE *file, const char *mode STREAMS_DC TSRMLS_DC) -{ - php_stdio_stream_data *self; - php_stream *stream; - - self = emalloc_rel_orig(sizeof(*self)); - memset(self, 0, sizeof(*self)); - self->file = file; - self->is_pipe = 1; - self->lock_flag = LOCK_UN; - self->is_process_pipe = 1; - self->fd = fileno(file); - self->temp_file_name = NULL; - - stream = php_stream_alloc_rel(&php_stream_stdio_ops, self, 0, mode); - stream->flags |= PHP_STREAM_FLAG_NO_SEEK; - return stream; -} - -#define PHP_STDIOP_GET_FD(anfd, data) anfd = (data)->file ? fileno((data)->file) : (data)->fd - -static size_t php_stdiop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) -{ - php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract; - - assert(data != NULL); - - if (data->fd >= 0) { - int bytes_written = write(data->fd, buf, count); - if (bytes_written < 0) return 0; - return (size_t) bytes_written; - } else { - -#if HAVE_FLUSHIO - 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); - } -} - -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 (data->fd >= 0) { - ret = read(data->fd, buf, count); - - stream->eof = (ret == 0 || (ret == -1 && errno != EWOULDBLOCK)); - - } else { -#if HAVE_FLUSHIO - if (!data->is_pipe && data->last_op == 'w') - fseek(data->file, 0, SEEK_CUR); - data->last_op = 'r'; -#endif - - ret = fread(buf, 1, count, data->file); - - stream->eof = feof(data->file); - } - return ret; -} - -static int php_stdiop_close(php_stream *stream, int close_handle TSRMLS_DC) -{ - int ret; - php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract; - - assert(data != NULL); - -#if HAVE_MMAP - if (data->last_mapped_addr) { - munmap(data->last_mapped_addr, data->last_mapped_len); - data->last_mapped_addr = NULL; - } -#elif defined(PHP_WIN32) - if (data->last_mapped_addr) { - UnmapViewOfFile(data->last_mapped_addr); - data->last_mapped_addr = NULL; - } - if (data->file_mapping) { - CloseHandle(data->file_mapping); - data->file_mapping = NULL; - } -#endif - - if (close_handle) { - if (data->lock_flag != LOCK_UN) { - php_stream_lock(stream, LOCK_UN); - } - if (data->file) { - if (data->is_process_pipe) { - errno = 0; - ret = pclose(data->file); - -#if HAVE_SYS_WAIT_H - if (WIFEXITED(ret)) { - ret = WEXITSTATUS(ret); - } -#endif - } else { - ret = fclose(data->file); - data->file = NULL; - } - } else if (data->fd != -1) { - ret = close(data->fd); - data->fd = -1; - } else { - return 0; /* everything should be closed already -> success */ - } - if (data->temp_file_name) { - unlink(data->temp_file_name); - /* temporary streams are never persistent */ - efree(data->temp_file_name); - data->temp_file_name = NULL; - } - } else { - ret = 0; - data->file = NULL; - data->fd = -1; - } - - pefree(data, stream->is_persistent); - - return ret; -} - -static int php_stdiop_flush(php_stream *stream TSRMLS_DC) -{ - php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract; - - assert(data != NULL); - - /* - * stdio buffers data in user land. By calling fflush(3), this - * data is send to the kernel using write(2). fsync'ing is - * something completely different. - */ - if (data->file) { - return fflush(data->file); - } - return 0; -} - -static int php_stdiop_seek(php_stream *stream, off_t offset, int whence, off_t *newoffset TSRMLS_DC) -{ - php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract; - int ret; - - assert(data != NULL); - - if (data->is_pipe) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot seek on a pipe"); - return -1; - } - - 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) -{ - int fd; - 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) { - - if (data->file == NULL) { - /* we were opened as a plain file descriptor, so we - * need fdopen now */ - data->file = fdopen(data->fd, stream->mode); - } - - *(FILE**)ret = data->file; - data->fd = -1; - } - return SUCCESS; - - case PHP_STREAM_AS_FD_FOR_SELECT: - PHP_STDIOP_GET_FD(fd, data); - if (fd < 0) { - return FAILURE; - } - if (ret) { - *(int*)ret = fd; - } - return SUCCESS; - - case PHP_STREAM_AS_FD: - PHP_STDIOP_GET_FD(fd, data); - - if (fd < 0) { - return FAILURE; - } - if (data->file) { - fflush(data->file); - } - if (ret) { - *(int*)ret = fd; - } - return SUCCESS; - default: - return FAILURE; - } -} - -static int php_stdiop_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC) -{ - int fd; - php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract; - - assert(data != NULL); - - PHP_STDIOP_GET_FD(fd, data); - - return fstat(fd, &ssb->sb); -} - -static int php_stdiop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC) -{ - php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract; - size_t size; - int fd; -#ifdef O_NONBLOCK - /* FIXME: make this work for win32 */ - int flags; - int oldval; -#endif - - PHP_STDIOP_GET_FD(fd, data); - - switch(option) { - case PHP_STREAM_OPTION_BLOCKING: - if (fd == -1) - return -1; -#ifdef O_NONBLOCK - flags = fcntl(fd, F_GETFL, 0); - oldval = (flags & O_NONBLOCK) ? 0 : 1; - if (value) - flags ^= O_NONBLOCK; - else - flags |= O_NONBLOCK; - - if (-1 == fcntl(fd, F_SETFL, flags)) - return -1; - return oldval; -#else - return -1; /* not yet implemented */ -#endif - - case PHP_STREAM_OPTION_WRITE_BUFFER: - - if (data->file == NULL) { - return -1; - } - - if (ptrparam) - size = *(size_t *)ptrparam; - else - size = BUFSIZ; - - switch(value) { - case PHP_STREAM_BUFFER_NONE: - stream->flags |= PHP_STREAM_FLAG_NO_BUFFER; - return setvbuf(data->file, NULL, _IONBF, 0); - - case PHP_STREAM_BUFFER_LINE: - stream->flags ^= PHP_STREAM_FLAG_NO_BUFFER; - return setvbuf(data->file, NULL, _IOLBF, size); - - case PHP_STREAM_BUFFER_FULL: - stream->flags ^= PHP_STREAM_FLAG_NO_BUFFER; - return setvbuf(data->file, NULL, _IOFBF, size); - - default: - return -1; - } - break; - - case PHP_STREAM_OPTION_LOCKING: - if (fd == -1) { - return -1; - } - - if ((long) ptrparam == PHP_STREAM_LOCK_SUPPORTED) { - return 0; - } - - if (!flock(fd, value) || (errno == EWOULDBLOCK && value & LOCK_NB)) { - data->lock_flag = value; - return 0; - } else { - return -1; - } - break; - - case PHP_STREAM_OPTION_MMAP_API: -#if HAVE_MMAP - { - php_stream_mmap_range *range = (php_stream_mmap_range*)ptrparam; - struct stat sbuf; - int prot, flags; - - switch (value) { - case PHP_STREAM_MMAP_SUPPORTED: - return fd == -1 ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK; - - case PHP_STREAM_MMAP_MAP_RANGE: - fstat(fd, &sbuf); - if (range->length == 0 || range->length > sbuf.st_size) { - range->length = sbuf.st_size; - } - switch (range->mode) { - case PHP_STREAM_MAP_MODE_READONLY: - prot = PROT_READ; - flags = MAP_PRIVATE; - break; - case PHP_STREAM_MAP_MODE_READWRITE: - prot = PROT_READ | PROT_WRITE; - flags = MAP_PRIVATE; - break; - case PHP_STREAM_MAP_MODE_SHARED_READONLY: - prot = PROT_READ; - flags = MAP_SHARED; - break; - case PHP_STREAM_MAP_MODE_SHARED_READWRITE: - prot = PROT_READ | PROT_WRITE; - flags = MAP_SHARED; - break; - default: - return PHP_STREAM_OPTION_RETURN_ERR; - } - range->mapped = (char*)mmap(NULL, range->length, prot, flags, fd, range->offset); - if (range->mapped == (char*)MAP_FAILED) { - range->mapped = NULL; - return PHP_STREAM_OPTION_RETURN_ERR; - } - /* remember the mapping */ - data->last_mapped_addr = range->mapped; - data->last_mapped_len = range->length; - return PHP_STREAM_OPTION_RETURN_OK; - - case PHP_STREAM_MMAP_UNMAP: - if (data->last_mapped_addr) { - munmap(data->last_mapped_addr, data->last_mapped_len); - data->last_mapped_addr = NULL; - - return PHP_STREAM_OPTION_RETURN_OK; - } - return PHP_STREAM_OPTION_RETURN_ERR; - } - } -#elif defined(PHP_WIN32) - { - php_stream_mmap_range *range = (php_stream_mmap_range*)ptrparam; - HANDLE hfile = (HANDLE)_get_osfhandle(fd); - DWORD prot, acc, loffs = 0, delta = 0; - - switch (value) { - case PHP_STREAM_MMAP_SUPPORTED: - return hfile == INVALID_HANDLE_VALUE ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK; - - case PHP_STREAM_MMAP_MAP_RANGE: - switch (range->mode) { - case PHP_STREAM_MAP_MODE_READONLY: - prot = PAGE_READONLY; - acc = FILE_MAP_READ; - break; - case PHP_STREAM_MAP_MODE_READWRITE: - prot = PAGE_READWRITE; - acc = FILE_MAP_READ | FILE_MAP_WRITE; - break; - case PHP_STREAM_MAP_MODE_SHARED_READONLY: - prot = PAGE_READONLY; - acc = FILE_MAP_READ; - /* TODO: we should assign a name for the mapping */ - break; - case PHP_STREAM_MAP_MODE_SHARED_READWRITE: - prot = PAGE_READWRITE; - acc = FILE_MAP_READ | FILE_MAP_WRITE; - /* TODO: we should assign a name for the mapping */ - break; - } - - /* create a mapping capable of viewing the whole file (this costs no real resources) */ - data->file_mapping = CreateFileMapping(hfile, NULL, prot, 0, 0, NULL); - - if (data->file_mapping == NULL) { - return PHP_STREAM_OPTION_RETURN_ERR; - } - - if (range->length == 0) { - range->length = GetFileSize(hfile, NULL) - range->offset; - } - - /* figure out how big a chunk to map to be able to view the part that we need */ - if (range->offset != 0) { - SYSTEM_INFO info; - DWORD gran; - - GetSystemInfo(&info); - gran = info.dwAllocationGranularity; - loffs = (range->offset / gran) * gran; - delta = range->offset - loffs; - } - - data->last_mapped_addr = MapViewOfFile(data->file_mapping, acc, 0, loffs, range->length); - - if (data->last_mapped_addr) { - /* give them back the address of the start offset they requested */ - range->mapped = data->last_mapped_addr + delta; - return PHP_STREAM_OPTION_RETURN_OK; - } - - CloseHandle(data->file_mapping); - data->file_mapping = NULL; - - return PHP_STREAM_OPTION_RETURN_ERR; - - case PHP_STREAM_MMAP_UNMAP: - if (data->last_mapped_addr) { - UnmapViewOfFile(data->last_mapped_addr); - data->last_mapped_addr = NULL; - CloseHandle(data->file_mapping); - data->file_mapping = NULL; - return PHP_STREAM_OPTION_RETURN_OK; - } - return PHP_STREAM_OPTION_RETURN_ERR; - - default: - return PHP_STREAM_OPTION_RETURN_ERR; - } - } - -#endif - return PHP_STREAM_OPTION_RETURN_NOTIMPL; - - case PHP_STREAM_OPTION_TRUNCATE_API: - switch (value) { - case PHP_STREAM_TRUNCATE_SUPPORTED: - return fd == -1 ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK; - - case PHP_STREAM_TRUNCATE_SET_SIZE: - return ftruncate(fd, *(size_t*)ptrparam) == 0 ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR; - } - - default: - return PHP_STREAM_OPTION_RETURN_NOTIMPL; - } -} - -PHPAPI php_stream_ops php_stream_stdio_ops = { - php_stdiop_write, php_stdiop_read, - php_stdiop_close, php_stdiop_flush, - "STDIO", - php_stdiop_seek, - php_stdiop_cast, - php_stdiop_stat, - php_stdiop_set_option -}; -/* }}} */ - -/* {{{ plain files opendir/readdir implementation */ -static size_t php_plain_files_dirstream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) -{ - DIR *dir = (DIR*)stream->abstract; - /* avoid libc5 readdir problems */ - char entry[sizeof(struct dirent)+MAXPATHLEN]; - struct dirent *result = (struct dirent *)&entry; - php_stream_dirent *ent = (php_stream_dirent*)buf; - - /* avoid problems if someone mis-uses the stream */ - if (count != sizeof(php_stream_dirent)) - return 0; - - if (php_readdir_r(dir, (struct dirent *)entry, &result) == 0 && result) { - PHP_STRLCPY(ent->d_name, result->d_name, sizeof(ent->d_name), strlen(result->d_name)); - return sizeof(php_stream_dirent); - } - return 0; -} - -static int php_plain_files_dirstream_close(php_stream *stream, int close_handle TSRMLS_DC) -{ - return closedir((DIR *)stream->abstract); -} - -static int php_plain_files_dirstream_rewind(php_stream *stream, off_t offset, int whence, off_t *newoffs TSRMLS_DC) -{ - rewinddir((DIR *)stream->abstract); - return 0; -} - -static php_stream_ops php_plain_files_dirstream_ops = { - NULL, php_plain_files_dirstream_read, - php_plain_files_dirstream_close, NULL, - "dir", - php_plain_files_dirstream_rewind, - NULL, /* cast */ - NULL, /* stat */ - NULL /* set_option */ -}; - -static php_stream *php_plain_files_dir_opener(php_stream_wrapper *wrapper, char *path, char *mode, - int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) -{ - DIR *dir = NULL; - php_stream *stream = NULL; - - if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path TSRMLS_CC)) { - return NULL; - } - - if (PG(safe_mode) &&(!php_checkuid(path, NULL, CHECKUID_ALLOW_ONLY_FILE))) { - return NULL; - } - - dir = VCWD_OPENDIR(path); - -#ifdef PHP_WIN32 - if (dir && dir->finished) { - closedir(dir); - dir = NULL; - } -#endif - if (dir) { - stream = php_stream_alloc(&php_plain_files_dirstream_ops, dir, 0, mode); - if (stream == NULL) - closedir(dir); - } - - return stream; -} -/* }}} */ - - -static php_stream *php_plain_files_stream_opener(php_stream_wrapper *wrapper, char *path, char *mode, - int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) -{ - if ((options & USE_PATH) && PG(include_path) != NULL) { - return php_stream_fopen_with_path_rel(path, mode, PG(include_path), opened_path, options); - } - - if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path TSRMLS_CC)) { - return NULL; - } - - if ((options & ENFORCE_SAFE_MODE) && PG(safe_mode) && (!php_checkuid(path, mode, CHECKUID_CHECK_MODE_PARAM))) - return NULL; - - return php_stream_fopen_rel(path, mode, opened_path, options); -} - -static int php_plain_files_url_stater(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC) -{ - - if (strncmp(url, "file://", sizeof("file://") - 1) == 0) { - url += sizeof("file://") - 1; - } - - if (PG(safe_mode) &&(!php_checkuid_ex(url, NULL, CHECKUID_CHECK_FILE_AND_DIR, (flags & PHP_STREAM_URL_STAT_QUIET) ? CHECKUID_NO_ERRORS : 0))) { - return -1; - } - - if (php_check_open_basedir_ex(url, (flags & PHP_STREAM_URL_STAT_QUIET) ? 0 : 1 TSRMLS_CC)) { - return -1; - } - -#ifdef HAVE_SYMLINK - if (flags & PHP_STREAM_URL_STAT_LINK) { - return VCWD_LSTAT(url, &ssb->sb); - } else -#endif - return VCWD_STAT(url, &ssb->sb); -} - -static int php_plain_files_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC) -{ - char *p; - int ret; - zval funcname; - zval *retval = NULL; - - if ((p = strstr(url, "://")) != NULL) { - url = p + 3; - } - - if (options & ENFORCE_SAFE_MODE) { - if (PG(safe_mode) && !php_checkuid(url, NULL, CHECKUID_CHECK_FILE_AND_DIR)) { - return 0; - } - - if (php_check_open_basedir(url TSRMLS_CC)) { - return 0; - } - } - - ret = VCWD_UNLINK(url); - if (ret == -1) { - if (options & REPORT_ERRORS) { - php_error_docref1(NULL TSRMLS_CC, url, E_WARNING, "%s", strerror(errno)); - } - return 0; - } - /* Clear stat cache */ - ZVAL_STRINGL(&funcname, "clearstatcache", sizeof("clearstatcache")-1, 0); - call_user_function_ex(CG(function_table), NULL, &funcname, &retval, 0, NULL, 0, NULL TSRMLS_CC); - if (retval) { - zval_ptr_dtor(&retval); - } - return 1; -} - -static int php_plain_files_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC) -{ - char *p; - int ret; - - if (!url_from || !url_to) { - return 0; - } - - if ((p = strstr(url_from, "://")) != NULL) { - url_from = p + 3; - } - - if ((p = strstr(url_to, "://")) != NULL) { - url_to = p + 3; - } - - if (PG(safe_mode) && (!php_checkuid(url_from, NULL, CHECKUID_CHECK_FILE_AND_DIR) || - !php_checkuid(url_to, NULL, CHECKUID_CHECK_FILE_AND_DIR))) { - return 0; - } - - if (php_check_open_basedir(url_from TSRMLS_CC) || php_check_open_basedir(url_to TSRMLS_CC)) { - return 0; - } - - ret = VCWD_RENAME(url_from, url_to); - - if (ret == -1) { -#ifdef EXDEV - if (errno == EXDEV) { - if (php_copy_file(url_from, url_to TSRMLS_CC) == SUCCESS) { - VCWD_UNLINK(url_from); - return 1; - } - } -#endif - php_error_docref2(NULL TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno)); - return 0; - } - - return 1; -} - -static int php_plain_files_mkdir(php_stream_wrapper *wrapper, char *dir, int mode, int options, php_stream_context *context TSRMLS_DC) -{ - int ret, recursive = options & PHP_STREAM_MKDIR_RECURSIVE; - char *p; - - if ((p = strstr(dir, "://")) != NULL) { - dir = p + 3; - } - - if (!recursive) { - ret = php_mkdir(dir, mode TSRMLS_CC); - } else { - /* we look for directory separator from the end of string, thus hopefuly reducing our work load */ - char *e, *buf; - struct stat sb; - int dir_len = strlen(dir); - - buf = estrndup(dir, dir_len); - e = buf + dir_len; - - /* find a top level directory we need to create */ - while ((p = strrchr(buf, DEFAULT_SLASH))) { - *p = '\0'; - if (VCWD_STAT(buf, &sb) == 0) { - *p = DEFAULT_SLASH; - break; - } - } - if (p == buf) { - ret = php_mkdir(dir, mode TSRMLS_CC); - } else if (!(ret = php_mkdir(buf, mode TSRMLS_CC))) { - if (!p) { - p = buf; - } - /* create any needed directories if the creation of the 1st directory worked */ - while (++p != e) { - if (*p == '\0' && *(p + 1) != '\0') { - *p = DEFAULT_SLASH; - if ((ret = VCWD_MKDIR(buf, (mode_t)mode)) < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno)); - break; - } - } - } - } - efree(buf); - } - if (ret < 0) { - /* Failure */ - return 0; - } else { - /* Success */ - return 1; - } -} - -static int php_plain_files_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC) -{ - if (PG(safe_mode) &&(!php_checkuid(url, NULL, CHECKUID_CHECK_FILE_AND_DIR))) { - return 0; - } - - if (php_check_open_basedir(url TSRMLS_CC)) { - return 0; - } - - if (VCWD_RMDIR(url) < 0) { - php_error_docref1(NULL TSRMLS_CC, url, E_WARNING, "%s", strerror(errno)); - return 0; - } - - return 1; -} - -static php_stream_wrapper_ops php_plain_files_wrapper_ops = { - php_plain_files_stream_opener, - NULL, - NULL, - php_plain_files_url_stater, - php_plain_files_dir_opener, - "plainfile", - php_plain_files_unlink, - php_plain_files_rename, - php_plain_files_mkdir, - php_plain_files_rmdir -}; - -php_stream_wrapper php_plain_files_wrapper = { - &php_plain_files_wrapper_ops, - NULL, - 0 -}; - -/* {{{ php_stream_fopen_with_path */ -PHPAPI php_stream *_php_stream_fopen_with_path(char *filename, char *mode, char *path, char **opened_path, int options STREAMS_DC TSRMLS_DC) -{ - /* code ripped off from fopen_wrappers.c */ - char *pathbuf, *ptr, *end; - char *exec_fname; - char trypath[MAXPATHLEN]; - struct stat sb; - php_stream *stream; - int path_length; - int filename_length; - int exec_fname_length; - - if (opened_path) { - *opened_path = NULL; - } - - if(!filename) { - return NULL; - } - - filename_length = strlen(filename); - - /* Relative path open */ - if (*filename == '.' && (IS_SLASH(filename[1]) || filename[1] == '.')) { - /* further checks, we could have ....... filenames */ - ptr = filename + 1; - if (*ptr == '.') { - while (*(++ptr) == '.'); - if (!IS_SLASH(*ptr)) { /* not a relative path after all */ - goto not_relative_path; - } - } - - - if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(filename TSRMLS_CC)) { - return NULL; - } - - if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM))) { - return NULL; - } - return php_stream_fopen_rel(filename, mode, opened_path, options); - } - - /* - * files in safe_mode_include_dir (or subdir) are excluded from - * safe mode GID/UID checks - */ - -not_relative_path: - - /* Absolute path open */ - if (IS_ABSOLUTE_PATH(filename, filename_length)) { - - if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(filename TSRMLS_CC)) { - return NULL; - } - - if ((php_check_safe_mode_include_dir(filename TSRMLS_CC)) == 0) - /* filename is in safe_mode_include_dir (or subdir) */ - return php_stream_fopen_rel(filename, mode, opened_path, options); - - if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM))) - return NULL; - - return php_stream_fopen_rel(filename, mode, opened_path, options); - } - -#ifdef PHP_WIN32 - if (IS_SLASH(filename[0])) { - int cwd_len; - char *cwd; - cwd = virtual_getcwd_ex(&cwd_len TSRMLS_CC); - /* getcwd() will return always return [DRIVE_LETTER]:/) on windows. */ - *(cwd+3) = '\0'; - - snprintf(trypath, MAXPATHLEN, "%s%s", cwd, filename); - - free(cwd); - - if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(trypath TSRMLS_CC)) { - return NULL; - } - if ((php_check_safe_mode_include_dir(trypath TSRMLS_CC)) == 0) { - return php_stream_fopen_rel(trypath, mode, opened_path, options); - } - if (PG(safe_mode) && (!php_checkuid(trypath, mode, CHECKUID_CHECK_MODE_PARAM))) { - return NULL; - } - - return php_stream_fopen_rel(trypath, mode, opened_path, options); - } -#endif - - if (!path || (path && !*path)) { - - if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path TSRMLS_CC)) { - return NULL; - } - - if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM))) { - return NULL; - } - return php_stream_fopen_rel(filename, mode, opened_path, options); - } - - /* check in provided path */ - /* append the calling scripts' current working directory - * as a fall back case - */ - if (zend_is_executing(TSRMLS_C)) { - exec_fname = zend_get_executed_filename(TSRMLS_C); - exec_fname_length = strlen(exec_fname); - path_length = strlen(path); - - while ((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length])); - if ((exec_fname && exec_fname[0] == '[') - || exec_fname_length<=0) { - /* [no active file] or no path */ - pathbuf = estrdup(path); - } else { - pathbuf = (char *) emalloc(exec_fname_length + path_length +1 +1); - memcpy(pathbuf, path, path_length); - pathbuf[path_length] = DEFAULT_DIR_SEPARATOR; - memcpy(pathbuf+path_length+1, exec_fname, exec_fname_length); - pathbuf[path_length + exec_fname_length +1] = '\0'; - } - } else { - pathbuf = estrdup(path); - } - - ptr = pathbuf; - - while (ptr && *ptr) { - end = strchr(ptr, DEFAULT_DIR_SEPARATOR); - if (end != NULL) { - *end = '\0'; - end++; - } - snprintf(trypath, MAXPATHLEN, "%s/%s", ptr, filename); - - if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(trypath TSRMLS_CC)) { - stream = NULL; - goto stream_done; - } - - if (PG(safe_mode)) { - if (VCWD_STAT(trypath, &sb) == 0) { - /* file exists ... check permission */ - if ((php_check_safe_mode_include_dir(trypath TSRMLS_CC) == 0) || - php_checkuid(trypath, mode, CHECKUID_CHECK_MODE_PARAM)) { - /* UID ok, or trypath is in safe_mode_include_dir */ - stream = php_stream_fopen_rel(trypath, mode, opened_path, options); - } else { - stream = NULL; - } - goto stream_done; - } - } - stream = php_stream_fopen_rel(trypath, mode, opened_path, options); - if (stream) { -stream_done: - efree(pathbuf); - return stream; - } - ptr = end; - } /* end provided path */ - - efree(pathbuf); - return NULL; - -} -/* }}} */ - - - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/main/streams/streams.c b/main/streams/streams.c deleted file mode 100755 index ece1870ce1..0000000000 --- a/main/streams/streams.c +++ /dev/null @@ -1,1844 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Wez Furlong <wez@thebrainroom.com> | - | Borrowed code from: | - | Rasmus Lerdorf <rasmus@lerdorf.on.ca> | - | Jim Winstead <jimw@php.net> | - +----------------------------------------------------------------------+ - */ - -/* $Id$ */ - -#define _GNU_SOURCE -#include "php.h" -#include "php_globals.h" -#include "php_network.h" -#include "php_open_temporary_file.h" -#include "ext/standard/file.h" -#include "ext/standard/basic_functions.h" /* for BG(mmap_file) (not strictly required) */ -#include "ext/standard/php_string.h" /* for php_memnstr, used by php_stream_get_record() */ -#include <stddef.h> -#include <fcntl.h> -#include "php_streams_int.h" - -/* {{{ resource and registration code */ -static HashTable url_stream_wrappers_hash; -static int le_stream = FAILURE; /* true global */ -static int le_pstream = FAILURE; /* true global */ - -PHPAPI int php_file_le_stream(void) -{ - return le_stream; -} - -PHPAPI int php_file_le_pstream(void) -{ - return le_pstream; -} - -PHPAPI HashTable *php_stream_get_url_stream_wrappers_hash() -{ - return &url_stream_wrappers_hash; -} - -static int _php_stream_release_context(list_entry *le, void *pContext TSRMLS_DC) -{ - if (le->ptr == pContext) { - return --le->refcount == 0; - } - return 0; -} - -static int forget_persistent_resource_id_numbers(zend_rsrc_list_entry *rsrc TSRMLS_DC) -{ - php_stream *stream; - - if (Z_TYPE_P(rsrc) != le_pstream) { - return 0; - } - - stream = (php_stream*)rsrc->ptr; - -#if STREAM_DEBUG -fprintf(stderr, "forget_persistent: %s:%p\n", stream->ops->label, stream); -#endif - - stream->rsrc_id = FAILURE; - - if (stream->context) { - zend_hash_apply_with_argument(&EG(regular_list), - (apply_func_arg_t) _php_stream_release_context, - stream->context TSRMLS_CC); - stream->context = NULL; - } - - return 0; -} - -PHP_RSHUTDOWN_FUNCTION(streams) -{ - zend_hash_apply(&EG(persistent_list), (apply_func_t)forget_persistent_resource_id_numbers TSRMLS_CC); - return SUCCESS; -} - -PHPAPI int php_stream_from_persistent_id(const char *persistent_id, php_stream **stream TSRMLS_DC) -{ - zend_rsrc_list_entry *le; - - if (zend_hash_find(&EG(persistent_list), (char*)persistent_id, strlen(persistent_id)+1, (void*) &le) == SUCCESS) { - if (Z_TYPE_P(le) == le_pstream) { - if (stream) { - *stream = (php_stream*)le->ptr; - le->refcount++; - (*stream)->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, *stream, le_pstream); - } - return PHP_STREAM_PERSISTENT_SUCCESS; - } - return PHP_STREAM_PERSISTENT_FAILURE; - } - return PHP_STREAM_PERSISTENT_NOT_EXIST; -} - -/* }}} */ - -/* {{{ wrapper error reporting */ -void php_stream_display_wrapper_errors(php_stream_wrapper *wrapper, const char *path, const char *caption TSRMLS_DC) -{ - char *tmp = estrdup(path); - char *msg; - int free_msg = 0; - - if (wrapper) { - if (wrapper->err_count > 0) { - int i; - size_t l; - int brlen; - char *br; - - if (PG(html_errors)) { - brlen = 7; - br = "<br />\n"; - } else { - brlen = 1; - br = "\n"; - } - - for (i = 0, l = 0; i < wrapper->err_count; i++) { - l += strlen(wrapper->err_stack[i]); - if (i < wrapper->err_count - 1) { - l += brlen; - } - } - msg = emalloc(l + 1); - msg[0] = '\0'; - for (i = 0; i < wrapper->err_count; i++) { - strcat(msg, wrapper->err_stack[i]); - if (i < wrapper->err_count - 1) { - strcat(msg, br); - } - } - - free_msg = 1; - } else { - msg = strerror(errno); - } - } else { - msg = "no suitable wrapper could be found"; - } - - php_strip_url_passwd(tmp); - php_error_docref1(NULL TSRMLS_CC, tmp, E_WARNING, "%s: %s", caption, msg); - efree(tmp); - if (free_msg) { - efree(msg); - } -} - -void php_stream_tidy_wrapper_error_log(php_stream_wrapper *wrapper TSRMLS_DC) -{ - if (wrapper) { - /* tidy up the error stack */ - int i; - - for (i = 0; i < wrapper->err_count; i++) { - efree(wrapper->err_stack[i]); - } - if (wrapper->err_stack) { - efree(wrapper->err_stack); - } - wrapper->err_stack = NULL; - wrapper->err_count = 0; - } -} - -PHPAPI void php_stream_wrapper_log_error(php_stream_wrapper *wrapper, int options TSRMLS_DC, const char *fmt, ...) -{ - va_list args; - char *buffer = NULL; - - va_start(args, fmt); - vspprintf(&buffer, 0, fmt, args); - va_end(args); - - if (options & REPORT_ERRORS || wrapper == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", buffer); - efree(buffer); - } else { - /* append to stack */ - wrapper->err_stack = erealloc(wrapper->err_stack, (wrapper->err_count + 1) * sizeof(char *)); - if (wrapper->err_stack) { - wrapper->err_stack[wrapper->err_count++] = buffer; - } - } -} - - -/* }}} */ - -/* allocate a new stream for a particular ops */ -PHPAPI php_stream *_php_stream_alloc(php_stream_ops *ops, void *abstract, const char *persistent_id, const char *mode STREAMS_DC TSRMLS_DC) /* {{{ */ -{ - php_stream *ret; - - ret = (php_stream*) pemalloc_rel_orig(sizeof(php_stream), persistent_id ? 1 : 0); - - memset(ret, 0, sizeof(php_stream)); - -#if STREAM_DEBUG -fprintf(stderr, "stream_alloc: %s:%p persistent=%s\n", ops->label, ret, persistent_id); -#endif - - ret->ops = ops; - ret->abstract = abstract; - ret->is_persistent = persistent_id ? 1 : 0; - ret->chunk_size = FG(def_chunk_size); - - if (FG(auto_detect_line_endings)) { - ret->flags |= PHP_STREAM_FLAG_DETECT_EOL; - } - - if (persistent_id) { - zend_rsrc_list_entry le; - - Z_TYPE(le) = le_pstream; - le.ptr = ret; - le.refcount = 0; - - if (FAILURE == zend_hash_update(&EG(persistent_list), (char *)persistent_id, - strlen(persistent_id) + 1, - (void *)&le, sizeof(le), NULL)) { - - pefree(ret, 1); - return NULL; - } - } - - ret->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, ret, persistent_id ? le_pstream : le_stream); - strlcpy(ret->mode, mode, sizeof(ret->mode)); - - return ret; -} -/* }}} */ - -static int _php_stream_free_persistent(list_entry *le, void *pStream TSRMLS_DC) -{ - return le->ptr == pStream; -} - -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++; - - /* 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 - - /* 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); - } - - /* Remove stream from any context link list */ - if (stream->context && stream->context->links) { - php_stream_context_del_link(stream->context, stream); - } - - if (close_options & PHP_STREAM_FREE_CALL_DTOR) { - 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 - we can be sure that we only reach here when PHP code calls - php_stream_free. - Lets let the cookie code clean it all up. - */ - stream->in_free = 0; - return fclose(stream->stdiocast); - } - - ret = stream->ops->close(stream, preserve_handle ? 0 : 1 TSRMLS_CC); - stream->abstract = NULL; - - /* tidy up any FILE* that might have been fdopened */ - 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; - } - } - - if (close_options & PHP_STREAM_FREE_RELEASE_STREAM) { - while (stream->readfilters.head) { - php_stream_filter_remove(stream->readfilters.head, 1 TSRMLS_CC); - } - while (stream->writefilters.head) { - php_stream_filter_remove(stream->writefilters.head, 1 TSRMLS_CC); - } - - if (stream->wrapper && stream->wrapper->wops && stream->wrapper->wops->stream_closer) { - stream->wrapper->wops->stream_closer(stream->wrapper, stream TSRMLS_CC); - stream->wrapper = NULL; - } - - if (stream->wrapperdata) { - zval_ptr_dtor(&stream->wrapperdata); - stream->wrapperdata = NULL; - } - - if (stream->readbuf) { - pefree(stream->readbuf, stream->is_persistent); - stream->readbuf = NULL; - } - - if (stream->is_persistent && (close_options & PHP_STREAM_FREE_PERSISTENT)) { - /* we don't work with *stream but need its value for comparison */ - zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) _php_stream_free_persistent, stream TSRMLS_CC); - } -#if ZEND_DEBUG - if ((close_options & PHP_STREAM_FREE_RSRC_DTOR) && (stream->__exposed == 0) && (EG(error_reporting) & E_WARNING)) { - /* it leaked: Lets deliberately NOT pefree it so that the memory manager shows it - * as leaked; it will log a warning, but lets help it out and display what kind - * of stream it was. */ - char *leakinfo; - spprintf(&leakinfo, 0, __FILE__ "(%d) : Stream of type '%s' %p (path:%s) was not closed\n", __LINE__, stream->ops->label, stream, stream->orig_path); - - if (stream->orig_path) { - pefree(stream->orig_path, stream->is_persistent); - stream->orig_path = NULL; - } - -# if defined(PHP_WIN32) - OutputDebugString(leakinfo); -# else - fprintf(stderr, "%s", leakinfo); -# endif - efree(leakinfo); - } else { - if (stream->orig_path) { - pefree(stream->orig_path, stream->is_persistent); - stream->orig_path = NULL; - } - - pefree(stream, stream->is_persistent); - } -#else - if (stream->orig_path) { - pefree(stream->orig_path, stream->is_persistent); - stream->orig_path = NULL; - } - - pefree(stream, stream->is_persistent); -#endif - } - - return ret; -} -/* }}} */ - -/* {{{ generic stream operations */ - -static void php_stream_fill_read_buffer(php_stream *stream, size_t size TSRMLS_DC) -{ - /* allocate/fill the buffer */ - - if (stream->readfilters.head) { - char *chunk_buf; - int err_flag = 0; - php_stream_bucket_brigade brig_in = { NULL, NULL }, brig_out = { NULL, NULL }; - php_stream_bucket_brigade *brig_inp = &brig_in, *brig_outp = &brig_out, *brig_swap; - - /* allocate a buffer for reading chunks */ - chunk_buf = emalloc(stream->chunk_size); - - while (!err_flag && (stream->writepos - stream->readpos < (off_t)size)) { - size_t justread = 0; - int flags; - php_stream_bucket *bucket; - php_stream_filter_status_t status = PSFS_ERR_FATAL; - php_stream_filter *filter; - - /* read a chunk into a bucket */ - justread = stream->ops->read(stream, chunk_buf, stream->chunk_size TSRMLS_CC); - if (justread > 0) { - bucket = php_stream_bucket_new(stream, chunk_buf, justread, 0, 0 TSRMLS_CC); - - /* after this call, bucket is owned by the brigade */ - php_stream_bucket_append(brig_inp, bucket TSRMLS_CC); - - flags = PSFS_FLAG_NORMAL; - } else { - flags = stream->eof ? PSFS_FLAG_FLUSH_CLOSE : PSFS_FLAG_FLUSH_INC; - } - - /* wind the handle... */ - for (filter = stream->readfilters.head; filter; filter = filter->next) { - status = filter->fops->filter(stream, filter, brig_inp, brig_outp, NULL, flags TSRMLS_CC); - - if (status != PSFS_PASS_ON) { - break; - } - - /* brig_out becomes brig_in. - * brig_in will always be empty here, as the filter MUST attach any un-consumed buckets - * to its own brigade */ - brig_swap = brig_inp; - brig_inp = brig_outp; - brig_outp = brig_swap; - memset(brig_outp, 0, sizeof(*brig_outp)); - } - - switch (status) { - case PSFS_PASS_ON: - /* we get here when the last filter in the chain has data to pass on. - * in this situation, we are passing the brig_in brigade into the - * stream read buffer */ - while (brig_inp->head) { - bucket = brig_inp->head; - /* grow buffer to hold this bucket - * TODO: this can fail for persistent streams */ - if (stream->readbuflen - stream->writepos < bucket->buflen) { - stream->readbuflen += bucket->buflen; - stream->readbuf = perealloc(stream->readbuf, stream->readbuflen, - stream->is_persistent); - } - memcpy(stream->readbuf + stream->writepos, bucket->buf, bucket->buflen); - stream->writepos += bucket->buflen; - - php_stream_bucket_unlink(bucket TSRMLS_CC); - php_stream_bucket_delref(bucket TSRMLS_CC); - } - - break; - - case PSFS_FEED_ME: - /* when a filter needs feeding, there is no brig_out to deal with. - * we simply continue the loop; if the caller needs more data, - * we will read again, otherwise out job is done here */ - if (justread == 0) { - /* there is no data */ - err_flag = 1; - break; - } - continue; - - case PSFS_ERR_FATAL: - /* some fatal error. Theoretically, the stream is borked, so all - * further reads should fail. */ - err_flag = 1; - break; - } - - if (justread == 0) { - break; - } - } - - efree(chunk_buf); - - } else { - /* is there enough data in the buffer ? */ - if (stream->writepos - stream->readpos < (off_t)size) { - size_t justread = 0; - - /* reduce buffer memory consumption if possible, to avoid a realloc */ - if (stream->readbuf && stream->readbuflen - stream->writepos < stream->chunk_size) { - memmove(stream->readbuf, stream->readbuf + stream->readpos, stream->readbuflen - stream->readpos); - stream->writepos -= stream->readpos; - stream->readpos = 0; - } - - /* grow the buffer if required - * TODO: this can fail for persistent streams */ - if (stream->readbuflen - stream->writepos < stream->chunk_size) { - stream->readbuflen += stream->chunk_size; - stream->readbuf = perealloc(stream->readbuf, stream->readbuflen, - stream->is_persistent); - } - - justread = stream->ops->read(stream, stream->readbuf + stream->writepos, - stream->readbuflen - stream->writepos - TSRMLS_CC); - - if (justread != (size_t)-1) { - stream->writepos += justread; - } - } - } -} - -PHPAPI size_t _php_stream_read(php_stream *stream, char *buf, size_t size TSRMLS_DC) -{ - size_t toread = 0, didread = 0; - - while (size > 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 - * the excess */ - if (stream->writepos > stream->readpos) { - - toread = stream->writepos - stream->readpos; - if (toread > size) { - toread = size; - } - - memcpy(buf, stream->readbuf + stream->readpos, toread); - stream->readpos += toread; - size -= toread; - buf += toread; - didread += toread; - } - - /* ignore eof here; the underlying state might have changed */ - if (size == 0) { - break; - } - - if (!stream->readfilters.head && (stream->flags & PHP_STREAM_FLAG_NO_BUFFER || stream->chunk_size == 1)) { - toread = stream->ops->read(stream, buf, size TSRMLS_CC); - } else { - php_stream_fill_read_buffer(stream, size TSRMLS_CC); - - toread = stream->writepos - stream->readpos; - if (toread > size) { - toread = size; - } - - if (toread > 0) { - memcpy(buf, stream->readbuf + stream->readpos, toread); - stream->readpos += toread; - } - } - if (toread > 0) { - didread += toread; - buf += toread; - size -= toread; - } else { - /* EOF, or temporary end of data (for non-blocking mode). */ - break; - } - } - - if (didread > 0) { - stream->position += didread; - } - - return didread; -} - -PHPAPI int _php_stream_eof(php_stream *stream TSRMLS_DC) -{ - /* if there is data in the buffer, it's not EOF */ - if (stream->writepos - stream->readpos > 0) { - return 0; - } - - if (!stream->eof && PHP_STREAM_OPTION_RETURN_ERR == - php_stream_set_option(stream, PHP_STREAM_OPTION_CHECK_LIVENESS, - 0, NULL)) { - stream->eof = 1; - } - - return stream->eof; -} - -PHPAPI int _php_stream_putc(php_stream *stream, int c TSRMLS_DC) -{ - unsigned char buf = c; - - if (php_stream_write(stream, &buf, 1) > 0) { - return 1; - } - return EOF; -} - -PHPAPI int _php_stream_getc(php_stream *stream TSRMLS_DC) -{ - char buf; - - if (php_stream_read(stream, &buf, 1) > 0) { - return buf & 0xff; - } - return EOF; -} - -PHPAPI int _php_stream_puts(php_stream *stream, char *buf TSRMLS_DC) -{ - int len; - char newline[2] = "\n"; /* is this OK for Win? */ - len = strlen(buf); - - if (len > 0 && php_stream_write(stream, buf, len) && php_stream_write(stream, newline, 1)) { - return 1; - } - return 0; -} - -PHPAPI int _php_stream_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC) -{ - memset(ssb, 0, sizeof(*ssb)); - - /* if the stream was wrapped, allow the wrapper to stat it */ - if (stream->wrapper && stream->wrapper->wops->stream_stat != NULL) { - return stream->wrapper->wops->stream_stat(stream->wrapper, stream, ssb TSRMLS_CC); - } - - /* if the stream doesn't directly support stat-ing, return with failure. - * We could try and emulate this by casting to a FD and fstat-ing it, - * but since the fd might not represent the actual underlying content - * this would give bogus results. */ - if (stream->ops->stat == NULL) { - return -1; - } - - return (stream->ops->stat)(stream, ssb TSRMLS_CC); -} - -PHPAPI char *php_stream_locate_eol(php_stream *stream, char *buf, size_t buf_len TSRMLS_DC) -{ - size_t avail; - char *cr, *lf, *eol = NULL; - char *readptr; - - if (!buf) { - readptr = stream->readbuf + stream->readpos; - avail = stream->writepos - stream->readpos; - } else { - readptr = buf; - avail = buf_len; - } - - /* Look for EOL */ - if (stream->flags & PHP_STREAM_FLAG_DETECT_EOL) { - cr = memchr(readptr, '\r', avail); - lf = memchr(readptr, '\n', avail); - - if (cr && lf != cr + 1 && !(lf && lf < cr)) { - /* mac */ - stream->flags ^= PHP_STREAM_FLAG_DETECT_EOL; - stream->flags |= PHP_STREAM_FLAG_EOL_MAC; - eol = cr; - } else if ((cr && lf && cr == lf - 1) || (lf)) { - /* dos or unix endings */ - stream->flags ^= PHP_STREAM_FLAG_DETECT_EOL; - eol = lf; - } - } else if (stream->flags & PHP_STREAM_FLAG_EOL_MAC) { - eol = memchr(readptr, '\r', avail); - } else { - /* unix (and dos) line endings */ - eol = memchr(readptr, '\n', avail); - } - - return eol; -} - -/* If buf == NULL, the buffer will be allocated automatically and will be of an - * appropriate length to hold the line, regardless of the line length, memory - * permitting */ -PHPAPI char *_php_stream_get_line(php_stream *stream, char *buf, size_t maxlen, - size_t *returned_len TSRMLS_DC) -{ - size_t avail = 0; - size_t current_buf_size = 0; - size_t total_copied = 0; - int grow_mode = 0; - char *bufstart = buf; - - if (buf == NULL) { - grow_mode = 1; - } else if (maxlen == 0) { - return NULL; - } - - /* - * If the underlying stream operations block when no new data is readable, - * we need to take extra precautions. - * - * If there is buffered data available, we check for a EOL. If it exists, - * we pass the data immediately back to the caller. This saves a call - * to the read implementation and will not block where blocking - * is not necessary at all. - * - * If the stream buffer contains more data than the caller requested, - * we can also avoid that costly step and simply return that data. - */ - - for (;;) { - avail = stream->writepos - stream->readpos; - - if (avail > 0) { - size_t cpysz = 0; - char *readptr; - char *eol; - int done = 0; - - readptr = stream->readbuf + stream->readpos; - eol = php_stream_locate_eol(stream, NULL, 0 TSRMLS_CC); - - if (eol) { - cpysz = eol - readptr + 1; - done = 1; - } else { - cpysz = avail; - } - - if (grow_mode) { - /* allow room for a NUL. If this realloc is really a realloc - * (ie: second time around), we get an extra byte. In most - * cases, with the default chunk size of 8K, we will only - * incur that overhead once. When people have lines longer - * than 8K, we waste 1 byte per additional 8K or so. - * That seems acceptable to me, to avoid making this code - * hard to follow */ - bufstart = erealloc(bufstart, current_buf_size + cpysz + 1); - current_buf_size += cpysz + 1; - buf = bufstart + total_copied; - } else { - if (cpysz >= maxlen - 1) { - cpysz = maxlen - 1; - done = 1; - } - } - - memcpy(buf, readptr, cpysz); - - stream->position += cpysz; - stream->readpos += cpysz; - buf += cpysz; - maxlen -= cpysz; - total_copied += cpysz; - - if (done) { - break; - } - } else if (stream->eof) { - break; - } else { - /* XXX: Should be fine to always read chunk_size */ - size_t toread; - - if (grow_mode) { - toread = stream->chunk_size; - } else { - toread = maxlen - 1; - if (toread > stream->chunk_size) { - toread = stream->chunk_size; - } - } - - php_stream_fill_read_buffer(stream, toread TSRMLS_CC); - - if (stream->writepos - stream->readpos == 0) { - break; - } - } - } - - if (total_copied == 0) { - if (grow_mode) { - assert(bufstart == NULL); - } - return NULL; - } - - buf[0] = '\0'; - if (returned_len) { - *returned_len = total_copied; - } - - return bufstart; -} - -PHPAPI char *php_stream_get_record(php_stream *stream, size_t maxlen, size_t *returned_len, char *delim, size_t delim_len TSRMLS_DC) -{ - char *e, *buf; - size_t toread; - - php_stream_fill_read_buffer(stream, maxlen TSRMLS_CC); - - if (delim_len == 0) { - toread = maxlen; - } else { - if (delim_len == 1) { - e = memchr(stream->readbuf, *delim, stream->readbuflen); - } else { - e = php_memnstr(stream->readbuf, delim, delim_len, (stream->readbuf + stream->readbuflen)); - } - - if (!e) { - toread = maxlen; - } else { - toread = e - (char *) stream->readbuf; - } - } - - if (toread > maxlen && maxlen > 0) { - toread = maxlen; - } - - buf = emalloc(toread + 1); - *returned_len = php_stream_read(stream, buf, toread); - - if (*returned_len >= 0) { - return buf; - } else { - efree(buf); - return NULL; - } -} - -/* Writes a buffer directly to a stream, using multiple of the chunk size */ -static size_t _php_stream_write_buffer(php_stream *stream, const char *buf, size_t count TSRMLS_DC) -{ - size_t didwrite = 0, towrite, justwrote; - - /* if we have a seekable stream we need to ensure that data is written at the - * current stream->position. This means invalidating the read buffer and then - * performing a low-level seek */ - if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) { - stream->readpos = stream->writepos = 0; - - stream->ops->seek(stream, stream->position, SEEK_SET, &stream->position TSRMLS_CC); - } - - - while (count > 0) { - towrite = count; - if (towrite > stream->chunk_size) - towrite = stream->chunk_size; - - justwrote = stream->ops->write(stream, buf, towrite TSRMLS_CC); - - /* convert justwrote to an integer, since normally it is unsigned */ - if ((int)justwrote > 0) { - buf += justwrote; - count -= justwrote; - didwrite += justwrote; - - /* Only screw with the buffer if we can seek, otherwise we lose data - * buffered from fifos and sockets */ - if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) { - stream->position += justwrote; - } - } else { - break; - } - } - return didwrite; - -} - -/* push some data through the write filter chain. - * buf may be NULL, if flags are set to indicate a flush. - * This may trigger a real write to the stream. - * Returns the number of bytes consumed from buf by the first filter in the chain. - * */ -static size_t _php_stream_write_filtered(php_stream *stream, const char *buf, size_t count, int flags TSRMLS_DC) -{ - size_t consumed = 0; - php_stream_bucket *bucket; - php_stream_bucket_brigade brig_in = { NULL, NULL }, brig_out = { NULL, NULL }; - php_stream_bucket_brigade *brig_inp = &brig_in, *brig_outp = &brig_out, *brig_swap; - php_stream_filter_status_t status = PSFS_ERR_FATAL; - php_stream_filter *filter; - - if (buf) { - bucket = php_stream_bucket_new(stream, (char *)buf, count, 0, 0 TSRMLS_CC); - php_stream_bucket_append(&brig_in, bucket TSRMLS_CC); - } - - for (filter = stream->writefilters.head; filter; filter = filter->next) { - /* for our return value, we are interested in the number of bytes consumed from - * the first filter in the chain */ - status = filter->fops->filter(stream, filter, brig_inp, brig_outp, - filter == stream->writefilters.head ? &consumed : NULL, flags TSRMLS_CC); - - if (status != PSFS_PASS_ON) { - break; - } - /* brig_out becomes brig_in. - * brig_in will always be empty here, as the filter MUST attach any un-consumed buckets - * to its own brigade */ - brig_swap = brig_inp; - brig_inp = brig_outp; - brig_outp = brig_swap; - memset(brig_outp, 0, sizeof(*brig_outp)); - } - - switch (status) { - case PSFS_PASS_ON: - /* filter chain generated some output; push it through to the - * underlying stream */ - while (brig_inp->head) { - bucket = brig_inp->head; - _php_stream_write_buffer(stream, bucket->buf, bucket->buflen TSRMLS_CC); - /* Potential error situation - eg: no space on device. Perhaps we should keep this brigade - * hanging around and try to write it later. - * At the moment, we just drop it on the floor - * */ - - php_stream_bucket_unlink(bucket TSRMLS_CC); - php_stream_bucket_delref(bucket TSRMLS_CC); - } - break; - case PSFS_FEED_ME: - /* need more data before we can push data through to the stream */ - break; - - case PSFS_ERR_FATAL: - /* some fatal error. Theoretically, the stream is borked, so all - * further writes should fail. */ - break; - } - - return consumed; -} - -PHPAPI int _php_stream_flush(php_stream *stream, int closing TSRMLS_DC) -{ - int ret = 0; - - if (stream->writefilters.head) { - _php_stream_write_filtered(stream, NULL, 0, closing ? PSFS_FLAG_FLUSH_CLOSE : PSFS_FLAG_FLUSH_INC TSRMLS_CC); - } - - if (stream->ops->flush) { - ret = stream->ops->flush(stream TSRMLS_CC); - } - - return ret; -} - -PHPAPI size_t _php_stream_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) -{ - if (buf == NULL || count == 0 || stream->ops->write == NULL) { - return 0; - } - - if (stream->writefilters.head) { - return _php_stream_write_filtered(stream, buf, count, PSFS_FLAG_NORMAL TSRMLS_CC); - } else { - return _php_stream_write_buffer(stream, buf, count TSRMLS_CC); - } -} - -PHPAPI size_t _php_stream_printf(php_stream *stream TSRMLS_DC, const char *fmt, ...) -{ - size_t count; - char *buf; - va_list ap; - - va_start(ap, fmt); - count = vspprintf(&buf, 0, fmt, ap); - va_end(ap); - - if (!buf) { - return 0; /* error condition */ - } - - count = php_stream_write(stream, buf, count); - efree(buf); - - return count; -} - -PHPAPI off_t _php_stream_tell(php_stream *stream TSRMLS_DC) -{ - return stream->position; -} - -PHPAPI int _php_stream_seek(php_stream *stream, off_t offset, int whence TSRMLS_DC) -{ - /* handle the case where we are in the buffer */ - if ((stream->flags & PHP_STREAM_FLAG_NO_BUFFER) == 0) { - switch(whence) { - case SEEK_CUR: - if (offset > 0 && offset < stream->writepos - stream->readpos) { - stream->readpos += offset; - stream->position += offset; - stream->eof = 0; - return 0; - } - break; - case SEEK_SET: - if (offset > stream->position && - offset < stream->position + stream->writepos - stream->readpos) { - stream->readpos += offset - stream->position; - stream->position = offset; - stream->eof = 0; - return 0; - } - break; - } - } - - - if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) { - int ret; - - if (stream->writefilters.head) { - _php_stream_flush(stream, 0 TSRMLS_CC); - } - - switch(whence) { - case SEEK_CUR: - offset = stream->position + offset; - whence = SEEK_SET; - break; - } - ret = stream->ops->seek(stream, offset, whence, &stream->position TSRMLS_CC); - - if (((stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) || ret == 0) { - if (ret == 0) { - stream->eof = 0; - } - - /* invalidate the buffer contents */ - stream->readpos = stream->writepos = 0; - - return ret; - } - /* else the stream has decided that it can't support seeking after all; - * fall through to attempt emulation */ - } - - /* emulate forward moving seeks with reads */ - if (whence == SEEK_CUR && offset > 0) { - char tmp[1024]; - while(offset >= sizeof(tmp)) { - if (php_stream_read(stream, tmp, sizeof(tmp)) == 0) { - return -1; - } - offset -= sizeof(tmp); - } - if (offset && (php_stream_read(stream, tmp, offset) == 0)) { - return -1; - } - stream->eof = 0; - return 0; - } - - php_error_docref(NULL TSRMLS_CC, E_WARNING, "stream does not support seeking"); - - return -1; -} - -PHPAPI int _php_stream_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC) -{ - int ret = PHP_STREAM_OPTION_RETURN_NOTIMPL; - - if (stream->ops->set_option) { - ret = stream->ops->set_option(stream, option, value, ptrparam TSRMLS_CC); - } - - if (ret == PHP_STREAM_OPTION_RETURN_NOTIMPL) { - switch(option) { - case PHP_STREAM_OPTION_SET_CHUNK_SIZE: - ret = stream->chunk_size; - stream->chunk_size = value; - return ret; - - case PHP_STREAM_OPTION_READ_BUFFER: - /* try to match the buffer mode as best we can */ - if (value == PHP_STREAM_BUFFER_NONE) { - stream->flags |= PHP_STREAM_FLAG_NO_BUFFER; - } else { - stream->flags ^= PHP_STREAM_FLAG_NO_BUFFER; - } - ret = PHP_STREAM_OPTION_RETURN_OK; - break; - - default: - ; - } - } - - return ret; -} - -PHPAPI int _php_stream_truncate_set_size(php_stream *stream, size_t newsize TSRMLS_DC) -{ - return php_stream_set_option(stream, PHP_STREAM_OPTION_TRUNCATE_API, PHP_STREAM_TRUNCATE_SET_SIZE, &newsize); -} - -PHPAPI size_t _php_stream_passthru(php_stream * stream STREAMS_DC TSRMLS_DC) -{ - size_t bcount = 0; - char buf[8192]; - int b; - - if (php_stream_mmap_possible(stream)) { - char *p; - size_t mapped; - - p = php_stream_mmap_range(stream, php_stream_tell(stream), 0, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped); - - if (p) { - PHPWRITE(p, mapped); - - php_stream_mmap_unmap(stream); - - return mapped; - } - } - - while ((b = php_stream_read(stream, buf, sizeof(buf))) > 0) { - PHPWRITE(buf, b); - bcount += b; - } - - return bcount; -} - - -PHPAPI size_t _php_stream_copy_to_mem(php_stream *src, char **buf, size_t maxlen, int persistent STREAMS_DC TSRMLS_DC) -{ - size_t ret = 0; - char *ptr; - size_t len = 0, max_len; - int step = CHUNK_SIZE; - int min_room = CHUNK_SIZE / 4; - php_stream_statbuf ssbuf; - - if (buf) { - *buf = NULL; - } - - if (maxlen == 0) { - return 0; - } - - if (maxlen == PHP_STREAM_COPY_ALL) { - maxlen = 0; - } - - if (php_stream_mmap_possible(src)) { - char *p; - size_t mapped; - - p = php_stream_mmap_range(src, php_stream_tell(src), maxlen, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped); - - if (p) { - *buf = pemalloc_rel_orig(mapped + 1, persistent); - - if (*buf) { - memcpy(*buf, p, mapped); - (*buf)[mapped] = '\0'; - } - - php_stream_mmap_unmap(src); - - return mapped; - } - } - - /* avoid many reallocs by allocating a good sized chunk to begin with, if - * we can. Note that the stream may be filtered, in which case the stat - * result may be inaccurate, as the filter may inflate or deflate the - * number of bytes that we can read. In order to avoid an upsize followed - * by a downsize of the buffer, overestimate by the step size (which is - * 2K). */ - if (php_stream_stat(src, &ssbuf) == 0 && ssbuf.sb.st_size > 0) { - max_len = ssbuf.sb.st_size + step; - } else { - max_len = step; - } - - ptr = *buf = pemalloc_rel_orig(max_len, persistent); - - while((ret = php_stream_read(src, ptr, max_len - len))) { - len += ret; - if (len + min_room >= max_len) { - *buf = perealloc_rel_orig(*buf, max_len + step, persistent); - max_len += step; - ptr = *buf + len; - } - } - if (len) { - *buf = perealloc_rel_orig(*buf, len + 1, persistent); - (*buf)[len] = '\0'; - } else { - pefree(*buf, persistent); - *buf = NULL; - } - return len; -} - -PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size_t maxlen STREAMS_DC TSRMLS_DC) -{ - char buf[CHUNK_SIZE]; - size_t readchunk; - size_t haveread = 0; - size_t didread; - php_stream_statbuf ssbuf; - - if (maxlen == 0) { - return 0; - } - - if (maxlen == PHP_STREAM_COPY_ALL) { - maxlen = 0; - } - - if (php_stream_stat(src, &ssbuf) == 0) { - /* in the event that the source file is 0 bytes, return 1 to indicate success - * because opening the file to write had already created a copy */ - if (ssbuf.sb.st_size == 0 -#ifdef S_ISFIFO - && !S_ISFIFO(ssbuf.sb.st_mode) -#endif -#ifdef S_ISCHR - && !S_ISCHR(ssbuf.sb.st_mode) -#endif - ) { - return 1; - } - } - - if (php_stream_mmap_possible(src)) { - char *p; - size_t mapped; - - p = php_stream_mmap_range(src, php_stream_tell(src), maxlen, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped); - - if (p) { - haveread = php_stream_write(dest, p, mapped); - - php_stream_mmap_unmap(src); - - return mapped; - } - } - - while(1) { - readchunk = sizeof(buf); - - if (maxlen && (maxlen - haveread) < readchunk) - readchunk = maxlen - haveread; - - didread = php_stream_read(src, buf, readchunk); - - if (didread) { - /* extra paranoid */ - size_t didwrite, towrite; - char *writeptr; - - towrite = didread; - writeptr = buf; - haveread += didread; - - while(towrite) { - didwrite = php_stream_write(dest, writeptr, towrite); - if (didwrite == 0) { - return 0; /* error */ - } - - towrite -= didwrite; - writeptr += didwrite; - } - } else { - if (maxlen == 0) { - return haveread; - } else { - return 0; /* error */ - } - } - - if (maxlen - haveread == 0) { - break; - } - } - return haveread; - -} -/* }}} */ - -/* {{{ wrapper init and registration */ - -static void stream_resource_regular_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) -{ - php_stream *stream = (php_stream*)rsrc->ptr; - /* set the return value for pclose */ - FG(pclose_ret) = php_stream_free(stream, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR); -} - -static void stream_resource_persistent_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) -{ - php_stream *stream = (php_stream*)rsrc->ptr; - FG(pclose_ret) = php_stream_free(stream, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR); -} - -int php_init_stream_wrappers(int module_number TSRMLS_DC) -{ - le_stream = zend_register_list_destructors_ex(stream_resource_regular_dtor, NULL, "stream", module_number); - le_pstream = zend_register_list_destructors_ex(NULL, stream_resource_persistent_dtor, "persistent stream", module_number); - - return ( - zend_hash_init(&url_stream_wrappers_hash, 0, NULL, NULL, 1) == SUCCESS - && - zend_hash_init(php_get_stream_filters_hash(), 0, NULL, NULL, 1) == SUCCESS - && - zend_hash_init(php_stream_xport_get_hash(), 0, NULL, NULL, 1) == SUCCESS - && - php_stream_xport_register("tcp", php_stream_generic_socket_factory TSRMLS_CC) == SUCCESS - && - php_stream_xport_register("udp", php_stream_generic_socket_factory TSRMLS_CC) == SUCCESS -#if defined(AF_UNIX) && !(defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)) - && - php_stream_xport_register("unix", php_stream_generic_socket_factory TSRMLS_CC) == SUCCESS - && - php_stream_xport_register("udg", php_stream_generic_socket_factory TSRMLS_CC) == SUCCESS -#endif - ) ? SUCCESS : FAILURE; -} - -int php_shutdown_stream_wrappers(int module_number TSRMLS_DC) -{ - zend_hash_destroy(&url_stream_wrappers_hash); - zend_hash_destroy(php_get_stream_filters_hash()); - zend_hash_destroy(php_stream_xport_get_hash()); - return SUCCESS; -} - -PHPAPI int php_register_url_stream_wrapper(char *protocol, php_stream_wrapper *wrapper TSRMLS_DC) -{ - return zend_hash_add(&url_stream_wrappers_hash, protocol, strlen(protocol), wrapper, sizeof(*wrapper), NULL); -} - -PHPAPI int php_unregister_url_stream_wrapper(char *protocol TSRMLS_DC) -{ - return zend_hash_del(&url_stream_wrappers_hash, protocol, strlen(protocol)); -} -/* }}} */ - -/* {{{ php_stream_locate_url_wrapper */ -PHPAPI php_stream_wrapper *php_stream_locate_url_wrapper(const char *path, char **path_for_open, int options TSRMLS_DC) -{ - php_stream_wrapper *wrapper = NULL; - const char *p, *protocol = NULL; - int n = 0; - - if (path_for_open) { - *path_for_open = (char*)path; - } - - if (options & IGNORE_URL) { - return (options & STREAM_LOCATE_WRAPPERS_ONLY) ? NULL : &php_plain_files_wrapper; - } - - for (p = path; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) { - n++; - } - - if ((*p == ':') && (n > 1) && !strncmp("://", p, 3)) { - protocol = path; - } else if (strncasecmp(path, "zlib:", 5) == 0) { - /* BC with older php scripts and zlib wrapper */ - protocol = "compress.zlib"; - n = 13; - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Use of \"zlib:\" wrapper is deprecated; please use \"compress.zlib://\" instead."); - } - - if (protocol) { - if (FAILURE == zend_hash_find(&url_stream_wrappers_hash, (char*)protocol, n, (void**)&wrapper)) { - char wrapper_name[32]; - - if (n >= sizeof(wrapper_name)) - n = sizeof(wrapper_name) - 1; - PHP_STRLCPY(wrapper_name, protocol, sizeof(wrapper_name), n); - - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unable to find the wrapper \"%s\" - did you forget to enable it when you configured PHP?", - wrapper_name); - - wrapper = NULL; - protocol = NULL; - } - } - /* TODO: curl based streams probably support file:// properly */ - if (!protocol || !strncasecmp(protocol, "file", n)) { - if (protocol && path[n+1] == '/' && path[n+2] == '/' && path[n+3] != '/') { - if (options & REPORT_ERRORS) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "remote host file access not supported, %s", path); - } - return NULL; - } - if (protocol && path_for_open) { - /* skip past protocol and :/, but handle windows correctly */ - *path_for_open = (char*)path + n + 1; - while (*(++*path_for_open)=='/'); -#ifdef PHP_WIN32 - if (*(*path_for_open + 1) != ':') -#endif - (*path_for_open)--; - } - - /* fall back on regular file access */ - return (options & STREAM_LOCATE_WRAPPERS_ONLY) ? NULL : &php_plain_files_wrapper; - } - - if (wrapper && wrapper->is_url && !PG(allow_url_fopen)) { - if (options & REPORT_ERRORS) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "URL file-access is disabled in the server configuration"); - } - return NULL; - } - - return wrapper; -} -/* }}} */ - -/* {{{ _php_stream_mkdir - */ -PHPAPI int _php_stream_mkdir(char *path, int mode, int options, php_stream_context *context TSRMLS_DC) -{ - php_stream_wrapper *wrapper = NULL; - - wrapper = php_stream_locate_url_wrapper(path, NULL, ENFORCE_SAFE_MODE TSRMLS_CC); - if (!wrapper || !wrapper->wops || !wrapper->wops->stream_mkdir) { - return 0; - } - - return wrapper->wops->stream_mkdir(wrapper, path, mode, options, context TSRMLS_CC); -} -/* }}} */ - -/* {{{ _php_stream_rmdir - */ -PHPAPI int _php_stream_rmdir(char *path, int options, php_stream_context *context TSRMLS_DC) -{ - php_stream_wrapper *wrapper = NULL; - - wrapper = php_stream_locate_url_wrapper(path, NULL, ENFORCE_SAFE_MODE TSRMLS_CC); - if (!wrapper || !wrapper->wops || !wrapper->wops->stream_rmdir) { - return 0; - } - - return wrapper->wops->stream_rmdir(wrapper, path, options, context TSRMLS_CC); -} -/* }}} */ - -/* {{{ _php_stream_stat_path */ -PHPAPI int _php_stream_stat_path(char *path, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC) -{ - php_stream_wrapper *wrapper = NULL; - char *path_to_open = path; - int ret; - - /* Try to hit the cache first */ - if (flags & PHP_STREAM_URL_STAT_LINK) { - if (BG(CurrentLStatFile) && strcmp(path, BG(CurrentLStatFile)) == 0) { - memcpy(ssb, &BG(lssb), sizeof(php_stream_statbuf)); - return 0; - } - } else { - if (BG(CurrentStatFile) && strcmp(path, BG(CurrentStatFile)) == 0) { - memcpy(ssb, &BG(ssb), sizeof(php_stream_statbuf)); - return 0; - } - } - - wrapper = php_stream_locate_url_wrapper(path, &path_to_open, ENFORCE_SAFE_MODE TSRMLS_CC); - if (wrapper && wrapper->wops->url_stat) { - ret = wrapper->wops->url_stat(wrapper, path_to_open, flags, ssb, context TSRMLS_CC); - if (ret == 0) { - /* Drop into cache */ - if (flags & PHP_STREAM_URL_STAT_LINK) { - if (BG(CurrentLStatFile)) { - efree(BG(CurrentLStatFile)); - } - BG(CurrentLStatFile) = estrdup(path); - memcpy(&BG(lssb), ssb, sizeof(php_stream_statbuf)); - } else { - if (BG(CurrentStatFile)) { - efree(BG(CurrentStatFile)); - } - BG(CurrentStatFile) = estrdup(path); - memcpy(&BG(ssb), ssb, sizeof(php_stream_statbuf)); - } - } - return ret; - } - return -1; -} -/* }}} */ - -/* {{{ php_stream_opendir */ -PHPAPI php_stream *_php_stream_opendir(char *path, int options, - php_stream_context *context STREAMS_DC TSRMLS_DC) -{ - php_stream *stream = NULL; - php_stream_wrapper *wrapper = NULL; - char *path_to_open; - - if (!path || !*path) { - return NULL; - } - - path_to_open = path; - - wrapper = php_stream_locate_url_wrapper(path, &path_to_open, options TSRMLS_CC); - - if (wrapper && wrapper->wops->dir_opener) { - stream = wrapper->wops->dir_opener(wrapper, - path_to_open, "r", options ^ REPORT_ERRORS, NULL, - context STREAMS_REL_CC TSRMLS_CC); - - if (stream) { - stream->wrapper = wrapper; - stream->flags |= PHP_STREAM_FLAG_NO_BUFFER; - } - } else if (wrapper) { - php_stream_wrapper_log_error(wrapper, options ^ REPORT_ERRORS TSRMLS_CC, "not implemented"); - } - if (stream == NULL && (options & REPORT_ERRORS)) { - php_stream_display_wrapper_errors(wrapper, path, "failed to open dir" TSRMLS_CC); - } - php_stream_tidy_wrapper_error_log(wrapper TSRMLS_CC); - - return stream; -} -/* }}} */ - -/* {{{ _php_stream_readdir */ -PHPAPI php_stream_dirent *_php_stream_readdir(php_stream *dirstream, php_stream_dirent *ent TSRMLS_DC) -{ - - if (sizeof(php_stream_dirent) == php_stream_read(dirstream, (char*)ent, sizeof(php_stream_dirent))) { - return ent; - } - - return NULL; -} -/* }}} */ - -/* {{{ php_stream_open_wrapper_ex */ -PHPAPI php_stream *_php_stream_open_wrapper_ex(char *path, char *mode, int options, - char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) -{ - php_stream *stream = NULL; - php_stream_wrapper *wrapper = NULL; - char *path_to_open; - int persistent = options & STREAM_OPEN_PERSISTENT; - char *copy_of_path = NULL; - - - if (opened_path) { - *opened_path = NULL; - } - - if (!path || !*path) { - return NULL; - } - - path_to_open = path; - - wrapper = php_stream_locate_url_wrapper(path, &path_to_open, options TSRMLS_CC); - if (options & STREAM_USE_URL && (!wrapper || !wrapper->is_url)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "This function may only be used against URLs."); - return NULL; - } - - if (wrapper) { - - stream = wrapper->wops->stream_opener(wrapper, - path_to_open, mode, options ^ REPORT_ERRORS, - opened_path, context STREAMS_REL_CC TSRMLS_CC); - - /* if the caller asked for a persistent stream but the wrapper did not - * return one, force an error here */ - if (stream && (options & STREAM_OPEN_PERSISTENT) && !stream->is_persistent) { - php_stream_wrapper_log_error(wrapper, options ^ REPORT_ERRORS TSRMLS_CC, - "wrapper does not support persistent streams"); - php_stream_close(stream); - stream = NULL; - } - - if (stream) { - stream->wrapper = wrapper; - } - } - - if (stream) { - copy_of_path = pestrdup(path, persistent); - stream->orig_path = copy_of_path; - } - - if (stream != NULL && (options & STREAM_MUST_SEEK)) { - php_stream *newstream; - - switch(php_stream_make_seekable_rel(stream, &newstream, - (options & STREAM_WILL_CAST) - ? PHP_STREAM_PREFER_STDIO : PHP_STREAM_NO_PREFERENCE)) { - case PHP_STREAM_UNCHANGED: - return stream; - case PHP_STREAM_RELEASED: - newstream->orig_path = pestrdup(path, persistent); - return newstream; - default: - php_stream_close(stream); - stream = NULL; - if (options & REPORT_ERRORS) { - char *tmp = estrdup(path); - php_strip_url_passwd(tmp); - php_error_docref1(NULL TSRMLS_CC, tmp, E_WARNING, "could not make seekable - %s", - tmp); - efree(tmp); - - options ^= REPORT_ERRORS; - } - } - } - - if (stream && stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0 && strchr(mode, 'a') && stream->position == 0) { - off_t newpos = 0; - - /* if opened for append, we need to revise our idea of the initial file position */ - if (0 == stream->ops->seek(stream, 0, SEEK_CUR, &newpos TSRMLS_CC)) { - stream->position = newpos; - } - } - - if (stream == NULL && (options & REPORT_ERRORS)) { - php_stream_display_wrapper_errors(wrapper, path, "failed to open stream" TSRMLS_CC); - } - php_stream_tidy_wrapper_error_log(wrapper TSRMLS_CC); -#if ZEND_DEBUG - if (stream == NULL && copy_of_path != NULL) { - pefree(copy_of_path, persistent); - } -#endif - return stream; -} -/* }}} */ - -/* {{{ context API */ -PHPAPI php_stream_context *php_stream_context_set(php_stream *stream, php_stream_context *context) -{ - php_stream_context *oldcontext = stream->context; - stream->context = context; - return oldcontext; -} - -PHPAPI void php_stream_notification_notify(php_stream_context *context, int notifycode, int severity, - char *xmsg, int xcode, size_t bytes_sofar, size_t bytes_max, void * ptr TSRMLS_DC) -{ - if (context && context->notifier) - context->notifier->func(context, notifycode, severity, xmsg, xcode, bytes_sofar, bytes_max, ptr TSRMLS_CC); -} - -PHPAPI void php_stream_context_free(php_stream_context *context) -{ - if (context->options) { - zval_ptr_dtor(&context->options); - context->options = NULL; - } - if (context->notifier) { - php_stream_notification_free(context->notifier); - context->notifier = NULL; - } - if (context->links) { - zval_ptr_dtor(&context->links); - context->links = NULL; - } - efree(context); -} - -PHPAPI php_stream_context *php_stream_context_alloc(void) -{ - php_stream_context *context; - - context = ecalloc(1, sizeof(php_stream_context)); - context->notifier = NULL; - MAKE_STD_ZVAL(context->options); - array_init(context->options); - - context->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, context, php_le_stream_context()); - return context; -} - -PHPAPI php_stream_notifier *php_stream_notification_alloc(void) -{ - return ecalloc(1, sizeof(php_stream_notifier)); -} - -PHPAPI void php_stream_notification_free(php_stream_notifier *notifier) -{ - if (notifier->dtor) { - notifier->dtor(notifier); - } - efree(notifier); -} - -PHPAPI int php_stream_context_get_option(php_stream_context *context, - const char *wrappername, const char *optionname, zval ***optionvalue) -{ - zval **wrapperhash; - - if (FAILURE == zend_hash_find(Z_ARRVAL_P(context->options), (char*)wrappername, strlen(wrappername)+1, (void**)&wrapperhash)) { - return FAILURE; - } - return zend_hash_find(Z_ARRVAL_PP(wrapperhash), (char*)optionname, strlen(optionname)+1, (void**)optionvalue); -} - -PHPAPI int php_stream_context_set_option(php_stream_context *context, - const char *wrappername, const char *optionname, zval *optionvalue) -{ - zval **wrapperhash; - zval *category, *copied_val; - - ALLOC_INIT_ZVAL(copied_val); - *copied_val = *optionvalue; - zval_copy_ctor(copied_val); - INIT_PZVAL(copied_val); - - if (FAILURE == zend_hash_find(Z_ARRVAL_P(context->options), (char*)wrappername, strlen(wrappername)+1, (void**)&wrapperhash)) { - MAKE_STD_ZVAL(category); - array_init(category); - if (FAILURE == zend_hash_update(Z_ARRVAL_P(context->options), (char*)wrappername, strlen(wrappername)+1, (void**)&category, sizeof(zval *), NULL)) { - return FAILURE; - } - - wrapperhash = &category; - } - return zend_hash_update(Z_ARRVAL_PP(wrapperhash), (char*)optionname, strlen(optionname)+1, (void**)&copied_val, sizeof(zval *), NULL); -} - -PHPAPI int php_stream_context_get_link(php_stream_context *context, - const char *hostent, php_stream **stream) -{ - php_stream **pstream; - - if (!stream || !hostent || !context || !(context->links)) { - return FAILURE; - } - if (SUCCESS == zend_hash_find(Z_ARRVAL_P(context->links), (char*)hostent, strlen(hostent)+1, (void**)&pstream)) { - *stream = *pstream; - return SUCCESS; - } - return FAILURE; -} - -PHPAPI int php_stream_context_set_link(php_stream_context *context, - const char *hostent, php_stream *stream) -{ - if (!context) { - return FAILURE; - } - if (!context->links) { - ALLOC_INIT_ZVAL(context->links); - array_init(context->links); - } - if (!stream) { - /* Delete any entry for <hostent> */ - return zend_hash_del(Z_ARRVAL_P(context->links), (char*)hostent, strlen(hostent)+1); - } - return zend_hash_update(Z_ARRVAL_P(context->links), (char*)hostent, strlen(hostent)+1, (void**)&stream, sizeof(php_stream *), NULL); -} - -PHPAPI int php_stream_context_del_link(php_stream_context *context, - php_stream *stream) -{ - php_stream **pstream; - char *hostent; - int ret = SUCCESS; - - if (!context || !context->links || !stream) { - return FAILURE; - } - - for(zend_hash_internal_pointer_reset(Z_ARRVAL_P(context->links)); - SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(context->links), (void**)&pstream); - zend_hash_move_forward(Z_ARRVAL_P(context->links))) { - if (*pstream == stream) { - if (SUCCESS == zend_hash_get_current_key(Z_ARRVAL_P(context->links), &hostent, NULL, 0)) { - if (FAILURE == zend_hash_del(Z_ARRVAL_P(context->links), (char*)hostent, strlen(hostent)+1)) { - ret = FAILURE; - } - } else { - ret = FAILURE; - } - } - } - - return ret; -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/main/streams/transports.c b/main/streams/transports.c deleted file mode 100644 index 5b2c0d89bb..0000000000 --- a/main/streams/transports.c +++ /dev/null @@ -1,487 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong <wez@thebrainroom.com> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#include "php.h" -#include "php_streams_int.h" -#include "ext/standard/file.h" - -static HashTable xport_hash; - -PHPAPI HashTable *php_stream_xport_get_hash(void) -{ - return &xport_hash; -} - -PHPAPI int php_stream_xport_register(char *protocol, php_stream_transport_factory factory TSRMLS_DC) -{ - return zend_hash_update(&xport_hash, protocol, strlen(protocol), &factory, sizeof(factory), NULL); -} - -PHPAPI int php_stream_xport_unregister(char *protocol TSRMLS_DC) -{ - return zend_hash_del(&xport_hash, protocol, strlen(protocol)); -} - -#define ERR_REPORT(out_err, fmt, arg) \ - if (out_err) { spprintf(out_err, 0, fmt, arg); } \ - else { php_error_docref(NULL TSRMLS_CC, E_WARNING, fmt, arg); } - -#define ERR_RETURN(out_err, local_err, fmt) \ - if (out_err) { *out_err = local_err; } \ - else { php_error_docref(NULL TSRMLS_CC, E_WARNING, fmt, local_err ? local_err : "Unspecified error"); \ - if (local_err) { efree(local_err); local_err = NULL; } \ - } - -PHPAPI php_stream *_php_stream_xport_create(const char *name, long namelen, int options, - int flags, const char *persistent_id, - struct timeval *timeout, - php_stream_context *context, - char **error_string, - int *error_code - STREAMS_DC TSRMLS_DC) -{ - php_stream *stream = NULL; - php_stream_transport_factory *factory = NULL; - const char *p, *protocol = NULL; - int n = 0, failed = 0; - char *error_text = NULL; - struct timeval default_timeout = { 0, 0 }; - - default_timeout.tv_sec = FG(default_socket_timeout); - - if (timeout == NULL) { - timeout = &default_timeout; - } - - /* check for a cached persistent socket */ - if (persistent_id) { - switch(php_stream_from_persistent_id(persistent_id, &stream TSRMLS_CC)) { - case PHP_STREAM_PERSISTENT_SUCCESS: - if (PHP_STREAM_OPTION_RETURN_OK == php_stream_set_option(stream, PHP_STREAM_OPTION_CHECK_LIVENESS, 0, NULL)) { - return stream; - } - /* dead - kill it */ - php_stream_pclose(stream); - stream = NULL; - - /* fall through */ - - case PHP_STREAM_PERSISTENT_FAILURE: - default: - /* failed; get a new one */ - ; - } - } - - for (p = name; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) { - n++; - } - - if ((*p == ':') && (n > 1) && !strncmp("://", p, 3)) { - protocol = name; - name = p + 3; - namelen -= n + 3; - } else { - protocol = "tcp"; - n = 3; - } - - if (protocol) { - if (FAILURE == zend_hash_find(&xport_hash, (char*)protocol, n, (void**)&factory)) { - char wrapper_name[32]; - - if (n >= sizeof(wrapper_name)) - n = sizeof(wrapper_name) - 1; - PHP_STRLCPY(wrapper_name, protocol, sizeof(wrapper_name), n); - - ERR_REPORT(error_string, "Unable to find the socket transport \"%s\" - did you forget to enable it when you configured PHP?", - wrapper_name); - - return NULL; - } - } - - if (factory == NULL) { - /* should never happen */ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not find a factory !?"); - return NULL; - } - - stream = (*factory)(protocol, n, - (char*)name, namelen, persistent_id, options, flags, timeout, - context STREAMS_REL_CC TSRMLS_CC); - - if (stream) { - stream->context = context; - - if ((flags & STREAM_XPORT_SERVER) == 0) { - /* client */ - - if (flags & STREAM_XPORT_CONNECT) { - if (0 != php_stream_xport_connect(stream, name, namelen, - flags & STREAM_XPORT_OP_CONNECT_ASYNC ? 1 : 0, - timeout, &error_text, error_code TSRMLS_CC)) { - - ERR_RETURN(error_string, error_text, "connect() failed: %s"); - - failed = 1; - } - } - - } else { - /* server */ - if (flags & STREAM_XPORT_BIND) { - if (0 != php_stream_xport_bind(stream, name, namelen, &error_text TSRMLS_CC)) { - ERR_RETURN(error_string, error_text, "bind() failed: %s"); - failed = 1; - } else if (flags & STREAM_XPORT_LISTEN) { - if (0 != php_stream_xport_listen(stream, 5, &error_text TSRMLS_CC)) { - ERR_RETURN(error_string, error_text, "listen() failed: %s"); - failed = 1; - } - } - } - } - } - - if (failed) { - /* failure means that they don't get a stream to play with */ - php_stream_close(stream); - stream = NULL; - } - - return stream; -} - -/* Bind the stream to a local address */ -PHPAPI int php_stream_xport_bind(php_stream *stream, - const char *name, long namelen, - char **error_text - TSRMLS_DC) -{ - php_stream_xport_param param; - int ret; - - memset(¶m, 0, sizeof(param)); - param.op = STREAM_XPORT_OP_BIND; - param.inputs.name = (char*)name; - param.inputs.namelen = namelen; - param.want_errortext = error_text ? 1 : 0; - - ret = php_stream_set_option(stream, PHP_STREAM_OPTION_XPORT_API, 0, ¶m); - - if (ret == PHP_STREAM_OPTION_RETURN_OK) { - if (error_text) { - *error_text = param.outputs.error_text; - } - - return param.outputs.returncode; - } - - return ret; -} - -/* Connect to a remote address */ -PHPAPI int php_stream_xport_connect(php_stream *stream, - const char *name, long namelen, - int asynchronous, - struct timeval *timeout, - char **error_text, - int *error_code - TSRMLS_DC) -{ - php_stream_xport_param param; - int ret; - - memset(¶m, 0, sizeof(param)); - param.op = asynchronous ? STREAM_XPORT_OP_CONNECT_ASYNC: STREAM_XPORT_OP_CONNECT; - param.inputs.name = (char*)name; - param.inputs.namelen = namelen; - param.inputs.timeout = timeout; - - param.want_errortext = error_text ? 1 : 0; - - ret = php_stream_set_option(stream, PHP_STREAM_OPTION_XPORT_API, 0, ¶m); - - if (ret == PHP_STREAM_OPTION_RETURN_OK) { - if (error_text) { - *error_text = param.outputs.error_text; - } - if (error_code) { - *error_code = param.outputs.error_code; - } - return param.outputs.returncode; - } - - return ret; - -} - -/* Prepare to listen */ -PHPAPI int php_stream_xport_listen(php_stream *stream, int backlog, char **error_text TSRMLS_DC) -{ - php_stream_xport_param param; - int ret; - - memset(¶m, 0, sizeof(param)); - param.op = STREAM_XPORT_OP_LISTEN; - param.inputs.backlog = backlog; - param.want_errortext = error_text ? 1 : 0; - - ret = php_stream_set_option(stream, PHP_STREAM_OPTION_XPORT_API, 0, ¶m); - - if (ret == PHP_STREAM_OPTION_RETURN_OK) { - if (error_text) { - *error_text = param.outputs.error_text; - } - - return param.outputs.returncode; - } - - return ret; -} - -/* Get the next client and their address (as a string) */ -PHPAPI int php_stream_xport_accept(php_stream *stream, php_stream **client, - char **textaddr, int *textaddrlen, - void **addr, socklen_t *addrlen, - struct timeval *timeout, - char **error_text - TSRMLS_DC) -{ - php_stream_xport_param param; - int ret; - - memset(¶m, 0, sizeof(param)); - - param.op = STREAM_XPORT_OP_ACCEPT; - param.inputs.timeout = timeout; - param.want_addr = addr ? 1 : 0; - param.want_textaddr = textaddr ? 1 : 0; - param.want_errortext = error_text ? 1 : 0; - - ret = php_stream_set_option(stream, PHP_STREAM_OPTION_XPORT_API, 0, ¶m); - - if (ret == PHP_STREAM_OPTION_RETURN_OK) { - *client = param.outputs.client; - if (addr) { - *addr = param.outputs.addr; - *addrlen = param.outputs.addrlen; - } - if (textaddr) { - *textaddr = param.outputs.textaddr; - *textaddrlen = param.outputs.textaddrlen; - } - if (error_text) { - *error_text = param.outputs.error_text; - } - - return param.outputs.returncode; - } - return ret; -} - -PHPAPI int php_stream_xport_get_name(php_stream *stream, int want_peer, - char **textaddr, int *textaddrlen, - void **addr, socklen_t *addrlen - TSRMLS_DC) -{ - php_stream_xport_param param; - int ret; - - memset(¶m, 0, sizeof(param)); - - param.op = want_peer ? STREAM_XPORT_OP_GET_PEER_NAME : STREAM_XPORT_OP_GET_NAME; - param.want_addr = addr ? 1 : 0; - param.want_textaddr = textaddr ? 1 : 0; - - ret = php_stream_set_option(stream, PHP_STREAM_OPTION_XPORT_API, 0, ¶m); - - if (ret == PHP_STREAM_OPTION_RETURN_OK) { - if (addr) { - *addr = param.outputs.addr; - *addrlen = param.outputs.addrlen; - } - if (textaddr) { - *textaddr = param.outputs.textaddr; - *textaddrlen = param.outputs.textaddrlen; - } - - return param.outputs.returncode; - } - return ret; -} - -PHPAPI int php_stream_xport_crypto_setup(php_stream *stream, php_stream_xport_crypt_method_t crypto_method, php_stream *session_stream TSRMLS_DC) -{ - php_stream_xport_crypto_param param; - int ret; - - memset(¶m, 0, sizeof(param)); - param.op = STREAM_XPORT_CRYPTO_OP_SETUP; - param.inputs.method = crypto_method; - param.inputs.session = session_stream; - - ret = php_stream_set_option(stream, PHP_STREAM_OPTION_CRYPTO_API, 0, ¶m); - - if (ret == PHP_STREAM_OPTION_RETURN_OK) { - return param.outputs.returncode; - } - - php_error_docref("streams.crypto" TSRMLS_CC, E_WARNING, "this stream does not support SSL/crypto"); - - return ret; -} - -PHPAPI int php_stream_xport_crypto_enable(php_stream *stream, int activate TSRMLS_DC) -{ - php_stream_xport_crypto_param param; - int ret; - - memset(¶m, 0, sizeof(param)); - param.op = STREAM_XPORT_CRYPTO_OP_ENABLE; - param.inputs.activate = activate; - - ret = php_stream_set_option(stream, PHP_STREAM_OPTION_CRYPTO_API, 0, ¶m); - - if (ret == PHP_STREAM_OPTION_RETURN_OK) { - return param.outputs.returncode; - } - - php_error_docref("streams.crypto" TSRMLS_CC, E_WARNING, "this stream does not support SSL/crypto"); - - return ret; -} - -/* Similar to recv() system call; read data from the stream, optionally - * peeking, optionally retrieving OOB data */ -PHPAPI int php_stream_xport_recvfrom(php_stream *stream, char *buf, size_t buflen, - long flags, void **addr, socklen_t *addrlen, char **textaddr, int *textaddrlen - TSRMLS_DC) -{ - php_stream_xport_param param; - int ret = 0; - int recvd_len = 0; - int oob; - - if (flags == 0 && addr == NULL) { - return php_stream_read(stream, buf, buflen); - } - - if (stream->readfilters.head) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot peek or fetch OOB data from a filtered stream"); - return -1; - } - - oob = (flags & STREAM_OOB) == STREAM_OOB; - - if (!oob && addr == NULL) { - /* must be peeking at regular data; copy content from the buffer - * first, then adjust the pointer/len before handing off to the - * stream */ - recvd_len = stream->writepos - stream->readpos; - if (recvd_len > buflen) { - recvd_len = buflen; - } - if (recvd_len) { - memcpy(buf, stream->readbuf, recvd_len); - buf += recvd_len; - buflen -= recvd_len; - } - /* if we filled their buffer, return */ - if (buflen == 0) { - return recvd_len; - } - } - - /* otherwise, we are going to bypass the buffer */ - - memset(¶m, 0, sizeof(param)); - - param.op = STREAM_XPORT_OP_RECV; - param.want_addr = addr ? 1 : 0; - param.want_textaddr = textaddr ? 1 : 0; - param.inputs.buf = buf; - param.inputs.buflen = buflen; - param.inputs.flags = flags; - - ret = php_stream_set_option(stream, PHP_STREAM_OPTION_XPORT_API, 0, ¶m); - - if (ret == PHP_STREAM_OPTION_RETURN_OK) { - if (addr) { - *addr = param.outputs.addr; - *addrlen = param.outputs.addrlen; - } - if (textaddr) { - *textaddr = param.outputs.textaddr; - *textaddrlen = param.outputs.textaddrlen; - } - return recvd_len + param.outputs.returncode; - } - return recvd_len ? recvd_len : -1; -} - -/* Similar to send() system call; send data to the stream, optionally - * sending it as OOB data */ -PHPAPI int php_stream_xport_sendto(php_stream *stream, const char *buf, size_t buflen, - long flags, void *addr, socklen_t addrlen TSRMLS_DC) -{ - php_stream_xport_param param; - int ret = 0; - int oob; - - if (flags == 0 && addr == NULL) { - return php_stream_write(stream, buf, buflen); - } - - oob = (flags & STREAM_OOB) == STREAM_OOB; - - if ((oob || addr) && stream->writefilters.head) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot write OOB data, or data to a targeted address on a filtered stream"); - return -1; - } - - memset(¶m, 0, sizeof(param)); - - param.op = STREAM_XPORT_OP_SEND; - param.want_addr = addr ? 1 : 0; - param.inputs.buf = (char*)buf; - param.inputs.buflen = buflen; - param.inputs.flags = flags; - param.inputs.addr = addr; - param.inputs.addrlen = addrlen; - - ret = php_stream_set_option(stream, PHP_STREAM_OPTION_XPORT_API, 0, ¶m); - - if (ret == PHP_STREAM_OPTION_RETURN_OK) { - return param.outputs.returncode; - } - return -1; -} - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/main/streams/userspace.c b/main/streams/userspace.c deleted file mode 100644 index a016bb2abf..0000000000 --- a/main/streams/userspace.c +++ /dev/null @@ -1,1245 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Wez Furlong <wez@thebrainroom.com> | - | Sara Golemon <pollita@php.net> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#include "php.h" -#include "php_globals.h" -#include "ext/standard/file.h" - -static int le_protocols; - -struct php_user_stream_wrapper { - char * protoname; - char * classname; - zend_class_entry *ce; - php_stream_wrapper wrapper; -}; - -static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); -static int user_wrapper_stat_url(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC); -static int user_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC); -static int user_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC); -static int user_wrapper_mkdir(php_stream_wrapper *wrapper, char *url, int mode, int options, php_stream_context *context TSRMLS_DC); -static int user_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC); -static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, char *filename, char *mode, - int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); - -static php_stream_wrapper_ops user_stream_wops = { - user_wrapper_opener, - NULL, /* close - the streams themselves know how */ - NULL, /* stat - the streams themselves know how */ - user_wrapper_stat_url, - user_wrapper_opendir, - "user-space", - user_wrapper_unlink, - user_wrapper_rename, - user_wrapper_mkdir, - user_wrapper_rmdir -}; - - -static void stream_wrapper_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) -{ - struct php_user_stream_wrapper * uwrap = (struct php_user_stream_wrapper*)rsrc->ptr; - - php_unregister_url_stream_wrapper(uwrap->protoname TSRMLS_CC); - efree(uwrap->protoname); - efree(uwrap->classname); - efree(uwrap); -} - - -PHP_MINIT_FUNCTION(user_streams) -{ - le_protocols = zend_register_list_destructors_ex(stream_wrapper_dtor, NULL, "stream factory", 0); - if (le_protocols == FAILURE) - return FAILURE; - - REGISTER_LONG_CONSTANT("STREAM_USE_PATH", USE_PATH, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("STREAM_IGNORE_URL", IGNORE_URL, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("STREAM_ENFORCE_SAFE_MODE", ENFORCE_SAFE_MODE, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("STREAM_REPORT_ERRORS", REPORT_ERRORS, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("STREAM_MUST_SEEK", STREAM_MUST_SEEK, CONST_CS|CONST_PERSISTENT); - - REGISTER_LONG_CONSTANT("STREAM_URL_STAT_LINK", PHP_STREAM_URL_STAT_LINK, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("STREAM_URL_STAT_QUIET", PHP_STREAM_URL_STAT_QUIET, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("STREAM_MKDIR_RECURSIVE", PHP_STREAM_MKDIR_RECURSIVE, CONST_CS|CONST_PERSISTENT); - - return SUCCESS; -} - -struct _php_userstream_data { - struct php_user_stream_wrapper * wrapper; - zval * object; -}; -typedef struct _php_userstream_data php_userstream_data_t; - -/* names of methods */ -#define USERSTREAM_OPEN "stream_open" -#define USERSTREAM_CLOSE "stream_close" -#define USERSTREAM_READ "stream_read" -#define USERSTREAM_WRITE "stream_write" -#define USERSTREAM_FLUSH "stream_flush" -#define USERSTREAM_SEEK "stream_seek" -#define USERSTREAM_TELL "stream_tell" -#define USERSTREAM_EOF "stream_eof" -#define USERSTREAM_STAT "stream_stat" -#define USERSTREAM_STATURL "url_stat" -#define USERSTREAM_UNLINK "unlink" -#define USERSTREAM_RENAME "rename" -#define USERSTREAM_MKDIR "mkdir" -#define USERSTREAM_RMDIR "rmdir" -#define USERSTREAM_DIR_OPEN "dir_opendir" -#define USERSTREAM_DIR_READ "dir_readdir" -#define USERSTREAM_DIR_REWIND "dir_rewinddir" -#define USERSTREAM_DIR_CLOSE "dir_closedir" -#define USERSTREAM_LOCK "stream_lock" - -/* {{{ class should have methods like these: - - function stream_open($path, $mode, $options, &$opened_path) - { - return true/false; - } - - function stream_read($count) - { - return false on error; - else return string; - } - - function stream_write($data) - { - return false on error; - else return count written; - } - - function stream_close() - { - } - - function stream_flush() - { - return true/false; - } - - function stream_seek($offset, $whence) - { - return true/false; - } - - function stream_tell() - { - return (int)$position; - } - - function stream_eof() - { - return true/false; - } - - function stream_stat() - { - return array( just like that returned by fstat() ); - } - - function url_stat(string $url, int $flags) - { - return array( just like that returned by stat() ); - } - - function unlink(string $url) - { - return true / false; - } - - function rename(string $from, string $to) - { - return true / false; - } - - function mkdir($dir, $mode, $options) - { - return true / false; - } - - function rmdir($dir, $options) - { - return true / false; - } - - function dir_opendir(string $url, int $options) - { - return true / false; - } - - function dir_readdir() - { - return string next filename in dir ; - } - - function dir_closedir() - { - release dir related resources; - } - - function dir_rewinddir() - { - reset to start of dir list; - } - - }}} **/ - -static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) -{ - struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; - php_userstream_data_t *us; - zval *zfilename, *zmode, *zopened, *zoptions, *zretval = NULL, *zfuncname; - zval **args[4]; - int call_result; - php_stream *stream = NULL; - zval *zcontext = NULL; - - /* Try to catch bad usage without preventing flexibility */ - if (FG(user_stream_current_filename) != NULL && strcmp(filename, FG(user_stream_current_filename)) == 0) { - php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "infinite recursion prevented"); - return NULL; - } - FG(user_stream_current_filename) = filename; - - us = emalloc(sizeof(*us)); - us->wrapper = uwrap; - - /* create an instance of our class */ - ALLOC_ZVAL(us->object); - object_init_ex(us->object, uwrap->ce); - ZVAL_REFCOUNT(us->object) = 1; - PZVAL_IS_REF(us->object) = 1; - - if (context) { - MAKE_STD_ZVAL(zcontext); - php_stream_context_to_zval(context, zcontext); - add_property_zval(us->object, "context", zcontext); - /* The object property should be the only reference, - 'get rid' of our local reference. */ - zval_ptr_dtor(&zcontext); - } else { - add_property_null(us->object, "context"); - } - - /* call it's stream_open method - set up params first */ - MAKE_STD_ZVAL(zfilename); - ZVAL_STRING(zfilename, filename, 1); - args[0] = &zfilename; - - MAKE_STD_ZVAL(zmode); - ZVAL_STRING(zmode, mode, 1); - args[1] = &zmode; - - MAKE_STD_ZVAL(zoptions); - ZVAL_LONG(zoptions, options); - args[2] = &zoptions; - - MAKE_STD_ZVAL(zopened); - ZVAL_REFCOUNT(zopened) = 1; - PZVAL_IS_REF(zopened) = 1; - ZVAL_NULL(zopened); - args[3] = &zopened; - - MAKE_STD_ZVAL(zfuncname); - ZVAL_STRING(zfuncname, USERSTREAM_OPEN, 1); - - call_result = call_user_function_ex(NULL, - &us->object, - zfuncname, - &zretval, - 4, args, - 0, NULL TSRMLS_CC); - - if (call_result == SUCCESS && zretval != NULL && zval_is_true(zretval)) { - /* the stream is now open! */ - stream = php_stream_alloc_rel(&php_stream_userspace_ops, us, 0, mode); - - /* if the opened path is set, copy it out */ - if (Z_TYPE_P(zopened) == IS_STRING && opened_path) { - *opened_path = estrndup(Z_STRVAL_P(zopened), Z_STRLEN_P(zopened)); - } - - /* set wrapper data to be a reference to our object */ - stream->wrapperdata = us->object; - zval_add_ref(&stream->wrapperdata); - } else { - php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "\"%s::" USERSTREAM_OPEN "\" call failed", - us->wrapper->classname); - } - - /* destroy everything else */ - if (stream == NULL) { - zval_ptr_dtor(&us->object); - efree(us); - } - if (zretval) - zval_ptr_dtor(&zretval); - - zval_ptr_dtor(&zfuncname); - zval_ptr_dtor(&zopened); - zval_ptr_dtor(&zoptions); - zval_ptr_dtor(&zmode); - zval_ptr_dtor(&zfilename); - - FG(user_stream_current_filename) = NULL; - - return stream; -} - -static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, char *filename, char *mode, - int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) -{ - struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; - php_userstream_data_t *us; - zval *zfilename, *zoptions, *zretval = NULL, *zfuncname, *zcontext; - zval **args[2]; - int call_result; - php_stream *stream = NULL; - - /* Try to catch bad usage without preventing flexibility */ - if (FG(user_stream_current_filename) != NULL && strcmp(filename, FG(user_stream_current_filename)) == 0) { - php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "infinite recursion prevented"); - return NULL; - } - FG(user_stream_current_filename) = filename; - - us = emalloc(sizeof(*us)); - us->wrapper = uwrap; - - /* create an instance of our class */ - ALLOC_ZVAL(us->object); - object_init_ex(us->object, uwrap->ce); - ZVAL_REFCOUNT(us->object) = 1; - PZVAL_IS_REF(us->object) = 1; - - if (context) { - MAKE_STD_ZVAL(zcontext); - php_stream_context_to_zval(context, zcontext); - add_property_zval(us->object, "context", zcontext); - /* The object property should be the only reference, - 'get rid' of our local reference. */ - zval_ptr_dtor(&zcontext); - } else { - add_property_null(us->object, "context"); - } - - /* call it's dir_open method - set up params first */ - MAKE_STD_ZVAL(zfilename); - ZVAL_STRING(zfilename, filename, 1); - args[0] = &zfilename; - - MAKE_STD_ZVAL(zoptions); - ZVAL_LONG(zoptions, options); - args[1] = &zoptions; - - MAKE_STD_ZVAL(zfuncname); - ZVAL_STRING(zfuncname, USERSTREAM_DIR_OPEN, 1); - - call_result = call_user_function_ex(NULL, - &us->object, - zfuncname, - &zretval, - 2, args, - 0, NULL TSRMLS_CC); - - if (call_result == SUCCESS && zretval != NULL && zval_is_true(zretval)) { - /* the stream is now open! */ - stream = php_stream_alloc_rel(&php_stream_userspace_dir_ops, us, 0, mode); - - /* set wrapper data to be a reference to our object */ - stream->wrapperdata = us->object; - zval_add_ref(&stream->wrapperdata); - } else { - php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "\"%s::" USERSTREAM_DIR_OPEN "\" call failed", - us->wrapper->classname); - } - - /* destroy everything else */ - if (stream == NULL) { - zval_ptr_dtor(&us->object); - efree(us); - } - if (zretval) - zval_ptr_dtor(&zretval); - - zval_ptr_dtor(&zfuncname); - zval_ptr_dtor(&zoptions); - zval_ptr_dtor(&zfilename); - - FG(user_stream_current_filename) = NULL; - - return stream; -} - - -/* {{{ proto bool stream_wrapper_register(string protocol, string classname) - Registers a custom URL protocol handler class */ -PHP_FUNCTION(stream_wrapper_register) -{ - char *protocol, *classname; - int protocol_len, classname_len; - struct php_user_stream_wrapper * uwrap; - int rsrc_id; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &protocol, &protocol_len, &classname, &classname_len) == FAILURE) { - RETURN_FALSE; - } - - uwrap = (struct php_user_stream_wrapper *)ecalloc(1, sizeof(*uwrap)); - uwrap->protoname = estrndup(protocol, protocol_len); - uwrap->classname = estrndup(classname, classname_len); - uwrap->wrapper.wops = &user_stream_wops; - uwrap->wrapper.abstract = uwrap; - - zend_str_tolower(uwrap->classname, classname_len); - rsrc_id = ZEND_REGISTER_RESOURCE(NULL, uwrap, le_protocols); - - if (zend_hash_find(EG(class_table), uwrap->classname, classname_len + 1, (void**)&uwrap->ce) == SUCCESS) { -#ifdef ZEND_ENGINE_2 - uwrap->ce = *(zend_class_entry**)uwrap->ce; -#endif - if (php_register_url_stream_wrapper(protocol, &uwrap->wrapper TSRMLS_CC) == SUCCESS) { - RETURN_TRUE; - } - } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "class '%s' is undefined", - classname); - } - - zend_list_delete(rsrc_id); - RETURN_FALSE; -} -/* }}} */ - - -static size_t php_userstreamop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) -{ - zval func_name; - zval *retval = NULL; - int call_result; - php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; - zval **args[1]; - zval zbuff, *zbufptr; - size_t didwrite = 0; - - assert(us != NULL); - - ZVAL_STRINGL(&func_name, USERSTREAM_WRITE, sizeof(USERSTREAM_WRITE)-1, 0); - - ZVAL_STRINGL(&zbuff, (char*)buf, count, 0); - zbufptr = &zbuff; - args[0] = &zbufptr; - - call_result = call_user_function_ex(NULL, - &us->object, - &func_name, - &retval, - 1, args, - 0, NULL TSRMLS_CC); - - didwrite = 0; - if (call_result == SUCCESS && retval != NULL) { - convert_to_long(retval); - didwrite = Z_LVAL_P(retval); - } else if (call_result == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_WRITE " is not implemented!", - us->wrapper->classname); - } - - /* don't allow strange buffer overruns due to bogus return */ - if (didwrite > count) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_WRITE " wrote %zd bytes more data than requested (%zd written, %zd max)", - us->wrapper->classname, - didwrite - count, didwrite, count); - didwrite = count; - } - - if (retval) - zval_ptr_dtor(&retval); - - return didwrite; -} - -static size_t php_userstreamop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) -{ - zval func_name; - zval *retval = NULL; - zval **args[1]; - int call_result; - size_t didread = 0; - php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; - zval *zcount; - - assert(us != NULL); - - ZVAL_STRINGL(&func_name, USERSTREAM_READ, sizeof(USERSTREAM_READ)-1, 0); - - 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 %zd bytes more data than requested (%zd read, %zd 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); - - if (retval) { - zval_ptr_dtor(&retval); - retval = NULL; - } - - /* since the user stream has no way of setting the eof flag directly, we need to ask it if we hit eof */ - - 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)) { - stream->eof = 1; - } else if (call_result == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "%s::" USERSTREAM_EOF " is not implemented! Assuming EOF", - us->wrapper->classname); - - stream->eof = 1; - } - - if (retval) { - zval_ptr_dtor(&retval); - retval = NULL; - } - - return didread; -} - -static int php_userstreamop_close(php_stream *stream, int close_handle TSRMLS_DC) -{ - zval func_name; - zval *retval = NULL; - php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; - - assert(us != NULL); - - ZVAL_STRINGL(&func_name, USERSTREAM_CLOSE, sizeof(USERSTREAM_CLOSE)-1, 0); - - call_user_function_ex(NULL, - &us->object, - &func_name, - &retval, - 0, NULL, 0, NULL TSRMLS_CC); - - if (retval) - zval_ptr_dtor(&retval); - - zval_ptr_dtor(&us->object); - - efree(us); - - return 0; -} - -static int php_userstreamop_flush(php_stream *stream TSRMLS_DC) -{ - zval func_name; - zval *retval = NULL; - int call_result; - php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; - - assert(us != NULL); - - ZVAL_STRINGL(&func_name, USERSTREAM_FLUSH, sizeof(USERSTREAM_FLUSH)-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)) - call_result = 0; - else - call_result = -1; - - if (retval) - zval_ptr_dtor(&retval); - - return call_result; -} - -static int php_userstreamop_seek(php_stream *stream, off_t offset, int whence, off_t *newoffs TSRMLS_DC) -{ - zval func_name; - zval *retval = NULL; - int call_result, ret; - php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; - zval **args[2]; - zval *zoffs, *zwhence; - - assert(us != NULL); - - ZVAL_STRINGL(&func_name, USERSTREAM_SEEK, sizeof(USERSTREAM_SEEK)-1, 0); - - MAKE_STD_ZVAL(zoffs); - ZVAL_LONG(zoffs, offset); - args[0] = &zoffs; - - MAKE_STD_ZVAL(zwhence); - ZVAL_LONG(zwhence, whence); - args[1] = &zwhence; - - call_result = call_user_function_ex(NULL, - &us->object, - &func_name, - &retval, - 2, args, - 0, NULL TSRMLS_CC); - - zval_ptr_dtor(&zoffs); - zval_ptr_dtor(&zwhence); - - if (call_result == FAILURE) { - /* stream_seek is not implemented, so disable seeks for this stream */ - stream->flags |= PHP_STREAM_FLAG_NO_SEEK; - /* there should be no retval to clean up */ - - if (retval) - zval_ptr_dtor(&retval); - - return -1; - } else if (call_result == SUCCESS && retval != NULL && zval_is_true(retval)) { - ret = 0; - } else { - ret = -1; - } - - if (retval) { - zval_ptr_dtor(&retval); - retval = NULL; - } - - /* now determine where we are */ - ZVAL_STRINGL(&func_name, USERSTREAM_TELL, sizeof(USERSTREAM_TELL)-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 && Z_TYPE_P(retval) == IS_LONG) - *newoffs = Z_LVAL_P(retval); - else - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_TELL " is not implemented!", - us->wrapper->classname); - - if (retval) - zval_ptr_dtor(&retval); - - return 0; -} - -/* parse the return value from one of the stat functions and store the - * relevant fields into the statbuf provided */ -static int statbuf_from_array(zval *array, php_stream_statbuf *ssb TSRMLS_DC) -{ - zval **elem; - -#define STAT_PROP_ENTRY_EX(name, name2) \ - if (SUCCESS == zend_hash_find(Z_ARRVAL_P(array), #name, sizeof(#name), (void**)&elem)) { \ - convert_to_long(*elem); \ - ssb->sb.st_##name2 = Z_LVAL_PP(elem); \ - } - -#define STAT_PROP_ENTRY(name) STAT_PROP_ENTRY_EX(name,name) - - STAT_PROP_ENTRY(dev); - STAT_PROP_ENTRY(ino); - STAT_PROP_ENTRY(mode); - STAT_PROP_ENTRY(nlink); - STAT_PROP_ENTRY(uid); - STAT_PROP_ENTRY(gid); -#if HAVE_ST_RDEV - STAT_PROP_ENTRY(rdev); -#endif - STAT_PROP_ENTRY(size); -#if defined(NETWARE) && defined(CLIB_STAT_PATCH) - STAT_PROP_ENTRY_EX(atime, atime.tv_sec); - STAT_PROP_ENTRY_EX(mtime, mtime.tv_sec); - STAT_PROP_ENTRY_EX(ctime, ctime.tv_sec); -#else - STAT_PROP_ENTRY(atime); - STAT_PROP_ENTRY(mtime); - STAT_PROP_ENTRY(ctime); -#endif -#ifdef HAVE_ST_BLKSIZE - STAT_PROP_ENTRY(blksize); -#endif -#ifdef HAVE_ST_BLOCKS - STAT_PROP_ENTRY(blocks); -#endif - -#undef STAT_PROP_ENTRY -#undef STAT_PROP_ENTRY_EX - return SUCCESS; -} - -static int php_userstreamop_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC) -{ - zval func_name; - zval *retval = NULL; - int call_result; - php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; - int ret = -1; - - ZVAL_STRINGL(&func_name, USERSTREAM_STAT, sizeof(USERSTREAM_STAT)-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 && Z_TYPE_P(retval) == IS_ARRAY) { - if (SUCCESS == statbuf_from_array(retval, ssb TSRMLS_CC)) - ret = 0; - } else { - if (call_result == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_STAT " is not implemented!", - us->wrapper->classname); - } - } - - if (retval) - zval_ptr_dtor(&retval); - - return ret; -} - - -static int php_userstreamop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC) { - zval func_name; - zval *retval = NULL; - int call_result; - php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; - int ret = -1; - zval *zvalue; - zval **args[1]; - - MAKE_STD_ZVAL(zvalue); - ZVAL_LONG(zvalue, value); - args[0] = &zvalue; - - switch (option) { - case PHP_STREAM_OPTION_LOCKING: - // TODO wouldblock - ZVAL_STRINGL(&func_name, USERSTREAM_LOCK, sizeof(USERSTREAM_LOCK)-1, 0); - - call_result = call_user_function_ex(NULL, - &us->object, - &func_name, - &retval, - 1, args, 0, NULL TSRMLS_CC); - - if (call_result == SUCCESS && retval != NULL && Z_TYPE_P(retval) == IS_BOOL) { - ret = !Z_LVAL_P(retval); - } else if (call_result == FAILURE) { - if (value == 0) { - ret = 0; // lock support test (TODO: more check) - } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_LOCK " is not implemented!", - us->wrapper->classname); - } - } - - if (retval) - zval_ptr_dtor(&retval); - - break; - } - - /* clean up */ - zval_ptr_dtor(&zvalue); - - return ret; -} - - -static int user_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC) -{ - struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; - zval *zfilename, *zfuncname, *zretval, *zcontext; - zval **args[1]; - int call_result; - zval *object; - int ret = 0; - - /* create an instance of our class */ - ALLOC_ZVAL(object); - object_init_ex(object, uwrap->ce); - ZVAL_REFCOUNT(object) = 1; - PZVAL_IS_REF(object) = 1; - - if (context) { - MAKE_STD_ZVAL(zcontext); - php_stream_context_to_zval(context, zcontext); - add_property_zval(object, "context", zcontext); - /* The object property should be the only reference, - 'get rid' of our local reference. */ - zval_ptr_dtor(&zcontext); - } else { - add_property_null(object, "context"); - } - - /* call the unlink method */ - MAKE_STD_ZVAL(zfilename); - ZVAL_STRING(zfilename, url, 1); - args[0] = &zfilename; - - MAKE_STD_ZVAL(zfuncname); - ZVAL_STRING(zfuncname, USERSTREAM_UNLINK, 1); - - call_result = call_user_function_ex(NULL, - &object, - zfuncname, - &zretval, - 1, args, - 0, NULL TSRMLS_CC); - - if (call_result == SUCCESS && zretval && Z_TYPE_P(zretval) == IS_BOOL) { - ret = Z_LVAL_P(zretval); - } else if (call_result == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_UNLINK " is not implemented!", uwrap->classname); - } - - /* clean up */ - zval_ptr_dtor(&object); - if (zretval) - zval_ptr_dtor(&zretval); - - zval_ptr_dtor(&zfuncname); - zval_ptr_dtor(&zfilename); - - return ret; -} - -static int user_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC) -{ - struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; - zval *zold_name, *znew_name, *zfuncname, *zretval, *zcontext; - zval **args[2]; - int call_result; - zval *object; - int ret = 0; - - /* create an instance of our class */ - ALLOC_ZVAL(object); - object_init_ex(object, uwrap->ce); - ZVAL_REFCOUNT(object) = 1; - PZVAL_IS_REF(object) = 1; - - if (context) { - MAKE_STD_ZVAL(zcontext); - php_stream_context_to_zval(context, zcontext); - add_property_zval(object, "context", zcontext); - /* The object property should be the only reference, - 'get rid' of our local reference. */ - zval_ptr_dtor(&zcontext); - } else { - add_property_null(object, "context"); - } - - /* call the rename method */ - MAKE_STD_ZVAL(zold_name); - ZVAL_STRING(zold_name, url_from, 1); - args[0] = &zold_name; - - MAKE_STD_ZVAL(znew_name); - ZVAL_STRING(znew_name, url_to, 1); - args[1] = &znew_name; - - MAKE_STD_ZVAL(zfuncname); - ZVAL_STRING(zfuncname, USERSTREAM_RENAME, 1); - - call_result = call_user_function_ex(NULL, - &object, - zfuncname, - &zretval, - 2, args, - 0, NULL TSRMLS_CC); - - if (call_result == SUCCESS && zretval && Z_TYPE_P(zretval) == IS_BOOL) { - ret = Z_LVAL_P(zretval); - } else if (call_result == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_RENAME " is not implemented!", uwrap->classname); - } - - /* clean up */ - zval_ptr_dtor(&object); - if (zretval) - zval_ptr_dtor(&zretval); - - zval_ptr_dtor(&zfuncname); - zval_ptr_dtor(&zold_name); - zval_ptr_dtor(&znew_name); - - return ret; -} - -static int user_wrapper_mkdir(php_stream_wrapper *wrapper, char *url, int mode, int options, php_stream_context *context TSRMLS_DC) -{ - struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; - zval *zfilename, *zmode, *zoptions, *zfuncname, *zretval, *zcontext; - zval **args[3]; - int call_result; - zval *object; - int ret = 0; - - /* create an instance of our class */ - ALLOC_ZVAL(object); - object_init_ex(object, uwrap->ce); - ZVAL_REFCOUNT(object) = 1; - PZVAL_IS_REF(object) = 1; - - if (context) { - MAKE_STD_ZVAL(zcontext); - php_stream_context_to_zval(context, zcontext); - add_property_zval(object, "context", zcontext); - /* The object property should be the only reference, - 'get rid' of our local reference. */ - zval_ptr_dtor(&zcontext); - } else { - add_property_null(object, "context"); - } - - /* call the unlink method */ - MAKE_STD_ZVAL(zfilename); - ZVAL_STRING(zfilename, url, 1); - args[0] = &zfilename; - - MAKE_STD_ZVAL(zmode); - ZVAL_LONG(zmode, mode); - args[1] = &zmode; - - MAKE_STD_ZVAL(zoptions); - ZVAL_LONG(zoptions, options); - args[2] = &zoptions; - - MAKE_STD_ZVAL(zfuncname); - ZVAL_STRING(zfuncname, USERSTREAM_MKDIR, 1); - - call_result = call_user_function_ex(NULL, - &object, - zfuncname, - &zretval, - 3, args, - 0, NULL TSRMLS_CC); - - if (call_result == SUCCESS && zretval && Z_TYPE_P(zretval) == IS_BOOL) { - ret = Z_LVAL_P(zretval); - } else if (call_result == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_MKDIR " is not implemented!", uwrap->classname); - } - - /* clean up */ - zval_ptr_dtor(&object); - if (zretval) { - zval_ptr_dtor(&zretval); - } - - zval_ptr_dtor(&zfuncname); - zval_ptr_dtor(&zfilename); - zval_ptr_dtor(&zmode); - zval_ptr_dtor(&zoptions); - - return ret; -} - -static int user_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC) -{ - struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; - zval *zfilename, *zoptions, *zfuncname, *zretval, *zcontext; - zval **args[3]; - int call_result; - zval *object; - int ret = 0; - - /* create an instance of our class */ - ALLOC_ZVAL(object); - object_init_ex(object, uwrap->ce); - ZVAL_REFCOUNT(object) = 1; - PZVAL_IS_REF(object) = 1; - - if (context) { - MAKE_STD_ZVAL(zcontext); - php_stream_context_to_zval(context, zcontext); - add_property_zval(object, "context", zcontext); - /* The object property should be the only reference, - 'get rid' of our local reference. */ - zval_ptr_dtor(&zcontext); - } else { - add_property_null(object, "context"); - } - - /* call the unlink method */ - MAKE_STD_ZVAL(zfilename); - ZVAL_STRING(zfilename, url, 1); - args[0] = &zfilename; - - MAKE_STD_ZVAL(zoptions); - ZVAL_LONG(zoptions, options); - args[1] = &zoptions; - - MAKE_STD_ZVAL(zfuncname); - ZVAL_STRING(zfuncname, USERSTREAM_RMDIR, 1); - - call_result = call_user_function_ex(NULL, - &object, - zfuncname, - &zretval, - 2, args, - 0, NULL TSRMLS_CC); - - if (call_result == SUCCESS && zretval && Z_TYPE_P(zretval) == IS_BOOL) { - ret = Z_LVAL_P(zretval); - } else if (call_result == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_RMDIR " is not implemented!", uwrap->classname); - } - - /* clean up */ - zval_ptr_dtor(&object); - if (zretval) { - zval_ptr_dtor(&zretval); - } - - zval_ptr_dtor(&zfuncname); - zval_ptr_dtor(&zfilename); - zval_ptr_dtor(&zoptions); - - return ret; -} - -static int user_wrapper_stat_url(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC) -{ - struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; - zval *zfilename, *zfuncname, *zretval, *zflags, *zcontext; - zval **args[2]; - int call_result; - zval *object; - int ret = -1; - - /* create an instance of our class */ - ALLOC_ZVAL(object); - object_init_ex(object, uwrap->ce); - ZVAL_REFCOUNT(object) = 1; - PZVAL_IS_REF(object) = 1; - - if (context) { - MAKE_STD_ZVAL(zcontext); - php_stream_context_to_zval(context, zcontext); - add_property_zval(object, "context", zcontext); - /* The object property should be the only reference, - 'get rid' of our local reference. */ - zval_ptr_dtor(&zcontext); - } else { - add_property_null(object, "context"); - } - - /* call the stat_url method */ - - /* call it's stream_open method - set up params first */ - MAKE_STD_ZVAL(zfilename); - ZVAL_STRING(zfilename, url, 1); - args[0] = &zfilename; - - MAKE_STD_ZVAL(zflags); - ZVAL_LONG(zflags, flags); - args[1] = &zflags; - - MAKE_STD_ZVAL(zfuncname); - ZVAL_STRING(zfuncname, USERSTREAM_STATURL, 1); - - call_result = call_user_function_ex(NULL, - &object, - zfuncname, - &zretval, - 2, args, - 0, NULL TSRMLS_CC); - - if (call_result == SUCCESS && zretval != NULL && Z_TYPE_P(zretval) == IS_ARRAY) { - /* We got the info we needed */ - if (SUCCESS == statbuf_from_array(zretval, ssb TSRMLS_CC)) - ret = 0; - } else { - if (call_result == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_STATURL " is not implemented!", - uwrap->classname); - } - } - - /* clean up */ - zval_ptr_dtor(&object); - if (zretval) - zval_ptr_dtor(&zretval); - - zval_ptr_dtor(&zfuncname); - zval_ptr_dtor(&zfilename); - zval_ptr_dtor(&zflags); - - return ret; - -} - -static size_t php_userstreamop_readdir(php_stream *stream, char *buf, size_t count TSRMLS_DC) -{ - zval func_name; - zval *retval = NULL; - int call_result; - size_t didread = 0; - php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; - php_stream_dirent *ent = (php_stream_dirent*)buf; - - /* avoid problems if someone mis-uses the stream */ - if (count != sizeof(php_stream_dirent)) - return 0; - - ZVAL_STRINGL(&func_name, USERSTREAM_DIR_READ, sizeof(USERSTREAM_DIR_READ)-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 && Z_TYPE_P(retval) != IS_BOOL) { - convert_to_string(retval); - PHP_STRLCPY(ent->d_name, Z_STRVAL_P(retval), sizeof(ent->d_name), Z_STRLEN_P(retval)); - - didread = sizeof(php_stream_dirent); - } else if (call_result == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::" USERSTREAM_DIR_READ " is not implemented!", - us->wrapper->classname); - } - - if (retval) - zval_ptr_dtor(&retval); - - return didread; -} - -static int php_userstreamop_closedir(php_stream *stream, int close_handle TSRMLS_DC) -{ - zval func_name; - zval *retval = NULL; - php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; - - assert(us != NULL); - - ZVAL_STRINGL(&func_name, USERSTREAM_DIR_CLOSE, sizeof(USERSTREAM_DIR_CLOSE)-1, 0); - - call_user_function_ex(NULL, - &us->object, - &func_name, - &retval, - 0, NULL, 0, NULL TSRMLS_CC); - - if (retval) - zval_ptr_dtor(&retval); - - zval_ptr_dtor(&us->object); - - efree(us); - - return 0; -} - -static int php_userstreamop_rewinddir(php_stream *stream, off_t offset, int whence, off_t *newoffs TSRMLS_DC) -{ - zval func_name; - zval *retval = NULL; - zval **args[1]; - php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract; - - ZVAL_STRINGL(&func_name, USERSTREAM_DIR_REWIND, sizeof(USERSTREAM_DIR_REWIND)-1, 0); - - call_user_function_ex(NULL, - &us->object, - &func_name, - &retval, - 0, NULL, 0, NULL TSRMLS_CC); - - if (retval) - zval_ptr_dtor(&retval); - - return 0; - -} - -php_stream_ops php_stream_userspace_ops = { - php_userstreamop_write, php_userstreamop_read, - php_userstreamop_close, php_userstreamop_flush, - "user-space", - php_userstreamop_seek, - NULL, /* cast */ - php_userstreamop_stat, - php_userstreamop_set_option, -}; - -php_stream_ops php_stream_userspace_dir_ops = { - NULL, /* write */ - php_userstreamop_readdir, - php_userstreamop_closedir, - NULL, /* flush */ - "user-space-dir", - php_userstreamop_rewinddir, - NULL, /* cast */ - NULL, /* stat */ - NULL /* set_option */ -}; - - diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c deleted file mode 100644 index 00b20b2b63..0000000000 --- a/main/streams/xp_socket.c +++ /dev/null @@ -1,751 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2004 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.0 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_0.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Wez Furlong <wez@thebrainroom.com> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#include "php.h" -#include "ext/standard/file.h" -#include "streams/php_streams_int.h" -#include "php_network.h" - -#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE) -# undef AF_UNIX -#endif - -#if defined(AF_UNIX) -#include <sys/un.h> -#endif - -php_stream_ops php_stream_generic_socket_ops; -PHPAPI php_stream_ops php_stream_socket_ops; -php_stream_ops php_stream_udp_socket_ops; -#ifdef AF_UNIX -php_stream_ops php_stream_unix_socket_ops; -php_stream_ops php_stream_unixdg_socket_ops; -#endif - - -static int php_tcp_sockop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC); - -/* {{{ Generic socket stream operations */ -static size_t php_sockop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) -{ - php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; - int didwrite; - - if (sock->socket == -1) { - return 0; - } - - didwrite = send(sock->socket, buf, count, 0); - - if (didwrite <= 0) { - char *estr = php_socket_strerror(php_socket_errno(), NULL, 0); - - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "send of %d bytes failed with errno=%d %s", - count, php_socket_errno(), estr); - efree(estr); - } - - if (didwrite > 0) { - php_stream_notify_progress_increment(stream->context, didwrite, 0); - } - - if (didwrite < 0) { - didwrite = 0; - } - - return didwrite; -} - -static void php_sock_stream_wait_for_data(php_stream *stream, php_netstream_data_t *sock TSRMLS_DC) -{ - fd_set fdr, tfdr; - int retval; - struct timeval timeout, *ptimeout; - - if (sock->socket == -1) { - return; - } - - FD_ZERO(&fdr); - FD_SET(sock->socket, &fdr); - sock->timeout_event = 0; - - if (sock->timeout.tv_sec == -1) - ptimeout = NULL; - else - ptimeout = &timeout; - - - while(1) { - tfdr = fdr; - timeout = sock->timeout; - - retval = select(sock->socket + 1, &tfdr, NULL, NULL, ptimeout); - - if (retval == 0) - sock->timeout_event = 1; - - if (retval >= 0) - break; - } -} - -static size_t php_sockop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) -{ - php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; - int nr_bytes = 0; - - if (sock->socket == -1) { - return 0; - } - - if (sock->is_blocked) { - php_sock_stream_wait_for_data(stream, sock TSRMLS_CC); - if (sock->timeout_event) - return 0; - } - - nr_bytes = recv(sock->socket, buf, count, 0); - - stream->eof = (nr_bytes == 0 || (nr_bytes == -1 && php_socket_errno() != EWOULDBLOCK)); - - if (nr_bytes > 0) { - php_stream_notify_progress_increment(stream->context, nr_bytes, 0); - } - - if (nr_bytes < 0) { - nr_bytes = 0; - } - - return nr_bytes; -} - - -static int php_sockop_close(php_stream *stream, int close_handle TSRMLS_DC) -{ - php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; -#ifdef PHP_WIN32 - fd_set wrfds, efds; - int n; - struct timeval timeout; -#endif - - if (close_handle) { - - if (sock->socket != -1) { -#ifdef PHP_WIN32 - /* prevent more data from coming in */ - shutdown(sock->socket, SHUT_RD); - - /* try to make sure that the OS sends all data before we close the connection. - * Essentially, we are waiting for the socket to become writeable, which means - * that all pending data has been sent. - * We use a small timeout which should encourage the OS to send the data, - * but at the same time avoid hanging indefintely. - * */ - do { - FD_ZERO(&wrfds); - FD_SET(sock->socket, &wrfds); - efds = wrfds; - - timeout.tv_sec = 0; - timeout.tv_usec = 5000; /* arbitrary */ - - n = select(sock->socket + 1, NULL, &wrfds, &efds, &timeout); - } while (n == -1 && php_socket_errno() == EINTR); -#endif - - closesocket(sock->socket); - sock->socket = -1; - } - - } - - pefree(sock, php_stream_is_persistent(stream)); - - return 0; -} - -static int php_sockop_flush(php_stream *stream TSRMLS_DC) -{ - php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; - return fsync(sock->socket); -} - -static int php_sockop_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC) -{ - php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; - return fstat(sock->socket, &ssb->sb); -} - -static inline int sock_recvfrom(php_netstream_data_t *sock, char *buf, size_t buflen, int flags, - char **textaddr, long *textaddrlen, - struct sockaddr **addr, socklen_t *addrlen - TSRMLS_DC) -{ - php_sockaddr_storage sa; - socklen_t sl = sizeof(sa); - int ret; - int want_addr = textaddr || addr; - - if (want_addr) { - ret = recvfrom(sock->socket, buf, buflen, flags, (struct sockaddr*)&sa, &sl); - php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl, - textaddr, textaddrlen, addr, addrlen TSRMLS_CC); - } else { - ret = recv(sock->socket, buf, buflen, flags); - } - - return ret; -} - -static int php_sockop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC) -{ - int oldmode, flags; - php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; - php_stream_xport_param *xparam; - - switch(option) { - case PHP_STREAM_OPTION_CHECK_LIVENESS: - { - fd_set rfds; - struct timeval tv; - char buf; - int alive = 1; - - if (sock->timeout.tv_sec == -1) { - tv.tv_sec = FG(default_socket_timeout); - } else { - tv = sock->timeout; - } - - if (sock->socket == -1) { - alive = 0; - } else { - FD_ZERO(&rfds); - FD_SET(sock->socket, &rfds); - - if (select(sock->socket + 1, &rfds, NULL, NULL, &tv) > 0 && FD_ISSET(sock->socket, &rfds)) { - if (0 == recv(sock->socket, &buf, sizeof(buf), MSG_PEEK) && php_socket_errno() != EAGAIN) { - alive = 0; - } - } - } - return alive ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR; - } - - case PHP_STREAM_OPTION_BLOCKING: - - oldmode = sock->is_blocked; - - /* no need to change anything */ - if (value == oldmode) - return oldmode; - - if (SUCCESS == php_set_sock_blocking(sock->socket, value TSRMLS_CC)) { - sock->is_blocked = value; - return oldmode; - } - - return PHP_STREAM_OPTION_RETURN_ERR; - - case PHP_STREAM_OPTION_READ_TIMEOUT: - sock->timeout = *(struct timeval*)ptrparam; - sock->timeout_event = 0; - return PHP_STREAM_OPTION_RETURN_OK; - - case PHP_STREAM_OPTION_META_DATA_API: - add_assoc_bool((zval *)ptrparam, "timed_out", sock->timeout_event); - add_assoc_bool((zval *)ptrparam, "blocked", sock->is_blocked); - add_assoc_bool((zval *)ptrparam, "eof", stream->eof); - return PHP_STREAM_OPTION_RETURN_OK; - - case PHP_STREAM_OPTION_XPORT_API: - xparam = (php_stream_xport_param *)ptrparam; - - switch (xparam->op) { - case STREAM_XPORT_OP_LISTEN: - xparam->outputs.returncode = listen(sock->socket, 5); - return PHP_STREAM_OPTION_RETURN_OK; - - case STREAM_XPORT_OP_GET_NAME: - xparam->outputs.returncode = php_network_get_sock_name(sock->socket, - xparam->want_textaddr ? &xparam->outputs.textaddr : NULL, - xparam->want_textaddr ? &xparam->outputs.textaddrlen : NULL, - xparam->want_addr ? &xparam->outputs.addr : NULL, - xparam->want_addr ? &xparam->outputs.addrlen : NULL - TSRMLS_CC); - return PHP_STREAM_OPTION_RETURN_OK; - - case STREAM_XPORT_OP_GET_PEER_NAME: - xparam->outputs.returncode = php_network_get_peer_name(sock->socket, - xparam->want_textaddr ? &xparam->outputs.textaddr : NULL, - xparam->want_textaddr ? &xparam->outputs.textaddrlen : NULL, - xparam->want_addr ? &xparam->outputs.addr : NULL, - xparam->want_addr ? &xparam->outputs.addrlen : NULL - TSRMLS_CC); - return PHP_STREAM_OPTION_RETURN_OK; - - case STREAM_XPORT_OP_SEND: - flags = 0; - if ((xparam->inputs.flags & STREAM_OOB) == STREAM_OOB) { - flags |= MSG_OOB; - } - xparam->outputs.returncode = sendto(sock->socket, - xparam->inputs.buf, xparam->inputs.buflen, - flags, - xparam->inputs.addr, - xparam->inputs.addrlen); - if (xparam->outputs.returncode == -1) { - char *err = php_socket_strerror(php_socket_errno(), NULL, 0); - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "%s\n", err); - efree(err); - } - return PHP_STREAM_OPTION_RETURN_OK; - - case STREAM_XPORT_OP_RECV: - flags = 0; - if ((xparam->inputs.flags & STREAM_OOB) == STREAM_OOB) { - flags |= MSG_OOB; - } - if ((xparam->inputs.flags & STREAM_PEEK) == STREAM_PEEK) { - flags |= MSG_PEEK; - } - xparam->outputs.returncode = sock_recvfrom(sock, - xparam->inputs.buf, xparam->inputs.buflen, - flags, - xparam->want_textaddr ? &xparam->outputs.textaddr : NULL, - xparam->want_textaddr ? &xparam->outputs.textaddrlen : NULL, - xparam->want_addr ? &xparam->outputs.addr : NULL, - xparam->want_addr ? &xparam->outputs.addrlen : NULL - TSRMLS_CC); - return PHP_STREAM_OPTION_RETURN_OK; - - - default: - return PHP_STREAM_OPTION_RETURN_NOTIMPL; - } - - default: - return PHP_STREAM_OPTION_RETURN_NOTIMPL; - } -} - -static int php_sockop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC) -{ - php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; - - switch(castas) { - case PHP_STREAM_AS_STDIO: - if (ret) { - *(FILE**)ret = fdopen(sock->socket, stream->mode); - if (*ret) - return SUCCESS; - return FAILURE; - } - return SUCCESS; - case PHP_STREAM_AS_FD_FOR_SELECT: - case PHP_STREAM_AS_FD: - case PHP_STREAM_AS_SOCKETD: - if (ret) - *(int*)ret = sock->socket; - return SUCCESS; - default: - return FAILURE; - } -} -/* }}} */ - -/* These may look identical, but we need them this way so that - * we can determine which type of socket we are dealing with - * by inspecting stream->ops. - * A "useful" side-effect is that the user's scripts can then - * make similar decisions using stream_get_meta_data. - * */ -php_stream_ops php_stream_generic_socket_ops = { - php_sockop_write, php_sockop_read, - php_sockop_close, php_sockop_flush, - "generic_socket", - NULL, /* seek */ - php_sockop_cast, - php_sockop_stat, - php_sockop_set_option, -}; - - -php_stream_ops php_stream_socket_ops = { - php_sockop_write, php_sockop_read, - php_sockop_close, php_sockop_flush, - "tcp_socket", - NULL, /* seek */ - php_sockop_cast, - php_sockop_stat, - php_tcp_sockop_set_option, -}; - -php_stream_ops php_stream_udp_socket_ops = { - php_sockop_write, php_sockop_read, - php_sockop_close, php_sockop_flush, - "udp_socket", - NULL, /* seek */ - php_sockop_cast, - php_sockop_stat, - php_tcp_sockop_set_option, -}; - -#ifdef AF_UNIX -php_stream_ops php_stream_unix_socket_ops = { - php_sockop_write, php_sockop_read, - php_sockop_close, php_sockop_flush, - "unix_socket", - NULL, /* seek */ - php_sockop_cast, - php_sockop_stat, - php_tcp_sockop_set_option, -}; -php_stream_ops php_stream_unixdg_socket_ops = { - php_sockop_write, php_sockop_read, - php_sockop_close, php_sockop_flush, - "udg_socket", - NULL, /* seek */ - php_sockop_cast, - php_sockop_stat, - php_tcp_sockop_set_option, -}; -#endif - - -/* network socket operations */ - -#ifdef AF_UNIX -static inline int parse_unix_address(php_stream_xport_param *xparam, struct sockaddr_un *unix_addr TSRMLS_DC) -{ - memset(unix_addr, 0, sizeof(*unix_addr)); - unix_addr->sun_family = AF_UNIX; - - /* we need to be binary safe on systems that support an abstract - * namespace */ - if (xparam->inputs.namelen >= sizeof(unix_addr->sun_path)) { - /* On linux, when the path begins with a NUL byte we are - * referring to an abstract namespace. In theory we should - * allow an extra byte below, since we don't need the NULL. - * BUT, to get into this branch of code, the name is too long, - * so we don't care. */ - xparam->inputs.namelen = sizeof(unix_addr->sun_path) - 1; - } - - memcpy(unix_addr->sun_path, xparam->inputs.name, xparam->inputs.namelen); - - return 1; -} -#endif - -static inline char *parse_ip_address(php_stream_xport_param *xparam, int *portno TSRMLS_DC) -{ - char *colon; - char *host = NULL; - -#ifdef HAVE_IPV6 - char *p; - - if (*(xparam->inputs.name) == '[') { - /* IPV6 notation to specify raw address with port (i.e. [fe80::1]:80) */ - p = memchr(xparam->inputs.name + 1, ']', xparam->inputs.namelen - 2); - if (!p || *(p + 1) != ':') { - if (xparam->want_errortext) { - spprintf(&xparam->outputs.error_text, 0, "Failed to parse IPv6 address \"%s\"", xparam->inputs.name); - } - return NULL; - } - *portno = atoi(p + 2); - return estrndup(xparam->inputs.name + 1, p - xparam->inputs.name - 1); - } -#endif - - colon = memchr(xparam->inputs.name, ':', xparam->inputs.namelen - 1); - if (colon) { - *portno = atoi(colon + 1); - host = estrndup(xparam->inputs.name, colon - xparam->inputs.name); - } else { - if (xparam->want_errortext) { - spprintf(&xparam->outputs.error_text, 0, "Failed to parse address \"%s\"", xparam->inputs.name); - } - return NULL; - } - - return host; -} - -static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t *sock, - php_stream_xport_param *xparam TSRMLS_DC) -{ - char *host = NULL; - int portno, err; - -#ifdef AF_UNIX - if (stream->ops == &php_stream_unix_socket_ops || stream->ops == &php_stream_unixdg_socket_ops) { - struct sockaddr_un unix_addr; - - sock->socket = socket(PF_UNIX, stream->ops == &php_stream_unix_socket_ops ? SOCK_STREAM : SOCK_DGRAM, 0); - - if (sock->socket == SOCK_ERR) { - if (xparam->want_errortext) { - spprintf(&xparam->outputs.error_text, 0, "Failed to create unix%s socket %s", - stream->ops == &php_stream_unix_socket_ops ? "" : "datagram", - strerror(errno)); - } - return -1; - } - - parse_unix_address(xparam, &unix_addr TSRMLS_CC); - - return bind(sock->socket, (struct sockaddr *)&unix_addr, sizeof(unix_addr)); - } -#endif - - host = parse_ip_address(xparam, &portno TSRMLS_CC); - - if (host == NULL) { - return -1; - } - - sock->socket = php_network_bind_socket_to_local_addr(host, portno, - stream->ops == &php_stream_udp_socket_ops ? SOCK_DGRAM : SOCK_STREAM, - xparam->want_errortext ? &xparam->outputs.error_text : NULL, - &err - TSRMLS_CC); - - if (host) { - efree(host); - } - - return sock->socket == -1 ? -1 : 0; -} - -static inline int php_tcp_sockop_connect(php_stream *stream, php_netstream_data_t *sock, - php_stream_xport_param *xparam TSRMLS_DC) -{ - char *host = NULL; - int portno; - int err; - int ret; - -#ifdef AF_UNIX - if (stream->ops == &php_stream_unix_socket_ops || stream->ops == &php_stream_unixdg_socket_ops) { - struct sockaddr_un unix_addr; - - sock->socket = socket(PF_UNIX, stream->ops == &php_stream_unix_socket_ops ? SOCK_STREAM : SOCK_DGRAM, 0); - - if (sock->socket == SOCK_ERR) { - if (xparam->want_errortext) { - spprintf(&xparam->outputs.error_text, 0, "Failed to create unix socket"); - } - return -1; - } - - parse_unix_address(xparam, &unix_addr TSRMLS_CC); - - ret = php_network_connect_socket(sock->socket, - (const struct sockaddr *)&unix_addr, (socklen_t)sizeof(unix_addr), - xparam->op == STREAM_XPORT_OP_CONNECT_ASYNC, xparam->inputs.timeout, - xparam->want_errortext ? &xparam->outputs.error_text : NULL, - &err); - - xparam->outputs.error_code = err; - - goto out; - } -#endif - - host = parse_ip_address(xparam, &portno TSRMLS_CC); - - if (host == NULL) { - return -1; - } - - /* Note: the test here for php_stream_udp_socket_ops is important, because we - * want the default to be TCP sockets so that the openssl extension can - * re-use this code. */ - - sock->socket = php_network_connect_socket_to_host(host, portno, - stream->ops == &php_stream_udp_socket_ops ? SOCK_DGRAM : SOCK_STREAM, - xparam->op == STREAM_XPORT_OP_CONNECT_ASYNC, - xparam->inputs.timeout, - xparam->want_errortext ? &xparam->outputs.error_text : NULL, - &err - TSRMLS_CC); - - ret = sock->socket == -1 ? -1 : 0; - xparam->outputs.error_code = err; - - if (host) { - efree(host); - } - -#ifdef AF_UNIX -out: -#endif - - if (ret >= 0 && xparam->op == STREAM_XPORT_OP_CONNECT_ASYNC && err == EINPROGRESS) { - /* indicates pending connection */ - return 1; - } - - return ret; -} - -static inline int php_tcp_sockop_accept(php_stream *stream, php_netstream_data_t *sock, - php_stream_xport_param *xparam STREAMS_DC TSRMLS_DC) -{ - int clisock; - - xparam->outputs.client = NULL; - - clisock = php_network_accept_incoming(sock->socket, - xparam->want_textaddr ? &xparam->outputs.textaddr : NULL, - xparam->want_textaddr ? &xparam->outputs.textaddrlen : NULL, - xparam->want_addr ? &xparam->outputs.addr : NULL, - xparam->want_addr ? &xparam->outputs.addrlen : NULL, - xparam->inputs.timeout, - xparam->want_errortext ? &xparam->outputs.error_text : NULL, - &xparam->outputs.error_code - TSRMLS_CC); - - if (clisock >= 0) { - php_netstream_data_t *clisockdata; - - clisockdata = emalloc(sizeof(*clisockdata)); - - if (clisockdata == NULL) { - close(clisock); - /* technically a fatal error */ - } else { - memcpy(clisockdata, sock, sizeof(*clisockdata)); - clisockdata->socket = clisock; - - xparam->outputs.client = php_stream_alloc_rel(stream->ops, clisockdata, NULL, "r+"); - if (xparam->outputs.client) { - /* TODO: addref ? */ - xparam->outputs.client->context = stream->context; - } - } - } - - return xparam->outputs.client == NULL ? -1 : 0; -} - -static int php_tcp_sockop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC) -{ - php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; - php_stream_xport_param *xparam; - - switch(option) { - case PHP_STREAM_OPTION_XPORT_API: - xparam = (php_stream_xport_param *)ptrparam; - - switch(xparam->op) { - case STREAM_XPORT_OP_CONNECT: - case STREAM_XPORT_OP_CONNECT_ASYNC: - xparam->outputs.returncode = php_tcp_sockop_connect(stream, sock, xparam TSRMLS_CC); - return PHP_STREAM_OPTION_RETURN_OK; - - case STREAM_XPORT_OP_BIND: - xparam->outputs.returncode = php_tcp_sockop_bind(stream, sock, xparam TSRMLS_CC); - return PHP_STREAM_OPTION_RETURN_OK; - - - case STREAM_XPORT_OP_ACCEPT: - xparam->outputs.returncode = php_tcp_sockop_accept(stream, sock, xparam STREAMS_CC TSRMLS_CC); - return PHP_STREAM_OPTION_RETURN_OK; - default: - /* fall through */ - ; - } - - /* fall through */ - default: - return php_sockop_set_option(stream, option, value, ptrparam TSRMLS_CC); - } -} - - -PHPAPI php_stream *php_stream_generic_socket_factory(const char *proto, long protolen, - char *resourcename, long resourcenamelen, - const char *persistent_id, int options, int flags, - struct timeval *timeout, - php_stream_context *context STREAMS_DC TSRMLS_DC) -{ - php_stream *stream = NULL; - php_netstream_data_t *sock; - php_stream_ops *ops; - - /* which type of socket ? */ - if (strncmp(proto, "tcp", protolen) == 0) { - ops = &php_stream_socket_ops; - } else if (strncmp(proto, "udp", protolen) == 0) { - ops = &php_stream_udp_socket_ops; - } -#ifdef AF_UNIX - else if (strncmp(proto, "unix", protolen) == 0) { - ops = &php_stream_unix_socket_ops; - } else if (strncmp(proto, "udg", protolen) == 0) { - ops = &php_stream_unixdg_socket_ops; - } -#endif - else { - /* should never happen */ - return NULL; - } - - sock = pemalloc(sizeof(php_netstream_data_t), persistent_id ? 1 : 0); - memset(sock, 0, sizeof(php_netstream_data_t)); - - sock->is_blocked = 1; - sock->timeout.tv_sec = FG(default_socket_timeout); - sock->timeout.tv_usec = 0; - - /* we don't know the socket until we have determined if we are binding or - * connecting */ - sock->socket = -1; - - stream = php_stream_alloc_rel(ops, sock, persistent_id, "r+"); - - if (stream == NULL) { - pefree(sock, persistent_id ? 1 : 0); - return NULL; - } - - if (flags == 0) { - return stream; - } - - return stream; -} - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ |