Browse Source

Implement stream_select() which works just like socket_select, but only on

streams.
@ - Added stream_select() which works like socket_select but only works on
@   streams returned by fopen(), fsockopen() and pfsockopen(). (Wez)
migration/unlabaled-1.1.2
Wez Furlong 24 years ago
parent
commit
315e0a599b
  1. 10
      ext/standard/basic_functions.c
  2. 134
      ext/standard/file.c
  3. 3
      ext/standard/file.h

10
ext/standard/basic_functions.c

@ -99,6 +99,9 @@ static unsigned char second_and_third_args_force_ref[] = { 3, BYREF_NONE, BYREF_
static unsigned char second_args_force_ref[] = { 2, BYREF_NONE, BYREF_FORCE };
static unsigned char third_and_fourth_args_force_ref[] = { 4, BYREF_NONE, BYREF_NONE, BYREF_FORCE, BYREF_FORCE };
static unsigned char third_and_rest_force_ref[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE_REST };
static unsigned char first_through_third_args_force_ref[] =
{3, BYREF_FORCE, BYREF_FORCE, BYREF_FORCE};
typedef struct _php_shutdown_function_entry {
zval **arguments;
@ -617,6 +620,7 @@ function_entry basic_functions[] = {
PHP_STATIC_FE("tmpfile", php_if_tmpfile, NULL)
PHP_FE(file, NULL)
PHP_FE(file_get_contents, NULL)
PHP_FE(stream_select, first_through_third_args_force_ref)
PHP_FE(stream_context_create, NULL)
PHP_FE(stream_context_set_params, NULL)
PHP_FE(stream_context_set_option, NULL)
@ -628,11 +632,9 @@ function_entry basic_functions[] = {
PHP_FE(get_meta_tags, NULL)
PHP_FE(set_file_buffer, NULL)
/* set_socket_blocking() is deprecated,
use socket_set_blocking() instead
*/
PHP_FE(set_socket_blocking, NULL)
PHP_FE(socket_set_blocking, NULL)
PHP_FE(stream_set_blocking, NULL)
PHP_FALIAS(socket_set_blocking, stream_set_blocking, NULL)
PHP_FE(file_get_meta_data, NULL)
PHP_FE(file_register_wrapper, NULL)

134
ext/standard/file.c

@ -639,6 +639,130 @@ PHP_FUNCTION(file_get_meta_data)
}
/* }}} */
static int stream_array_to_fd_set(zval *stream_array, fd_set *fds, int *max_fd TSRMLS_DC)
{
zval **elem;
php_stream *stream;
int this_fd;
if (Z_TYPE_P(stream_array) != IS_ARRAY)
return 0;
for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(stream_array));
zend_hash_get_current_data(Z_ARRVAL_P(stream_array), (void **) &elem) == SUCCESS;
zend_hash_move_forward(Z_ARRVAL_P(stream_array))) {
php_stream_from_zval_no_verify(stream, elem);
if (stream == NULL)
continue;
/* get the fd */
if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&this_fd, 1)) {
FD_SET(this_fd, fds);
if (this_fd > *max_fd) {
*max_fd = this_fd;
}
}
}
return 1;
}
static int stream_array_from_fd_set(zval *stream_array, fd_set *fds TSRMLS_DC)
{
zval **elem, **dest_elem;
php_stream *stream;
HashTable *new_hash;
int this_fd;
if (Z_TYPE_P(stream_array) != IS_ARRAY)
return 0;
ALLOC_HASHTABLE(new_hash);
zend_hash_init(new_hash, 0, NULL, ZVAL_PTR_DTOR, 0);
for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(stream_array));
zend_hash_get_current_data(Z_ARRVAL_P(stream_array), (void **) &elem) == SUCCESS;
zend_hash_move_forward(Z_ARRVAL_P(stream_array))) {
php_stream_from_zval_no_verify(stream, elem);
if (stream == NULL)
continue;
/* get the fd */
if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&this_fd, 1)) {
if (FD_ISSET(this_fd, fds)) {
zend_hash_next_index_insert(new_hash, (void *)elem, sizeof(zval *), (void **)&dest_elem);
if (dest_elem)
zval_add_ref(dest_elem);
}
}
}
/* destroy old array and add new one */
zend_hash_destroy(Z_ARRVAL_P(stream_array));
efree(Z_ARRVAL_P(stream_array));
zend_hash_internal_pointer_reset(new_hash);
Z_ARRVAL_P(stream_array) = new_hash;
return 1;
}
/* {{{ proto int stream_select(array &read_streams, array &write_streams, array &except_streams, int tv_sec[, int tv_usec])
Runs the select() system call on the sets of streams with a timeout specified by tv_sec and tv_usec */
PHP_FUNCTION(stream_select)
{
zval *r_array, *w_array, *e_array, *sec;
struct timeval tv;
struct timeval *tv_p = NULL;
fd_set rfds, wfds, efds;
int max_fd = 0;
int retval, sets = 0, usec = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!a!z!|l", &r_array, &w_array, &e_array, &sec, &usec) == FAILURE)
return;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&efds);
if (r_array != NULL) sets += stream_array_to_fd_set(r_array, &rfds, &max_fd TSRMLS_CC);
if (w_array != NULL) sets += stream_array_to_fd_set(w_array, &wfds, &max_fd TSRMLS_CC);
if (e_array != NULL) sets += stream_array_to_fd_set(e_array, &efds, &max_fd TSRMLS_CC);
if (!sets) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "No stream arrays were passed");
RETURN_FALSE;
}
/* If seconds is not set to null, build the timeval, else we wait indefinitely */
if (sec != NULL) {
convert_to_long_ex(&sec);
tv.tv_sec = Z_LVAL_P(sec);
tv.tv_usec = usec;
tv_p = &tv;
}
retval = select(max_fd+1, &rfds, &wfds, &efds, tv_p);
if (retval == -1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to select [%d]: %s",
errno, strerror(errno));
RETURN_FALSE;
}
if (r_array != NULL) stream_array_from_fd_set(r_array, &rfds TSRMLS_CC);
if (w_array != NULL) stream_array_from_fd_set(w_array, &wfds TSRMLS_CC);
if (e_array != NULL) stream_array_from_fd_set(e_array, &efds TSRMLS_CC);
RETURN_LONG(retval);
}
/* {{{ stream_context related functions */
static void user_space_stream_notifier(php_stream_context *context, int notifycode, int severity,
char *xmsg, int xcode, size_t bytes_sofar, size_t bytes_max, void * ptr TSRMLS_DC)
@ -846,6 +970,7 @@ PHP_FUNCTION(stream_context_create)
}
/* }}} */
/* {{{ streams filter functions */
static void apply_filter_to_stream(int append, INTERNAL_FUNCTION_PARAMETERS)
{
zval *zstream;
@ -888,6 +1013,7 @@ PHP_FUNCTION(stream_filter_append)
apply_filter_to_stream(1, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* }}} */
/* {{{ proto resource fopen(string filename, string mode [, bool use_include_path [, resource context]])
Open a file or a URL and return a file pointer */
@ -1045,9 +1171,9 @@ PHPAPI PHP_FUNCTION(feof)
}
/* }}} */
/* {{{ proto bool socket_set_blocking(resource socket, int mode)
/* {{{ proto bool stream_set_blocking(resource socket, int mode)
Set blocking/non-blocking mode on a socket or stream */
PHP_FUNCTION(socket_set_blocking)
PHP_FUNCTION(stream_set_blocking)
{
zval **arg1, **arg2;
int block;
@ -1073,8 +1199,8 @@ PHP_FUNCTION(socket_set_blocking)
Set blocking/non-blocking mode on a socket */
PHP_FUNCTION(set_socket_blocking)
{
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "This function is deprecated, use socket_set_blocking() instead");
PHP_FN(socket_set_blocking)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "This function is deprecated, use stream_set_blocking() instead");
PHP_FN(stream_set_blocking)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */

3
ext/standard/file.h

@ -55,7 +55,8 @@ PHP_FUNCTION(copy);
PHP_FUNCTION(file);
PHP_FUNCTION(file_get_contents);
PHP_FUNCTION(set_socket_blocking); /* deprecated */
PHP_FUNCTION(socket_set_blocking);
PHP_FUNCTION(stream_set_blocking);
PHP_FUNCTION(stream_select);
PHP_FUNCTION(socket_set_timeout);
PHP_FUNCTION(set_file_buffer);
PHP_FUNCTION(get_meta_tags);

Loading…
Cancel
Save