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); }
The PHP Life Cycle
Variables from the Inside Out
Memory Management
Setting Up a Build Environment
Your First Extension
Returning Values
Accepting Parameters
Working with Arrays and HashTables
The Resource Data Type
PHP4 Objects
PHP5 Objects
Startup, Shutdown, and a Few Points in Between
INI Settings
Accessing Streams
Implementing Streams
Diverting the Stream
Configuration and Linking
Extension Generators
Setting Up a Host Environment
Advanced Embedding
Appendix A. A Zend API Reference
Appendix B. PHPAPI
Appendix C. Extending and Embedding Cookbook
Appendix D. Additional Resources