summaryrefslogtreecommitdiff
path: root/main/streams/streams.c
diff options
context:
space:
mode:
authorWez Furlong <wez@php.net>2003-02-27 17:43:38 +0000
committerWez Furlong <wez@php.net>2003-02-27 17:43:38 +0000
commitfd61f69077f6156ca71dde60ecfd9ed9765a02db (patch)
tree7285ad393cdb5a85107a3329d1ab2bcafe89f051 /main/streams/streams.c
parent560e33968de93250377606782949f5004affca83 (diff)
downloadphp-git-fd61f69077f6156ca71dde60ecfd9ed9765a02db.tar.gz
Another big commit (tm).
Main Changes: - Implement a socket transport layer for use by all code that needs to open some kind of "special" socket for network or IPC. - Extensions can register (and override) transports. - Implement ftruncate() on streams via the ioctl-alike option interface. - Implement mmap() on streams via the ioctl-alike option interface. - Implement generic crypto API via the ioctl-alike option interface. (currently only supports OpenSSL, but could support other SSL toolkits, and other crypto transport protocols). Impact: - tcp sockets can be overloaded by the openssl capable sockets at runtime, removing the link-time requirement for ssl:// and https:// sockets and streams. - checking stream types using PHP_STREAM_IS_SOCKET is deprecated, since there are now a range of possible socket-type streams. Working towards: - socket servers using the new transport layer - mmap support under win32 - Cleaner code. # I will be updating the win32 build to add the new files shortly # after this commit.
Diffstat (limited to 'main/streams/streams.c')
-rwxr-xr-xmain/streams/streams.c200
1 files changed, 71 insertions, 129 deletions
diff --git a/main/streams/streams.c b/main/streams/streams.c
index e798684d18..b46dcc97aa 100755
--- a/main/streams/streams.c
+++ b/main/streams/streams.c
@@ -29,9 +29,6 @@
#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() */
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
#include <stddef.h>
#include <fcntl.h>
#include "php_streams_int.h"
@@ -103,7 +100,7 @@ PHPAPI int php_stream_from_persistent_id(const char *persistent_id, php_stream *
/* }}} */
/* {{{ wrapper error reporting */
-static void display_wrapper_errors(php_stream_wrapper *wrapper, const char *path, const char *caption TSRMLS_DC)
+void php_stream_display_wrapper_errors(php_stream_wrapper *wrapper, const char *path, const char *caption TSRMLS_DC)
{
char *tmp = estrdup(path);
char *msg;
@@ -152,7 +149,7 @@ static void display_wrapper_errors(php_stream_wrapper *wrapper, const char *path
efree(msg);
}
-static void tidy_wrapper_error_log(php_stream_wrapper *wrapper TSRMLS_DC)
+void php_stream_tidy_wrapper_error_log(php_stream_wrapper *wrapper TSRMLS_DC)
{
if (wrapper) {
/* tidy up the error stack */
@@ -1061,52 +1058,37 @@ PHPAPI int _php_stream_set_option(php_stream *stream, int option, int value, voi
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;
- int ready = 0;
char buf[8192];
-#ifdef HAVE_MMAP
- int fd;
-#endif
+ int b;
-#ifdef HAVE_MMAP
- if (!php_stream_is(stream, PHP_STREAM_IS_SOCKET)
- && !php_stream_is_filtered(stream)
- && php_stream_tell(stream) == 0
- && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&fd, 0))
- {
- struct stat sbuf;
- off_t off;
- void *p;
- size_t len;
-
- fstat(fd, &sbuf);
-
- if (sbuf.st_size > sizeof(buf)) {
- off = php_stream_tell(stream);
- len = sbuf.st_size - off;
- p = mmap(0, len, PROT_READ, MAP_SHARED, fd, off);
- if (p != (void *) MAP_FAILED) {
- BG(mmap_file) = p;
- BG(mmap_len) = len;
- PHPWRITE(p, len);
- BG(mmap_file) = NULL;
- munmap(p, len);
- bcount += len;
- ready = 1;
- }
+ 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;
}
}
-#endif
- if(!ready) {
- int b;
- while ((b = php_stream_read(stream, buf, sizeof(buf))) > 0) {
- PHPWRITE(buf, b);
- bcount += b;
- }
+ while ((b = php_stream_read(stream, buf, sizeof(buf))) > 0) {
+ PHPWRITE(buf, b);
+ bcount += b;
}
+
return bcount;
}
@@ -1118,9 +1100,6 @@ PHPAPI size_t _php_stream_copy_to_mem(php_stream *src, char **buf, size_t maxlen
size_t len = 0, max_len;
int step = CHUNK_SIZE;
int min_room = CHUNK_SIZE / 4;
-#if HAVE_MMAP
- int srcfd;
-#endif
if (buf)
*buf = NULL;
@@ -1131,50 +1110,25 @@ PHPAPI size_t _php_stream_copy_to_mem(php_stream *src, char **buf, size_t maxlen
if (maxlen == PHP_STREAM_COPY_ALL)
maxlen = 0;
-#if HAVE_MMAP
- /* try and optimize the case where we are copying from the start of a plain file.
- * We could probably make this work in more situations, but I don't trust the stdio
- * buffering layer.
- * */
- if ( php_stream_is(src, PHP_STREAM_IS_STDIO) &&
- !php_stream_is_filtered(src) &&
- php_stream_tell(src) == 0 &&
- SUCCESS == php_stream_cast(src, PHP_STREAM_AS_FD, (void**)&srcfd, 0))
- {
- struct stat sbuf;
+ if (php_stream_mmap_possible(src)) {
+ char *p;
+ size_t mapped;
- if (fstat(srcfd, &sbuf) == 0) {
- void *srcfile;
+ p = php_stream_mmap_range(src, php_stream_tell(src), maxlen, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped);
-#if STREAM_DEBUG
- fprintf(stderr, "mmap attempt: maxlen=%d filesize=%ld\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) {
+ if (p) {
+ *buf = pemalloc_rel_orig(mapped + 1, persistent);
- *buf = pemalloc_rel_orig(maxlen + 1, persistent);
-
- if (*buf) {
- memcpy(*buf, srcfile, maxlen);
- (*buf)[maxlen] = '\0';
- ret = maxlen;
- }
+ if (*buf) {
+ memcpy(*buf, p, mapped);
+ (*buf)[mapped] = '\0';
+ }
- munmap(srcfile, maxlen);
+ php_stream_mmap_unmap(src);
- return ret;
- }
+ return mapped;
}
- /* fall through - we might be able to copy in smaller chunks */
}
-#endif
ptr = *buf = pemalloc_rel_orig(step, persistent);
max_len = step;
@@ -1204,9 +1158,6 @@ PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size
size_t haveread = 0;
size_t didread;
php_stream_statbuf ssbuf;
-#if HAVE_MMAP
- int srcfd;
-#endif
if (maxlen == 0)
return 0;
@@ -1214,41 +1165,6 @@ PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size
if (maxlen == PHP_STREAM_COPY_ALL)
maxlen = 0;
-#if HAVE_MMAP
- /* try and optimize the case where we are copying from the start of a plain file.
- * We could probably make this work in more situations, but I don't trust the stdio
- * buffering layer.
- * */
- if ( php_stream_is(src, PHP_STREAM_IS_STDIO) &&
- !php_stream_is_filtered(src) &&
- php_stream_tell(src) == 0 &&
- SUCCESS == php_stream_cast(src, PHP_STREAM_AS_FD, (void**)&srcfd, 0))
- {
- struct stat sbuf;
-
- if (fstat(srcfd, &sbuf) == 0) {
- void *srcfile;
-
- /* 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(sbuf.st_size ==0)
- return 1;
-
- if (maxlen > sbuf.st_size || maxlen == 0)
- maxlen = sbuf.st_size;
-
- srcfile = mmap(NULL, maxlen, PROT_READ, MAP_SHARED, srcfd, 0);
- if (srcfile != (void*)MAP_FAILED) {
- haveread = php_stream_write(dest, srcfile, maxlen);
- munmap(srcfile, maxlen);
- return haveread;
- }
- }
- /* fall through - we might be able to copy in smaller chunks */
- }
-#endif
-
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 */
@@ -1257,6 +1173,21 @@ PHPAPI size_t _php_stream_copy_to_stream(php_stream *src, php_stream *dest, size
}
}
+ 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);
@@ -1323,6 +1254,18 @@ int php_init_stream_wrappers(int module_number TSRMLS_DC)
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
+#ifdef AF_UNIX
+ &&
+ 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;
}
@@ -1330,6 +1273,7 @@ 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;
}
@@ -1451,9 +1395,9 @@ PHPAPI php_stream *_php_stream_opendir(char *path, int options,
php_stream_wrapper_log_error(wrapper, options ^ REPORT_ERRORS TSRMLS_CC, "not implemented");
}
if (stream == NULL && (options & REPORT_ERRORS)) {
- display_wrapper_errors(wrapper, path, "failed to open dir" TSRMLS_CC);
+ php_stream_display_wrapper_errors(wrapper, path, "failed to open dir" TSRMLS_CC);
}
- tidy_wrapper_error_log(wrapper TSRMLS_CC);
+ php_stream_tidy_wrapper_error_log(wrapper TSRMLS_CC);
return stream;
}
@@ -1498,15 +1442,13 @@ PHPAPI php_stream *_php_stream_open_wrapper_ex(char *path, char *mode, int optio
if (wrapper) {
- /* prepare error stack */
- wrapper->err_count = 0;
- wrapper->err_stack = NULL;
-
stream = wrapper->wops->stream_opener(wrapper,
path_to_open, mode, options ^ REPORT_ERRORS,
opened_path, context STREAMS_REL_CC TSRMLS_CC);
- if (stream)
+
+ if (stream) {
stream->wrapper = wrapper;
+ }
}
#if ZEND_DEBUG
@@ -1554,9 +1496,9 @@ PHPAPI php_stream *_php_stream_open_wrapper_ex(char *path, char *mode, int optio
}
if (stream == NULL && (options & REPORT_ERRORS)) {
- display_wrapper_errors(wrapper, path, "failed to open stream" TSRMLS_CC);
+ php_stream_display_wrapper_errors(wrapper, path, "failed to open stream" TSRMLS_CC);
}
- tidy_wrapper_error_log(wrapper TSRMLS_CC);
+ php_stream_tidy_wrapper_error_log(wrapper TSRMLS_CC);
#if ZEND_DEBUG
if (stream == NULL && copy_of_path != NULL) {
efree(copy_of_path);