diff options
Diffstat (limited to 'main')
| -rw-r--r-- | main/memory_streams.c | 6 | ||||
| -rw-r--r-- | main/network.c | 9 | ||||
| -rwxr-xr-x | main/php_streams.h | 23 | ||||
| -rwxr-xr-x | main/streams.c | 68 | ||||
| -rw-r--r-- | main/user_streams.c | 5 |
5 files changed, 96 insertions, 15 deletions
diff --git a/main/memory_streams.c b/main/memory_streams.c index 65d4956b04..fdd074903f 100644 --- a/main/memory_streams.c +++ b/main/memory_streams.c @@ -232,10 +232,11 @@ static int php_stream_memory_cast(php_stream *stream, int castas, void **ret TSR 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_gets, php_stream_memory_cast, - "MEMORY" + NULL }; @@ -448,10 +449,11 @@ static int php_stream_temp_cast(php_stream *stream, int castas, void **ret TSRML 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_gets, php_stream_temp_cast, - "TEMP" + NULL }; diff --git a/main/network.c b/main/network.c index be15ae2677..7ed301a654 100644 --- a/main/network.c +++ b/main/network.c @@ -768,6 +768,12 @@ static int php_sockop_flush(php_stream *stream TSRMLS_DC) 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 int php_sockop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC) { php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; @@ -869,9 +875,10 @@ static char *php_sockop_gets(php_stream *stream, char *buf, size_t maxlen TSRMLS php_stream_ops php_stream_socket_ops = { php_sockop_write, php_sockop_read, php_sockop_close, php_sockop_flush, + "socket", NULL, php_sockop_gets, php_sockop_cast, - "socket" + php_sockop_stat }; diff --git a/main/php_streams.h b/main/php_streams.h index c8e05fd091..2243f07de4 100755 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -22,6 +22,8 @@ #ifdef HAVE_SYS_TIME_H #include <sys/time.h> #endif +#include <sys/types.h> +#include <sys/stat.h> /* See README.STREAMS in php4 root dir for more info about this stuff */ @@ -88,23 +90,37 @@ typedef struct _php_stream php_stream; typedef struct _php_stream_wrapper php_stream_wrapper; +typedef struct _php_stream_statbuf { + struct stat sb; /* regular info */ + /* extended info to go here some day */ +} php_stream_statbuf; + typedef struct _php_stream_ops { /* stdio like functions - these are mandatory! */ size_t (*write)(php_stream *stream, const char *buf, size_t count TSRMLS_DC); size_t (*read)(php_stream *stream, char *buf, size_t count TSRMLS_DC); int (*close)(php_stream *stream, int close_handle TSRMLS_DC); int (*flush)(php_stream *stream TSRMLS_DC); + + const char *label; /* label for this ops structure */ + /* these are optional */ int (*seek)(php_stream *stream, off_t offset, int whence TSRMLS_DC); char *(*gets)(php_stream *stream, char *buf, size_t size TSRMLS_DC); int (*cast)(php_stream *stream, int castas, void **ret TSRMLS_DC); - const char *label; /* label for this ops structure */ + int (*stat)(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC); } php_stream_ops; typedef struct _php_stream_wrapper_ops { + /* open/create a wrapped stream */ php_stream *(*opener)(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC); - php_stream *(*closer)(php_stream_wrapper *wrapper, php_stream *stream TSRMLS_DC); + /* close/destroy a wrapped stream */ + int (*closer)(php_stream_wrapper *wrapper, php_stream *stream TSRMLS_DC); + /* stat a wrapped stream */ + int (*stream_stat)(php_stream_wrapper *wrapper, php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC); + /* stat a URL */ + int (*url_stat)(php_stream_wrapper *wrapper, php_stream_statbuf *ssb TSRMLS_DC); } php_stream_wrapper_ops; struct _php_stream_wrapper { @@ -199,6 +215,9 @@ PHPAPI char *_php_stream_gets(php_stream *stream, char *buf, size_t maxlen TSRML PHPAPI int _php_stream_puts(php_stream *stream, char *buf TSRMLS_DC); #define php_stream_puts(stream, buf) _php_stream_puts((stream), (buf) TSRMLS_CC) +PHPAPI int _php_stream_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC); +#define php_stream_stat(stream, ssb) _php_stream_stat((stream), (ssb) TSRMLS_CC) + /* copy up to maxlen bytes from src to dest. If maxlen is PHP_STREAM_COPY_ALL, copy until eof(src). * Uses mmap if the src is a plain file and at offset 0 */ #define PHP_STREAM_COPY_ALL -1 diff --git a/main/streams.c b/main/streams.c index 8f366af0d5..52431cd1da 100755 --- a/main/streams.c +++ b/main/streams.c @@ -43,6 +43,8 @@ #include "build-defs.h" #endif +#define STREAM_DEBUG 0 + /* {{{ some macros to help track leaks */ #if ZEND_DEBUG #define emalloc_rel_orig(size) \ @@ -76,6 +78,10 @@ PHPAPI php_stream *_php_stream_alloc(php_stream_ops *ops, void *abstract, int pe memset(ret, 0, sizeof(php_stream)); +#if STREAM_DEBUG +fprintf(stderr, "stream_alloc: %s:%p\n", ops->label, ret); +#endif + ret->ops = ops; ret->abstract = abstract; ret->is_persistent = persistent; @@ -90,6 +96,10 @@ PHPAPI int _php_stream_free(php_stream *stream, int close_options TSRMLS_DC) /* { int ret = 1; +#if STREAM_DEBUG +fprintf(stderr, "stream_free: %s:%p in_free=%d opts=%08x\n", stream->ops->label, stream, stream->in_free, close_options); +#endif + if (stream->in_free) return 1; @@ -112,8 +122,6 @@ PHPAPI int _php_stream_free(php_stream *stream, int close_options TSRMLS_DC) /* return fclose(stream->stdiocast); } - php_stream_flush(stream); - ret = stream->ops->close(stream, close_options & PHP_STREAM_FREE_PRESERVE_HANDLE ? 0 : 1 TSRMLS_CC); stream->abstract = NULL; @@ -126,7 +134,7 @@ PHPAPI int _php_stream_free(php_stream *stream, int close_options TSRMLS_DC) /* if (close_options & PHP_STREAM_FREE_RELEASE_STREAM) { - if (stream->wrapper && stream->wrapper->wops->closer) { + if (stream->wrapper && stream->wrapper->wops && stream->wrapper->wops->closer) { stream->wrapper->wops->closer(stream->wrapper, stream TSRMLS_CC); stream->wrapper = NULL; } @@ -204,6 +212,26 @@ PHPAPI int _php_stream_puts(php_stream *stream, char *buf TSRMLS_DC) 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_gets(php_stream *stream, char *buf, size_t maxlen TSRMLS_DC) { @@ -367,20 +395,29 @@ PHPAPI size_t _php_stream_copy_to_mem(php_stream *src, char **buf, size_t maxlen if (fstat(srcfd, &sbuf) == 0) { void *srcfile; +#if STREAM_DEBUG + fprintf(stderr, "mmap attempt: maxlen=%d filesize=%d\n", maxlen, sbuf.st_size); +#endif + if (maxlen > sbuf.st_size || maxlen == 0) maxlen = sbuf.st_size; - +#if STREAM_DEBUG + fprintf(stderr, "mmap attempt: will map maxlen=%d\n", maxlen); +#endif + srcfile = mmap(NULL, maxlen, PROT_READ, MAP_SHARED, srcfd, 0); if (srcfile != (void*)MAP_FAILED) { - *buf = pemalloc_rel_orig(persistent, maxlen); + *buf = pemalloc_rel_orig(maxlen + 1, persistent); if (*buf) { memcpy(*buf, srcfile, maxlen); + (*buf)[maxlen] = '\0'; ret = maxlen; } munmap(srcfile, maxlen); + return ret; } } @@ -388,7 +425,7 @@ PHPAPI size_t _php_stream_copy_to_mem(php_stream *src, char **buf, size_t maxlen } #endif - ptr = *buf = pemalloc_rel_orig(persistent, step); + ptr = *buf = pemalloc_rel_orig(step, persistent); max_len = step; while((ret = php_stream_read(src, ptr, max_len - len))) { @@ -687,11 +724,25 @@ static int php_stdiop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC) } } +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); + + fd = fileno(data->file); + + return fstat(fd, &ssb->sb); +} + php_stream_ops php_stream_stdio_ops = { php_stdiop_write, php_stdiop_read, - php_stdiop_close, php_stdiop_flush, php_stdiop_seek, + php_stdiop_close, php_stdiop_flush, + "STDIO", + php_stdiop_seek, php_stdiop_gets, php_stdiop_cast, - "STDIO" + php_stdiop_stat }; /* }}} */ @@ -850,7 +901,6 @@ 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; } diff --git a/main/user_streams.c b/main/user_streams.c index 53bb3863cc..fe81d7c10f 100644 --- a/main/user_streams.c +++ b/main/user_streams.c @@ -33,6 +33,8 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filena static php_stream_wrapper_ops user_stream_wops = { user_wrapper_opener, + NULL, + NULL, NULL }; @@ -504,9 +506,10 @@ static char *php_userstreamop_gets(php_stream *stream, char *buf, size_t size TS php_stream_ops php_stream_userspace_ops = { php_userstreamop_write, php_userstreamop_read, php_userstreamop_close, php_userstreamop_flush, + "user-space", php_userstreamop_seek, php_userstreamop_gets, NULL, /* cast */ - "user-space" + NULL /* stat */ }; |
