Manipulation
Four of the five static wrapper operations handle non-I/O based manipulation of streamable resources. You've already seen what they are and how their prototypes look; now it's time to implement them within the framework of the varstream wrapper.
unlink
Add the following function, which allows unlink() to behave much like unset() when used with the varstream wrapper anywhere above your wrapper_ops structure:
static int php_varstream_unlink(php_stream_wrapper *wrapper, char *filename, int options, php_stream_context *context TSRMLS_DC) { php_url *url; url = php_url_parse(filename); if (!url) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unexpected error parsing URL"); return -1; } if (!url->host || (url->host[0] == 0) || strcasecmp("var", url->scheme) != 0) { /* Bad URL or wrong wrapper */ php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Invalid URL, must be in the form: " "var://variablename"); php_url_free(url); return -1; } /* Delete it */ zend_hash_del(&EG(symbol_table), url->host, strlen(url->host) + 1); php_url_free(url); return 0; }
The bulk of this function should look familiar as it's taken straight out of php_varstream_opener. The only difference is that this time you've passed the variable name to zend_hash_del instead.
rename, mkdir, and rmdir
Just for completeness, here are implementations of the rename, mkdir, and rmdir methods:
static int php_varstream_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC) { php_url *from, *to; zval **var; from = php_url_parse(url_from); if (!from) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unexpected error parsing source"); return -1; } if (zend_hash_find(&EG(symbol_table), from->host, strlen(from->host) + 1, (void**)&var) == FAILURE) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "$%s does not exist", from->host); php_url_free(from); return -1; } to = php_url_parse(url_to); if (!to) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unexpected error parsing dest"); php_url_free(from); return -1; } ZVAL_ADDREF(*var); zend_hash_update(&EG(symbol_table), to->host, strlen(to->host) + 1, (void*)var, sizeof(zval*), NULL); zend_hash_del(&EG(symbol_table), from->host, strlen(from->host) + 1); php_url_free(from); php_url_free(to); return 0; } static int php_varstream_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, int options, php_stream_context *context TSRMLS_DC) { php_url *url; php_url_parse(url_from); if (!url) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unexpected error parsing URL"); return -1; } if (zend_hash_exists(&EG(symbol_table), url->host, strlen(url->host) + 1)) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "$%s already exists", url->host); php_url_free(url); return -1; } /* EG(uninitialized_zval_ptr) is a general purpose * IS_NULL zval* with an unlimited refcount */ zend_hash_add(&EG(symbol_table), url->host, strlen(url->host) + 1, (void*)&EG(uninitialized_zval_ptr), sizeof(zval*), NULL); php_url_free(url); return 0; } static int php_varstream_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC) { /* Act just like unlink() */ wrapper->wops->unlink(wrapper, url, options, context TSRMLS_CC); }