📄 file.c
字号:
RETURN_FALSE; } /* Initialize return array */ array_init(return_value); if ((target_len = php_stream_copy_to_mem(stream, &target_buf, PHP_STREAM_COPY_ALL, 0))) { s = target_buf; e = target_buf + target_len; if (!(p = php_stream_locate_eol(stream, target_buf, target_len TSRMLS_CC))) { p = e; goto parse_eol; } if (stream->flags & PHP_STREAM_FLAG_EOL_MAC) { eol_marker = '\r'; } do { p++;parse_eol: if (PG(magic_quotes_runtime)) { /* s is in target_buf which is freed at the end of the function */ slashed = php_addslashes(s, (p-s), &len, 0 TSRMLS_CC); add_index_stringl(return_value, i++, slashed, len, 0); } else { add_index_stringl(return_value, i++, estrndup(s, p-s), p-s, 0); } s = p; } while ((p = memchr(p, eol_marker, (e-p)))); /* handle any left overs of files without new lines */ if (s != e) { p = e; goto parse_eol; } } if (target_buf) { efree(target_buf); } php_stream_close(stream);}/* }}} *//* {{{ proto string tempnam(string dir, string prefix) Create a unique filename in a directory */PHP_FUNCTION(tempnam){ pval **arg1, **arg2; char *d; char *opened_path; char *p; FILE *fp; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_string_ex(arg1); convert_to_string_ex(arg2); if (php_check_open_basedir(Z_STRVAL_PP(arg1) TSRMLS_CC)) { RETURN_FALSE; } d = estrndup(Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1)); p = php_basename(Z_STRVAL_PP(arg2), Z_STRLEN_PP(arg2), NULL, 0); if (strlen(p) > 64) { p[63] = '\0'; } if ((fp = php_open_temporary_file(d, p, &opened_path TSRMLS_CC))) { fclose(fp); RETVAL_STRING(opened_path, 0); } else { RETVAL_FALSE; } efree(p); efree(d);}/* }}} *//* {{{ proto resource tmpfile(void) Create a temporary file that will be deleted automatically after use */PHP_NAMED_FUNCTION(php_if_tmpfile){ php_stream *stream; if (ZEND_NUM_ARGS() != 0) { WRONG_PARAM_COUNT; } stream = php_stream_fopen_tmpfile(); if (stream) { php_stream_to_zval(stream, return_value); } else { RETURN_FALSE; }}/* }}} *//* {{{ proto resource stream_get_meta_data(resource fp) Retrieves header/meta data from streams/file pointers */PHP_FUNCTION(stream_get_meta_data){ zval **arg1; php_stream *stream; zval *newval; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == FAILURE) { WRONG_PARAM_COUNT; } PHP_STREAM_TO_ZVAL(stream, arg1); array_init(return_value); if (stream->wrapperdata) { MAKE_STD_ZVAL(newval); *newval = *(stream->wrapperdata); zval_copy_ctor(newval); INIT_PZVAL(newval); add_assoc_zval(return_value, "wrapper_data", newval); } if (stream->wrapper) { add_assoc_string(return_value, "wrapper_type", (char *)stream->wrapper->wops->label, 1); } add_assoc_string(return_value, "stream_type", (char *)stream->ops->label, 1); if (stream->filterhead) { php_stream_filter *filter; MAKE_STD_ZVAL(newval); array_init(newval); for (filter = stream->filterhead; filter != NULL; filter = filter->next) { add_next_index_string(newval, (char *)filter->fops->label, 1); } add_assoc_zval(return_value, "filters", newval); } add_assoc_long(return_value, "unread_bytes", stream->writepos - stream->readpos); if (php_stream_is(stream, PHP_STREAM_IS_SOCKET)) { php_netstream_data_t *sock = PHP_NETSTREAM_DATA_FROM_STREAM(stream); add_assoc_bool(return_value, "timed_out", sock->timeout_event); add_assoc_bool(return_value, "blocked", sock->is_blocked); add_assoc_bool(return_value, "eof", stream->eof); } else { add_assoc_bool(return_value, "timed_out", 0); add_assoc_bool(return_value, "blocked", 1); add_assoc_bool(return_value, "eof", php_stream_eof(stream)); }}/* }}} *//* {{{ stream_select related functions */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. * NB: Most other code will NOT use the PHP_STREAM_CAST_INTERNAL flag * when casting. It is only used here so that the buffered data warning * is not displayed. * */ if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (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, ret = 0; 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 * NB: Most other code will NOT use the PHP_STREAM_CAST_INTERNAL flag * when casting. It is only used here so that the buffered data warning * is not displayed. */ if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (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); ret++; continue; } } } /* 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 ret;}static int stream_array_emulate_read_fd_set(zval *stream_array TSRMLS_DC){ zval **elem, **dest_elem; php_stream *stream; HashTable *new_hash; int ret = 0; 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; if ((stream->writepos - stream->readpos) > 0) { /* allow readable non-descriptor based streams to participate in stream_select. * Non-descriptor streams will only "work" if they have previously buffered the * data. Not ideal, but better than nothing. * This branch of code also allows blocking streams with buffered data to * operate correctly in stream_select. * */ zend_hash_next_index_insert(new_hash, (void *)elem, sizeof(zval *), (void **)&dest_elem); if (dest_elem) zval_add_ref(dest_elem); ret++; continue; } } if (ret > 0) { /* 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; } else { zend_hash_destroy(new_hash); FREE_HASHTABLE(new_hash); } return ret;}/* }}} *//* {{{ 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; long 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(sec); if (usec > 999999) { tv.tv_sec = Z_LVAL_P(sec) + (usec / 1000000); tv.tv_usec = usec % 1000000; } else { tv.tv_sec = Z_LVAL_P(sec); tv.tv_usec = usec; } tv_p = &tv; } /* slight hack to support buffered data; if there is data sitting in the * read buffer of any of the streams in the read array, let's pretend * that we selected, but return only the readable sockets */ if (r_array != NULL) { retval = stream_array_emulate_read_fd_set(r_array TSRMLS_CC); if (retval > 0) { RETURN_LONG(retval); } } 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){ zval *callback = (zval*)context->notifier->ptr; zval *retval = NULL; zval zvs[6]; zval *ps[6]; zval **ptps[6]; int i; for (i = 0; i < 6; i++) { INIT_ZVAL(zvs[i]); ps[i] = &zvs[i]; ptps[i] = &ps[i]; } ZVAL_LONG(ps[0], notifycode); ZVAL_LONG(ps[1], severity); if (xmsg) { ZVAL_STRING(ps[2], xmsg, 0); } else { ZVAL_NULL(ps[2]); } ZVAL_LONG(ps[3], xcode); ZVAL_LONG(ps[4], bytes_sofar); ZVAL_LONG(ps[5], bytes_max); if (FAILURE == call_user_function_ex(EG(function_table), NULL, callback, &retval, 6, ptps, 0, NULL TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to call user notifier"); } if (retval) zval_ptr_dtor(&retval);}static void user_space_stream_notifier_dtor(php_stream_notifier *notifier){ if (notifier && notifier->ptr) { zval_ptr_dtor((zval **)&(notifier->ptr)); notifier->ptr = NULL; }}static int parse_context_options(php_stream_context *context, zval *options){ HashPosition pos, opos; zval **wval, **oval; char *wkey, *okey; uint wkey_len, okey_len; int ret = SUCCESS; ulong num_key; zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(options), &pos); while (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_P(options), (void**)&wval, &pos)) { if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(Z_ARRVAL_P(options), &wkey, &wkey_len, &num_key, 0, &pos) && Z_TYPE_PP(wval) == IS_ARRAY) { zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(wval), &opos); while (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(wval), (void**)&oval, &opos)) { if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(Z_ARRVAL_PP(wval), &okey, &okey_len, &num_key, 0, &opos)) { php_stream_context_set_option(context, wkey, okey, *oval); } zend_hash_move_forward_ex(Z_ARRVAL_PP(wval), &opos); } } else { zend_error(E_WARNING, "options should have the form [\"wrappername\"][\"optionname\"] = $value"); } zend_hash_move_forward_ex(Z_ARRVAL_P(options), &pos); } return ret;}static int parse_context_params(php_stream_context *context, zval *params){ int ret = FAILURE; zval **tmp; if ((ret = zend_hash_find(Z_ARRVAL_P(params), "notification", sizeof("notification"), (void**)&tmp)) == SUCCESS) { if (context->notifier) { php_stream_notification_free(context->notifier); context->notifier = NULL; } context->notifier = php_stream_notification_alloc(); context->notifier->func = user_space_stream_notifier; context->notifier->ptr = *tmp; ZVAL_ADDREF(*tmp); context->notifier->dtor = user_space_stream_notifier_dtor; } if ((ret = zend_hash_find(Z_ARRVAL_P(params), "options", sizeof("options"), (void**)&tmp)) == SUCCESS) { parse_context_options(context, *tmp); } return ret;}/* given a zval which is either a stream or a context, return the underlying * stream_context. If it is a stream that does not have a context assigned, it * will create and assign a context and return that. */static php_stream_context *decode_context_param(zval *contextresource TSRMLS_DC){ php_stream_context *context = NULL; context = zend_fetch_resource(&contextresource TSRMLS_CC, -1, NULL, NULL, 1, php_le_stream_context()); if (context == NULL) { php_stream *stream; stream = zend_fetch_resource(&contextresource TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream); if (stream) { context = stream->context; if (context == NULL) { context = stream->context = php_stream_context_alloc(); /* Register this magical context so that it'll get cleaned up later. PHP5 does this more cleanly */ ZEND_REGISTER_RESOURCE(NULL, context, php_le_stream_context()); } } } return context;}/* }}} *//* {{{ proto array stream_context_get_options(resource context|resource stream) Retrieve options for a stream/wrapper/context */PHP_FUNCTION(stream_context_get_options){ zval *zcontext; php_stream_context *context; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zcontext) == FAILURE) { RETURN_FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -