php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
userspace.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Wez Furlong <wez@thebrainroom.com> |
14 | Sara Golemon <pollita@php.net> |
15 +----------------------------------------------------------------------+
16*/
17
18#include "php.h"
19#include "php_globals.h"
20#include "ext/standard/file.h"
22#ifdef HAVE_SYS_FILE_H
23#include <sys/file.h>
24#endif
25#include <stddef.h>
26
27#ifdef HAVE_UTIME
28# ifdef PHP_WIN32
29# include <sys/utime.h>
30# else
31# include <utime.h>
32# endif
33#endif
34#include "userspace_arginfo.h"
35
36static int le_protocols;
37
44
45static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char *filename, const char *mode, int options, zend_string **opened_path, php_stream_context *context STREAMS_DC);
46static int user_wrapper_close(php_stream_wrapper *wrapper, php_stream *stream);
47static int user_wrapper_stat_url(php_stream_wrapper *wrapper, const char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context);
48static int user_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context);
49static int user_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to, int options, php_stream_context *context);
50static int user_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url, int mode, int options, php_stream_context *context);
51static int user_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context);
52static int user_wrapper_metadata(php_stream_wrapper *wrapper, const char *url, int option, void *value, php_stream_context *context);
53static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char *filename, const char *mode,
55
56static const php_stream_wrapper_ops user_stream_wops = {
57 user_wrapper_opener,
58 user_wrapper_close,
59 NULL, /* stat - the streams themselves know how */
60 user_wrapper_stat_url,
61 user_wrapper_opendir,
62 "user-space",
63 user_wrapper_unlink,
64 user_wrapper_rename,
65 user_wrapper_mkdir,
66 user_wrapper_rmdir,
67 user_wrapper_metadata
68};
69
70
71static void stream_wrapper_dtor(zend_resource *rsrc)
72{
73 struct php_user_stream_wrapper * uwrap = (struct php_user_stream_wrapper*)rsrc->ptr;
74
75 efree(uwrap->protoname);
76 efree(uwrap);
77}
78
79
80PHP_MINIT_FUNCTION(user_streams)
81{
82 le_protocols = zend_register_list_destructors_ex(stream_wrapper_dtor, NULL, "stream factory", 0);
83 if (le_protocols == FAILURE)
84 return FAILURE;
85
86 register_userspace_symbols(module_number);
87
88 return SUCCESS;
89}
90
96
97/* names of methods */
98#define USERSTREAM_OPEN "stream_open"
99#define USERSTREAM_CLOSE "stream_close"
100#define USERSTREAM_READ "stream_read"
101#define USERSTREAM_WRITE "stream_write"
102#define USERSTREAM_FLUSH "stream_flush"
103#define USERSTREAM_SEEK "stream_seek"
104#define USERSTREAM_TELL "stream_tell"
105#define USERSTREAM_EOF "stream_eof"
106#define USERSTREAM_STAT "stream_stat"
107#define USERSTREAM_STATURL "url_stat"
108#define USERSTREAM_UNLINK "unlink"
109#define USERSTREAM_RENAME "rename"
110#define USERSTREAM_MKDIR "mkdir"
111#define USERSTREAM_RMDIR "rmdir"
112#define USERSTREAM_DIR_OPEN "dir_opendir"
113#define USERSTREAM_DIR_READ "dir_readdir"
114#define USERSTREAM_DIR_REWIND "dir_rewinddir"
115#define USERSTREAM_DIR_CLOSE "dir_closedir"
116#define USERSTREAM_LOCK "stream_lock"
117#define USERSTREAM_CAST "stream_cast"
118#define USERSTREAM_SET_OPTION "stream_set_option"
119#define USERSTREAM_TRUNCATE "stream_truncate"
120#define USERSTREAM_METADATA "stream_metadata"
121
122/* {{{ class should have methods like these:
123
124 function stream_open($path, $mode, $options, &$opened_path)
125 {
126 return true/false;
127 }
128
129 function stream_read($count)
130 {
131 return false on error;
132 else return string;
133 }
134
135 function stream_write($data)
136 {
137 return false on error;
138 else return count written;
139 }
140
141 function stream_close()
142 {
143 }
144
145 function stream_flush()
146 {
147 return true/false;
148 }
149
150 function stream_seek($offset, $whence)
151 {
152 return true/false;
153 }
154
155 function stream_tell()
156 {
157 return (int)$position;
158 }
159
160 function stream_eof()
161 {
162 return true/false;
163 }
164
165 function stream_stat()
166 {
167 return array( just like that returned by fstat() );
168 }
169
170 function stream_cast($castas)
171 {
172 if ($castas == STREAM_CAST_FOR_SELECT) {
173 return $this->underlying_stream;
174 }
175 return false;
176 }
177
178 function stream_set_option($option, $arg1, $arg2)
179 {
180 switch($option) {
181 case STREAM_OPTION_BLOCKING:
182 $blocking = $arg1;
183 ...
184 case STREAM_OPTION_READ_TIMEOUT:
185 $sec = $arg1;
186 $usec = $arg2;
187 ...
188 case STREAM_OPTION_WRITE_BUFFER:
189 $mode = $arg1;
190 $size = $arg2;
191 ...
192 default:
193 return false;
194 }
195 }
196
197 function url_stat(string $url, int $flags)
198 {
199 return array( just like that returned by stat() );
200 }
201
202 function unlink(string $url)
203 {
204 return true / false;
205 }
206
207 function rename(string $from, string $to)
208 {
209 return true / false;
210 }
211
212 function mkdir($dir, $mode, $options)
213 {
214 return true / false;
215 }
216
217 function rmdir($dir, $options)
218 {
219 return true / false;
220 }
221
222 function dir_opendir(string $url, int $options)
223 {
224 return true / false;
225 }
226
227 function dir_readdir()
228 {
229 return string next filename in dir ;
230 }
231
232 function dir_closedir()
233 {
234 release dir related resources;
235 }
236
237 function dir_rewinddir()
238 {
239 reset to start of dir list;
240 }
241
242 function stream_lock($operation)
243 {
244 return true / false;
245 }
246
247 function stream_truncate($new_size)
248 {
249 return true / false;
250 }
251
252 }}} **/
253
254static zend_result call_method_if_exists(
255 zval *object, zval *method_name, zval *retval, uint32_t param_count, zval *params)
256{
258 Z_OBJ_P(object), Z_STR_P(method_name), retval, param_count, params);
259}
260
261static void user_stream_create_object(struct php_user_stream_wrapper *uwrap, php_stream_context *context, zval *object)
262{
264 ZVAL_UNDEF(object);
265 return;
266 }
267
268 /* create an instance of our class */
269 if (object_init_ex(object, uwrap->ce) == FAILURE) {
270 ZVAL_UNDEF(object);
271 return;
272 }
273
274 if (context) {
275 GC_ADDREF(context->res);
276 add_property_resource(object, "context", context->res);
277 } else {
278 add_property_null(object, "context");
279 }
280
281 if (EG(exception) != NULL) {
282 zval_ptr_dtor(object);
283 ZVAL_UNDEF(object);
284 return;
285 }
286
287 if (uwrap->ce->constructor) {
288 zend_call_known_instance_method_with_0_params(
289 uwrap->ce->constructor, Z_OBJ_P(object), NULL);
290 }
291}
292
293static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char *filename, const char *mode,
295{
298 zval zretval, zfuncname;
299 zval args[4];
300 int call_result;
301 php_stream *stream = NULL;
302 bool old_in_user_include;
303
304 /* Try to catch bad usage without preventing flexibility */
305 if (FG(user_stream_current_filename) != NULL && strcmp(filename, FG(user_stream_current_filename)) == 0) {
306 php_stream_wrapper_log_error(wrapper, options, "infinite recursion prevented");
307 return NULL;
308 }
309 FG(user_stream_current_filename) = filename;
310
311 /* if the user stream was registered as local and we are in include context,
312 we add allow_url_include restrictions to allow_url_fopen ones */
313 /* we need only is_url == 0 here since if is_url == 1 and remote wrappers
314 were restricted we wouldn't get here */
315 old_in_user_include = PG(in_user_include);
316 if(uwrap->wrapper.is_url == 0 &&
318 !PG(allow_url_include)) {
319 PG(in_user_include) = 1;
320 }
321
322 us = emalloc(sizeof(*us));
323 us->wrapper = uwrap;
324 /* call_method_if_exists() may unregister the stream wrapper. Hold on to it. */
326
327 user_stream_create_object(uwrap, context, &us->object);
328 if (Z_TYPE(us->object) == IS_UNDEF) {
329 FG(user_stream_current_filename) = NULL;
330 PG(in_user_include) = old_in_user_include;
331 efree(us);
332 return NULL;
333 }
334
335 /* call it's stream_open method - set up params first */
336 ZVAL_STRING(&args[0], filename);
337 ZVAL_STRING(&args[1], mode);
338 ZVAL_LONG(&args[2], options);
339 ZVAL_NEW_REF(&args[3], &EG(uninitialized_zval));
340
341 ZVAL_STRING(&zfuncname, USERSTREAM_OPEN);
342
343 zend_try {
344 call_result = call_method_if_exists(&us->object, &zfuncname, &zretval, 4, args);
345 } zend_catch {
346 FG(user_stream_current_filename) = NULL;
347 zend_bailout();
348 } zend_end_try();
349
350 if (call_result == SUCCESS && Z_TYPE(zretval) != IS_UNDEF && zval_is_true(&zretval)) {
351 /* the stream is now open! */
353
354 /* if the opened path is set, copy it out */
355 if (Z_ISREF(args[3]) && Z_TYPE_P(Z_REFVAL(args[3])) == IS_STRING && opened_path) {
356 *opened_path = zend_string_copy(Z_STR_P(Z_REFVAL(args[3])));
357 }
358
359 /* set wrapper data to be a reference to our object */
360 ZVAL_COPY(&stream->wrapperdata, &us->object);
361 } else {
363 ZSTR_VAL(us->wrapper->ce->name));
364 }
365
366 /* destroy everything else */
367 if (stream == NULL) {
368 zval_ptr_dtor(&us->object);
369 ZVAL_UNDEF(&us->object);
371 efree(us);
372 }
373 zval_ptr_dtor(&zretval);
374 zval_ptr_dtor(&zfuncname);
375 zval_ptr_dtor(&args[3]);
376 zval_ptr_dtor(&args[2]);
377 zval_ptr_dtor(&args[1]);
378 zval_ptr_dtor(&args[0]);
379
380 FG(user_stream_current_filename) = NULL;
381
382 PG(in_user_include) = old_in_user_include;
383 return stream;
384}
385
386static int user_wrapper_close(php_stream_wrapper *wrapper, php_stream *stream)
387{
390 // FIXME: Unused?
391 return 0;
392}
393
394static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char *filename, const char *mode,
396{
399 zval zretval, zfuncname;
400 zval args[2];
401 int call_result;
402 php_stream *stream = NULL;
403
404 /* Try to catch bad usage without preventing flexibility */
405 if (FG(user_stream_current_filename) != NULL && strcmp(filename, FG(user_stream_current_filename)) == 0) {
406 php_stream_wrapper_log_error(wrapper, options, "infinite recursion prevented");
407 return NULL;
408 }
409 FG(user_stream_current_filename) = filename;
410
411 us = emalloc(sizeof(*us));
412 us->wrapper = uwrap;
413 /* call_method_if_exists() may unregister the stream wrapper. Hold on to it. */
415
416 user_stream_create_object(uwrap, context, &us->object);
417 if (Z_TYPE(us->object) == IS_UNDEF) {
418 FG(user_stream_current_filename) = NULL;
419 efree(us);
420 return NULL;
421 }
422
423 /* call it's dir_open method - set up params first */
424 ZVAL_STRING(&args[0], filename);
425 ZVAL_LONG(&args[1], options);
426
427 ZVAL_STRING(&zfuncname, USERSTREAM_DIR_OPEN);
428
429 call_result = call_method_if_exists(&us->object, &zfuncname, &zretval, 2, args);
430
431 if (call_result == SUCCESS && Z_TYPE(zretval) != IS_UNDEF && zval_is_true(&zretval)) {
432 /* the stream is now open! */
434
435 /* set wrapper data to be a reference to our object */
436 ZVAL_COPY(&stream->wrapperdata, &us->object);
437 } else {
439 ZSTR_VAL(us->wrapper->ce->name));
440 }
441
442 /* destroy everything else */
443 if (stream == NULL) {
444 zval_ptr_dtor(&us->object);
445 ZVAL_UNDEF(&us->object);
447 efree(us);
448 }
449 zval_ptr_dtor(&zretval);
450
451 zval_ptr_dtor(&zfuncname);
452 zval_ptr_dtor(&args[1]);
453 zval_ptr_dtor(&args[0]);
454
455 FG(user_stream_current_filename) = NULL;
456
457 return stream;
458}
459
460
461/* {{{ Registers a custom URL protocol handler class */
463{
464 zend_string *protocol;
465 struct php_user_stream_wrapper *uwrap;
467 zend_resource *rsrc;
468 zend_long flags = 0;
469
470 if (zend_parse_parameters(ZEND_NUM_ARGS(), "SC|l", &protocol, &ce, &flags) == FAILURE) {
472 }
473
474 uwrap = (struct php_user_stream_wrapper *)ecalloc(1, sizeof(*uwrap));
475 uwrap->ce = ce;
476 uwrap->protoname = estrndup(ZSTR_VAL(protocol), ZSTR_LEN(protocol));
477 uwrap->wrapper.wops = &user_stream_wops;
478 uwrap->wrapper.abstract = uwrap;
479 uwrap->wrapper.is_url = ((flags & PHP_STREAM_IS_URL) != 0);
480
481 rsrc = zend_register_resource(uwrap, le_protocols);
482
483 if (php_register_url_stream_wrapper_volatile(protocol, &uwrap->wrapper) == SUCCESS) {
484 uwrap->resource = rsrc;
486 }
487
488 /* We failed. But why? */
489 if (zend_hash_exists(php_stream_get_url_stream_wrappers_hash(), protocol)) {
490 php_error_docref(NULL, E_WARNING, "Protocol %s:// is already defined.", ZSTR_VAL(protocol));
491 } else {
492 /* Hash doesn't exist so it must have been an invalid protocol scheme */
493 php_error_docref(NULL, E_WARNING, "Invalid protocol scheme specified. Unable to register wrapper class %s to %s://", ZSTR_VAL(uwrap->ce->name), ZSTR_VAL(protocol));
494 }
495
496 zend_list_delete(rsrc);
498}
499/* }}} */
500
501/* {{{ Unregister a wrapper for the life of the current request. */
503{
504 zend_string *protocol;
505
506 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &protocol) == FAILURE) {
508 }
509
510 php_stream_wrapper *wrapper = zend_hash_find_ptr(php_stream_get_url_stream_wrappers_hash(), protocol);
512 /* We failed */
513 php_error_docref(NULL, E_WARNING, "Unable to unregister protocol %s://", ZSTR_VAL(protocol));
515 }
516
518 if (wrapper->wops == &user_stream_wops) {
520 // uwrap will be released by resource destructor
522 }
523
525}
526/* }}} */
527
528/* {{{ Restore the original protocol handler, overriding if necessary */
530{
531 zend_string *protocol;
533 HashTable *global_wrapper_hash, *wrapper_hash;
534
535 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &protocol) == FAILURE) {
537 }
538
540 if ((wrapper = zend_hash_find_ptr(global_wrapper_hash, protocol)) == NULL) {
541 php_error_docref(NULL, E_WARNING, "%s:// never existed, nothing to restore", ZSTR_VAL(protocol));
543 }
544
546 if (wrapper_hash == global_wrapper_hash || zend_hash_find_ptr(wrapper_hash, protocol) == wrapper) {
547 php_error_docref(NULL, E_NOTICE, "%s:// was never changed, nothing to restore", ZSTR_VAL(protocol));
549 }
550
551 /* A failure here could be okay given that the protocol might have been merely unregistered */
553
555 php_error_docref(NULL, E_WARNING, "Unable to restore original %s:// wrapper", ZSTR_VAL(protocol));
557 }
558
560}
561/* }}} */
562
563static ssize_t php_userstreamop_write(php_stream *stream, const char *buf, size_t count)
564{
566 zval retval;
567 int call_result;
569 zval args[1];
570 ssize_t didwrite;
571
572 assert(us != NULL);
573
575
576 ZVAL_STRINGL(&args[0], (char*)buf, count);
577
578 call_result = call_method_if_exists(&us->object, &func_name, &retval, 1, args);
579 zval_ptr_dtor(&args[0]);
581
582 if (EG(exception)) {
583 return -1;
584 }
585
586 if (call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
587 if (Z_TYPE(retval) == IS_FALSE) {
588 didwrite = -1;
589 } else {
591 didwrite = Z_LVAL(retval);
592 }
593 } else {
594 php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_WRITE " is not implemented!",
595 ZSTR_VAL(us->wrapper->ce->name));
596 didwrite = -1;
597 }
598
599 /* don't allow strange buffer overruns due to bogus return */
600 if (didwrite > 0 && didwrite > count) {
601 php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_WRITE " wrote " ZEND_LONG_FMT " bytes more data than requested (" ZEND_LONG_FMT " written, " ZEND_LONG_FMT " max)",
602 ZSTR_VAL(us->wrapper->ce->name),
603 (zend_long)(didwrite - count), (zend_long)didwrite, (zend_long)count);
604 didwrite = count;
605 }
606
608
609 return didwrite;
610}
611
612static ssize_t php_userstreamop_read(php_stream *stream, char *buf, size_t count)
613{
615 zval retval;
616 zval args[1];
617 int call_result;
618 size_t didread = 0;
620
621 assert(us != NULL);
622
624
625 ZVAL_LONG(&args[0], count);
626
627 call_result = call_method_if_exists(&us->object, &func_name, &retval, 1, args);
628
629 zval_ptr_dtor(&args[0]);
631
632 if (EG(exception)) {
633 return -1;
634 }
635
636 if (call_result == FAILURE) {
637 php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_READ " is not implemented!",
638 ZSTR_VAL(us->wrapper->ce->name));
639 return -1;
640 }
641
642 if (Z_TYPE(retval) == IS_FALSE) {
643 return -1;
644 }
645
646 if (!try_convert_to_string(&retval)) {
648 return -1;
649 }
650
651 didread = Z_STRLEN(retval);
652 if (didread > 0) {
653 if (didread > count) {
654 php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_READ " - read " ZEND_LONG_FMT " bytes more data than requested (" ZEND_LONG_FMT " read, " ZEND_LONG_FMT " max) - excess data will be lost",
655 ZSTR_VAL(us->wrapper->ce->name), (zend_long)(didread - count), (zend_long)didread, (zend_long)count);
656 didread = count;
657 }
658 memcpy(buf, Z_STRVAL(retval), didread);
659 }
660
663
664 /* since the user stream has no way of setting the eof flag directly, we need to ask it if we hit eof */
665
667 call_result = call_method_if_exists(&us->object, &func_name, &retval, 0, NULL);
669
670 if (EG(exception)) {
671 stream->eof = 1;
672 return -1;
673 }
674
675 if (call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF && zval_is_true(&retval)) {
676 stream->eof = 1;
677 } else if (call_result == FAILURE) {
679 "%s::" USERSTREAM_EOF " is not implemented! Assuming EOF",
680 ZSTR_VAL(us->wrapper->ce->name));
681
682 stream->eof = 1;
683 }
684
686
687 return didread;
688}
689
690static int php_userstreamop_close(php_stream *stream, int close_handle)
691{
693 zval retval;
695
696 assert(us != NULL);
697
699
700 call_method_if_exists(&us->object, &func_name, &retval, 0, NULL);
701
704
705 zval_ptr_dtor(&us->object);
706 ZVAL_UNDEF(&us->object);
707
708 efree(us);
709
710 return 0;
711}
712
713static int php_userstreamop_flush(php_stream *stream)
714{
716 zval retval;
717 int call_result;
719
720 assert(us != NULL);
721
723
724 call_result = call_method_if_exists(&us->object, &func_name, &retval, 0, NULL);
725
726 if (call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF && zval_is_true(&retval))
727 call_result = 0;
728 else
729 call_result = -1;
730
733
734 return call_result;
735}
736
737static int php_userstreamop_seek(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffs)
738{
740 zval retval;
741 int call_result, ret;
743 zval args[2];
744
745 assert(us != NULL);
746
748
749 ZVAL_LONG(&args[0], offset);
750 ZVAL_LONG(&args[1], whence);
751
752 call_result = call_method_if_exists(&us->object, &func_name, &retval, 2, args);
753
754 zval_ptr_dtor(&args[0]);
755 zval_ptr_dtor(&args[1]);
757
758 if (call_result == FAILURE) {
759 /* stream_seek is not implemented, so disable seeks for this stream */
761 /* there should be no retval to clean up */
762
764
765 return -1;
766 } else if (call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF && zval_is_true(&retval)) {
767 ret = 0;
768 } else {
769 ret = -1;
770 }
771
774
775 if (ret) {
776 return ret;
777 }
778
779 /* now determine where we are */
781
782 call_result = call_method_if_exists(&us->object, &func_name, &retval, 0, NULL);
783
784 if (call_result == SUCCESS && Z_TYPE(retval) == IS_LONG) {
785 *newoffs = Z_LVAL(retval);
786 ret = 0;
787 } else if (call_result == FAILURE) {
788 php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_TELL " is not implemented!", ZSTR_VAL(us->wrapper->ce->name));
789 ret = -1;
790 } else {
791 ret = -1;
792 }
793
796 return ret;
797}
798
799/* parse the return value from one of the stat functions and store the
800 * relevant fields into the statbuf provided */
801static void statbuf_from_array(zval *array, php_stream_statbuf *ssb)
802{
803 zval *elem;
804
805#define STAT_PROP_ENTRY_EX(name, name2) \
806 if (NULL != (elem = zend_hash_str_find(Z_ARRVAL_P(array), #name, sizeof(#name)-1))) { \
807 ssb->sb.st_##name2 = zval_get_long(elem); \
808 }
809
810#define STAT_PROP_ENTRY(name) STAT_PROP_ENTRY_EX(name,name)
811
812 memset(ssb, 0, sizeof(php_stream_statbuf));
813 STAT_PROP_ENTRY(dev);
814 STAT_PROP_ENTRY(ino);
816 STAT_PROP_ENTRY(nlink);
817 STAT_PROP_ENTRY(uid);
818 STAT_PROP_ENTRY(gid);
819#ifdef HAVE_STRUCT_STAT_ST_RDEV
820 STAT_PROP_ENTRY(rdev);
821#endif
823 STAT_PROP_ENTRY(atime);
824 STAT_PROP_ENTRY(mtime);
825 STAT_PROP_ENTRY(ctime);
826#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
827 STAT_PROP_ENTRY(blksize);
828#endif
829#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
830 STAT_PROP_ENTRY(blocks);
831#endif
832
833#undef STAT_PROP_ENTRY
834#undef STAT_PROP_ENTRY_EX
835}
836
837static int php_userstreamop_stat(php_stream *stream, php_stream_statbuf *ssb)
838{
840 zval retval;
841 int call_result;
843 int ret = -1;
844
846
847 call_result = call_method_if_exists(&us->object, &func_name, &retval, 0, NULL);
848
849 if (call_result == SUCCESS && Z_TYPE(retval) == IS_ARRAY) {
850 statbuf_from_array(&retval, ssb);
851 ret = 0;
852 } else {
853 if (call_result == FAILURE) {
854 php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_STAT " is not implemented!",
855 ZSTR_VAL(us->wrapper->ce->name));
856 }
857 }
858
861
862 return ret;
863}
864
865
866static int php_userstreamop_set_option(php_stream *stream, int option, int value, void *ptrparam) {
868 zval retval;
869 int call_result;
872 zval args[3];
873
874 switch (option) {
877 call_result = call_method_if_exists(&us->object, &func_name, &retval, 0, NULL);
878 if (call_result == SUCCESS && (Z_TYPE(retval) == IS_FALSE || Z_TYPE(retval) == IS_TRUE)) {
880 } else {
883 "%s::" USERSTREAM_EOF " is not implemented! Assuming EOF",
884 ZSTR_VAL(us->wrapper->ce->name));
885 }
888 break;
889
891 ZVAL_LONG(&args[0], 0);
892
893 if (value & LOCK_NB) {
894 Z_LVAL_P(&args[0]) |= PHP_LOCK_NB;
895 }
896 switch(value & ~LOCK_NB) {
897 case LOCK_SH:
898 Z_LVAL_P(&args[0]) |= PHP_LOCK_SH;
899 break;
900 case LOCK_EX:
901 Z_LVAL_P(&args[0]) |= PHP_LOCK_EX;
902 break;
903 case LOCK_UN:
904 Z_LVAL_P(&args[0]) |= PHP_LOCK_UN;
905 break;
906 }
907
908 /* TODO wouldblock */
910
911 call_result = call_method_if_exists(&us->object, &func_name, &retval, 1, args);
912
913 if (call_result == SUCCESS && (Z_TYPE(retval) == IS_FALSE || Z_TYPE(retval) == IS_TRUE)) {
914 ret = (Z_TYPE(retval) == IS_FALSE);
915 } else if (call_result == FAILURE) {
916 if (value == 0) {
917 /* lock support test (TODO: more check) */
919 } else {
920 php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_LOCK " is not implemented!",
921 ZSTR_VAL(us->wrapper->ce->name));
923 }
924 }
925
928 zval_ptr_dtor(&args[0]);
929 break;
930
933
934 switch (value) {
938 else
940 break;
941
943 ptrdiff_t new_size = *(ptrdiff_t*) ptrparam;
944 if (new_size >= 0 && new_size <= (ptrdiff_t)LONG_MAX) {
945 ZVAL_LONG(&args[0], (zend_long)new_size);
946 call_result = call_method_if_exists(&us->object, &func_name, &retval, 1, args);
947 if (call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
948 if (Z_TYPE(retval) == IS_FALSE || Z_TYPE(retval) == IS_TRUE) {
951 } else {
953 "%s::" USERSTREAM_TRUNCATE " did not return a boolean!",
954 ZSTR_VAL(us->wrapper->ce->name));
955 }
956 } else {
958 "%s::" USERSTREAM_TRUNCATE " is not implemented!",
959 ZSTR_VAL(us->wrapper->ce->name));
960 }
962 zval_ptr_dtor(&args[0]);
963 } else { /* bad new size */
965 }
966 break;
967 }
968 }
970 break;
971
976
978
979 ZVAL_LONG(&args[0], option);
980 ZVAL_NULL(&args[1]);
981 ZVAL_NULL(&args[2]);
982
983 switch(option) {
986 ZVAL_LONG(&args[1], value);
987 if (ptrparam) {
988 ZVAL_LONG(&args[2], *(long *)ptrparam);
989 } else {
990 ZVAL_LONG(&args[2], BUFSIZ);
991 }
992 break;
994 struct timeval tv = *(struct timeval*)ptrparam;
995 ZVAL_LONG(&args[1], tv.tv_sec);
996 ZVAL_LONG(&args[2], tv.tv_usec);
997 break;
998 }
1000 ZVAL_LONG(&args[1], value);
1001 break;
1002 default:
1003 break;
1004 }
1005
1006 call_result = call_method_if_exists(&us->object, &func_name, &retval, 3, args);
1007
1008 if (call_result == FAILURE) {
1009 php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_SET_OPTION " is not implemented!",
1010 ZSTR_VAL(us->wrapper->ce->name));
1012 } else if (zend_is_true(&retval)) {
1014 } else {
1016 }
1017
1019 zval_ptr_dtor(&args[2]);
1020 zval_ptr_dtor(&args[1]);
1021 zval_ptr_dtor(&args[0]);
1023
1024 break;
1025 }
1026 }
1027
1028 return ret;
1029}
1030
1031
1032static int user_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context)
1033{
1035 zval zfuncname, zretval;
1036 zval args[1];
1037 int call_result;
1038 zval object;
1039 int ret = 0;
1040
1041 /* create an instance of our class */
1042 user_stream_create_object(uwrap, context, &object);
1043 if (Z_TYPE(object) == IS_UNDEF) {
1044 return ret;
1045 }
1046
1047 /* call the unlink method */
1048 ZVAL_STRING(&args[0], url);
1049
1050 ZVAL_STRING(&zfuncname, USERSTREAM_UNLINK);
1051
1052 call_result = call_method_if_exists(&object, &zfuncname, &zretval, 1, args);
1053
1054 if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
1055 ret = (Z_TYPE(zretval) == IS_TRUE);
1056 } else if (call_result == FAILURE) {
1057 php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_UNLINK " is not implemented!", ZSTR_VAL(uwrap->ce->name));
1058 }
1059
1060 /* clean up */
1061 zval_ptr_dtor(&object);
1062 zval_ptr_dtor(&zretval);
1063 zval_ptr_dtor(&zfuncname);
1064
1065 zval_ptr_dtor(&args[0]);
1066
1067 return ret;
1068}
1069
1070static int user_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to,
1072{
1074 zval zfuncname, zretval;
1075 zval args[2];
1076 int call_result;
1077 zval object;
1078 int ret = 0;
1079
1080 /* create an instance of our class */
1081 user_stream_create_object(uwrap, context, &object);
1082 if (Z_TYPE(object) == IS_UNDEF) {
1083 return ret;
1084 }
1085
1086 /* call the rename method */
1087 ZVAL_STRING(&args[0], url_from);
1088 ZVAL_STRING(&args[1], url_to);
1089
1090 ZVAL_STRING(&zfuncname, USERSTREAM_RENAME);
1091
1092 call_result = call_method_if_exists(&object, &zfuncname, &zretval, 2, args);
1093
1094 if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
1095 ret = (Z_TYPE(zretval) == IS_TRUE);
1096 } else if (call_result == FAILURE) {
1097 php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_RENAME " is not implemented!", ZSTR_VAL(uwrap->ce->name));
1098 }
1099
1100 /* clean up */
1101 zval_ptr_dtor(&object);
1102 zval_ptr_dtor(&zretval);
1103
1104 zval_ptr_dtor(&zfuncname);
1105 zval_ptr_dtor(&args[1]);
1106 zval_ptr_dtor(&args[0]);
1107
1108 return ret;
1109}
1110
1111static int user_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url, int mode,
1113{
1115 zval zfuncname, zretval;
1116 zval args[3];
1117 int call_result;
1118 zval object;
1119 int ret = 0;
1120
1121 /* create an instance of our class */
1122 user_stream_create_object(uwrap, context, &object);
1123 if (Z_TYPE(object) == IS_UNDEF) {
1124 return ret;
1125 }
1126
1127 /* call the mkdir method */
1128 ZVAL_STRING(&args[0], url);
1129 ZVAL_LONG(&args[1], mode);
1130 ZVAL_LONG(&args[2], options);
1131
1132 ZVAL_STRING(&zfuncname, USERSTREAM_MKDIR);
1133
1134 call_result = call_method_if_exists(&object, &zfuncname, &zretval, 3, args);
1135
1136 if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
1137 ret = (Z_TYPE(zretval) == IS_TRUE);
1138 } else if (call_result == FAILURE) {
1139 php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_MKDIR " is not implemented!", ZSTR_VAL(uwrap->ce->name));
1140 }
1141
1142 /* clean up */
1143 zval_ptr_dtor(&object);
1144 zval_ptr_dtor(&zretval);
1145
1146 zval_ptr_dtor(&zfuncname);
1147 zval_ptr_dtor(&args[2]);
1148 zval_ptr_dtor(&args[1]);
1149 zval_ptr_dtor(&args[0]);
1150
1151 return ret;
1152}
1153
1154static int user_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url,
1156{
1158 zval zfuncname, zretval;
1159 zval args[2];
1160 int call_result;
1161 zval object;
1162 int ret = 0;
1163
1164 /* create an instance of our class */
1165 user_stream_create_object(uwrap, context, &object);
1166 if (Z_TYPE(object) == IS_UNDEF) {
1167 return ret;
1168 }
1169
1170 /* call the rmdir method */
1171 ZVAL_STRING(&args[0], url);
1172 ZVAL_LONG(&args[1], options);
1173
1174 ZVAL_STRING(&zfuncname, USERSTREAM_RMDIR);
1175
1176 call_result = call_method_if_exists(&object, &zfuncname, &zretval, 2, args);
1177
1178 if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
1179 ret = (Z_TYPE(zretval) == IS_TRUE);
1180 } else if (call_result == FAILURE) {
1181 php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_RMDIR " is not implemented!", ZSTR_VAL(uwrap->ce->name));
1182 }
1183
1184 /* clean up */
1185 zval_ptr_dtor(&object);
1186 zval_ptr_dtor(&zretval);
1187
1188 zval_ptr_dtor(&zfuncname);
1189 zval_ptr_dtor(&args[1]);
1190 zval_ptr_dtor(&args[0]);
1191
1192 return ret;
1193}
1194
1195static int user_wrapper_metadata(php_stream_wrapper *wrapper, const char *url, int option,
1197{
1199 zval zfuncname, zretval;
1200 zval args[3];
1201 int call_result;
1202 zval object;
1203 int ret = 0;
1204
1205 switch(option) {
1207 array_init(&args[2]);
1208 if(value) {
1209 struct utimbuf *newtime = (struct utimbuf *)value;
1210 add_index_long(&args[2], 0, newtime->modtime);
1211 add_index_long(&args[2], 1, newtime->actime);
1212 }
1213 break;
1217 ZVAL_LONG(&args[2], *(long *)value);
1218 break;
1221 ZVAL_STRING(&args[2], value);
1222 break;
1223 default:
1224 php_error_docref(NULL, E_WARNING, "Unknown option %d for " USERSTREAM_METADATA, option);
1225 zval_ptr_dtor(&args[2]);
1226 return ret;
1227 }
1228
1229 /* create an instance of our class */
1230 user_stream_create_object(uwrap, context, &object);
1231 if (Z_TYPE(object) == IS_UNDEF) {
1232 zval_ptr_dtor(&args[2]);
1233 return ret;
1234 }
1235
1236 /* call the mkdir method */
1237 ZVAL_STRING(&args[0], url);
1238 ZVAL_LONG(&args[1], option);
1239
1240 ZVAL_STRING(&zfuncname, USERSTREAM_METADATA);
1241
1242 call_result = call_method_if_exists(&object, &zfuncname, &zretval, 3, args);
1243
1244 if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) {
1245 ret = Z_TYPE(zretval) == IS_TRUE;
1246 } else if (call_result == FAILURE) {
1247 php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_METADATA " is not implemented!", ZSTR_VAL(uwrap->ce->name));
1248 }
1249
1250 /* clean up */
1251 zval_ptr_dtor(&object);
1252 zval_ptr_dtor(&zretval);
1253
1254 zval_ptr_dtor(&zfuncname);
1255 zval_ptr_dtor(&args[0]);
1256 zval_ptr_dtor(&args[1]);
1257 zval_ptr_dtor(&args[2]);
1258
1259 return ret;
1260}
1261
1262
1263static int user_wrapper_stat_url(php_stream_wrapper *wrapper, const char *url, int flags,
1265{
1267 zval zfuncname, zretval;
1268 zval args[2];
1269 int call_result;
1270 zval object;
1271 int ret = -1;
1272
1273 /* create an instance of our class */
1274 user_stream_create_object(uwrap, context, &object);
1275 if (Z_TYPE(object) == IS_UNDEF) {
1276 return ret;
1277 }
1278
1279 /* call it's stat_url method - set up params first */
1280 ZVAL_STRING(&args[0], url);
1281 ZVAL_LONG(&args[1], flags);
1282
1283 ZVAL_STRING(&zfuncname, USERSTREAM_STATURL);
1284
1285 call_result = call_method_if_exists(&object, &zfuncname, &zretval, 2, args);
1286
1287 if (call_result == SUCCESS && Z_TYPE(zretval) == IS_ARRAY) {
1288 /* We got the info we needed */
1289 statbuf_from_array(&zretval, ssb);
1290 ret = 0;
1291 } else {
1292 if (call_result == FAILURE) {
1293 php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_STATURL " is not implemented!",
1294 ZSTR_VAL(uwrap->ce->name));
1295 }
1296 }
1297
1298 /* clean up */
1299 zval_ptr_dtor(&object);
1300 zval_ptr_dtor(&zretval);
1301
1302 zval_ptr_dtor(&zfuncname);
1303 zval_ptr_dtor(&args[1]);
1304 zval_ptr_dtor(&args[0]);
1305
1306 return ret;
1307
1308}
1309
1310static ssize_t php_userstreamop_readdir(php_stream *stream, char *buf, size_t count)
1311{
1313 zval retval;
1314 int call_result;
1315 size_t didread = 0;
1318
1319 /* avoid problems if someone mis-uses the stream */
1320 if (count != sizeof(php_stream_dirent))
1321 return -1;
1322
1324
1325 call_result = call_method_if_exists(&us->object, &func_name, &retval, 0, NULL);
1326
1327 if (call_result == SUCCESS && Z_TYPE(retval) != IS_FALSE && Z_TYPE(retval) != IS_TRUE) {
1329 PHP_STRLCPY(ent->d_name, Z_STRVAL(retval), sizeof(ent->d_name), Z_STRLEN(retval));
1330 ent->d_type = DT_UNKNOWN;
1331
1332 didread = sizeof(php_stream_dirent);
1333 } else if (call_result == FAILURE) {
1334 php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_DIR_READ " is not implemented!",
1335 ZSTR_VAL(us->wrapper->ce->name));
1336 }
1337
1340
1341 return didread;
1342}
1343
1344static int php_userstreamop_closedir(php_stream *stream, int close_handle)
1345{
1347 zval retval;
1349
1350 assert(us != NULL);
1351
1353
1354 call_method_if_exists(&us->object, &func_name, &retval, 0, NULL);
1355
1358 zval_ptr_dtor(&us->object);
1359 ZVAL_UNDEF(&us->object);
1360
1361 efree(us);
1362
1363 return 0;
1364}
1365
1366static int php_userstreamop_rewinddir(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffs)
1367{
1369 zval retval;
1371
1373
1374 call_method_if_exists(&us->object, &func_name, &retval, 0, NULL);
1375
1378
1379 return 0;
1380
1381}
1382
1383static int php_userstreamop_cast(php_stream *stream, int castas, void **retptr)
1384{
1387 zval retval;
1388 zval args[1];
1389 php_stream * intstream = NULL;
1390 int call_result;
1391 int ret = FAILURE;
1392 /* If we are checking if the stream can cast, no return pointer is provided, so do not emit errors */
1393 bool report_errors = retptr;
1394
1396
1397 switch(castas) {
1400 break;
1401 default:
1403 break;
1404 }
1405
1406 call_result = call_method_if_exists(&us->object, &func_name, &retval, 1, args);
1407
1408 do {
1409 if (call_result == FAILURE) {
1410 if (report_errors) {
1411 php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " is not implemented!",
1412 ZSTR_VAL(us->wrapper->ce->name));
1413 }
1414 break;
1415 }
1416 if (!zend_is_true(&retval)) {
1417 break;
1418 }
1420 if (!intstream) {
1421 if (report_errors) {
1422 php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " must return a stream resource",
1423 ZSTR_VAL(us->wrapper->ce->name));
1424 }
1425 break;
1426 }
1427 if (intstream == stream) {
1428 if (report_errors) {
1429 php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " must not return itself",
1430 ZSTR_VAL(us->wrapper->ce->name));
1431 }
1432 intstream = NULL;
1433 break;
1434 }
1435 ret = php_stream_cast(intstream, castas, retptr, 1);
1436 } while (0);
1437
1440 zval_ptr_dtor(&args[0]);
1441
1442 return ret;
1443}
1444
1446 php_userstreamop_write, php_userstreamop_read,
1447 php_userstreamop_close, php_userstreamop_flush,
1448 "user-space",
1449 php_userstreamop_seek,
1450 php_userstreamop_cast,
1451 php_userstreamop_stat,
1452 php_userstreamop_set_option,
1453};
1454
1456 NULL, /* write */
1457 php_userstreamop_readdir,
1458 php_userstreamop_closedir,
1459 NULL, /* flush */
1460 "user-space-dir",
1461 php_userstreamop_rewinddir,
1462 NULL, /* cast */
1463 NULL, /* stat */
1464 NULL /* set_option */
1465};
bool exception
Definition assert.c:30
stream_wrapper_restore(string $protocol)
stream_wrapper_register(string $protocol, string $class, int $flags=0)
stream_wrapper_unregister(string $protocol)
count(Countable|array $value, int $mode=COUNT_NORMAL)
assert(mixed $assertion, Throwable|string|null $description=null)
zend_long ptrdiff_t
new_type size
Definition ffi.c:4365
memcpy(ptr1, ptr2, size)
memset(ptr, 0, type->size)
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
#define LOCK_NB
#define PHP_LOCK_EX
#define PHP_LOCK_NB
#define PHP_LOCK_UN
#define PHP_LOCK_SH
zend_long offset
char * mode
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
#define PHP_FUNCTION
Definition php.h:364
#define PHP_MINIT_FUNCTION
Definition php.h:400
#define PHP_STRLCPY(dst, src, size, src_size)
Definition php.h:142
#define PG(v)
Definition php_globals.h:31
PHP_JSON_API size_t int options
Definition php_json.h:102
PHPAPI const php_stream_ops php_stream_userspace_dir_ops
Definition userspace.c:1455
PHPAPI const php_stream_ops php_stream_userspace_ops
Definition userspace.c:1445
#define php_stream_cast(stream, as, ret, show_err)
struct _php_stream_wrapper_ops php_stream_wrapper_ops
struct _php_stream php_stream
Definition php_streams.h:96
struct _php_stream_context php_stream_context
Definition php_streams.h:98
#define PHP_STREAM_META_GROUP
#define PHP_STREAM_OPTION_BLOCKING
struct _php_stream_dirent php_stream_dirent
#define PHP_STREAM_AS_FD_FOR_SELECT
#define PHP_STREAM_TRUNCATE_SET_SIZE
#define PHP_STREAM_META_OWNER_NAME
#define STREAMS_DC
Definition php_streams.h:53
#define php_stream_alloc_rel(ops, thisptr, persistent, mode)
Definition php_streams.h:60
#define PHP_STREAM_FLAG_NO_SEEK
#define STREAM_OPEN_FOR_INCLUDE
#define PHP_STREAM_OPTION_WRITE_BUFFER
#define PHP_STREAM_META_GROUP_NAME
PHPAPI HashTable * php_stream_get_url_stream_wrappers_hash_global(void)
Definition streams.c:62
#define PHP_STREAM_OPTION_RETURN_NOTIMPL
#define PHP_STREAM_META_OWNER
#define PHP_STREAM_OPTION_READ_TIMEOUT
struct _php_stream_ops php_stream_ops
#define PHP_STREAM_OPTION_LOCKING
#define PHP_STREAM_META_TOUCH
#define PHP_STREAM_OPTION_READ_BUFFER
PHPAPI zend_result php_unregister_url_stream_wrapper_volatile(zend_string *protocol)
Definition streams.c:1953
#define php_stream_get_url_stream_wrappers_hash()
#define PHP_STREAM_OPTION_RETURN_ERR
#define PHP_STREAM_OPTION_CHECK_LIVENESS
#define php_stream_from_zval_no_verify(xstr, pzval)
#define PHP_STREAM_OPTION_TRUNCATE_API
#define PHP_STREAM_IS_URL
struct _php_stream_wrapper php_stream_wrapper
Definition php_streams.h:97
#define PHP_STREAM_TRUNCATE_SUPPORTED
PHPAPI zend_result php_register_url_stream_wrapper_volatile(zend_string *protocol, php_stream_wrapper *wrapper)
Definition streams.c:1940
#define PHP_STREAM_OPTION_RETURN_OK
#define PHP_STREAM_AS_STDIO
struct _php_stream_statbuf php_stream_statbuf
PHPAPI void php_stream_wrapper_log_error(const php_stream_wrapper *wrapper, int options, const char *fmt,...) PHP_ATTRIBUTE_FORMAT(printf
#define PHP_STREAM_META_ACCESS
const char * func_name
#define DT_UNKNOWN
Definition readdir.h:19
struct timeval tv
Definition session.c:1280
#define FG(v)
Definition file.h:117
unsigned char d_type
char d_name[MAXPATHLEN]
const php_stream_wrapper_ops * wops
uint16_t eof
uint32_t flags
void * abstract
struct php_user_stream_wrapper * wrapper
Definition userspace.c:92
zend_string * name
Definition zend.h:149
uint32_t ce_flags
Definition zend.h:156
zend_function * constructor
Definition zend.h:172
Definition dce.c:49
zend_resource * resource
Definition userspace.c:42
zend_class_entry * ce
Definition userspace.c:41
php_stream_wrapper wrapper
Definition userspace.c:39
#define USERSTREAM_RENAME
Definition userspace.c:109
#define USERSTREAM_LOCK
Definition userspace.c:116
#define USERSTREAM_DIR_REWIND
Definition userspace.c:114
#define USERSTREAM_UNLINK
Definition userspace.c:108
#define USERSTREAM_DIR_OPEN
Definition userspace.c:112
#define USERSTREAM_CLOSE
Definition userspace.c:99
struct _php_userstream_data php_userstream_data_t
Definition userspace.c:95
#define USERSTREAM_DIR_CLOSE
Definition userspace.c:115
#define USERSTREAM_MKDIR
Definition userspace.c:110
#define USERSTREAM_SEEK
Definition userspace.c:103
#define USERSTREAM_STATURL
Definition userspace.c:107
#define USERSTREAM_METADATA
Definition userspace.c:120
#define USERSTREAM_RMDIR
Definition userspace.c:111
#define USERSTREAM_OPEN
Definition userspace.c:98
#define USERSTREAM_FLUSH
Definition userspace.c:102
#define USERSTREAM_STAT
Definition userspace.c:106
#define USERSTREAM_DIR_READ
Definition userspace.c:113
#define USERSTREAM_CAST
Definition userspace.c:117
#define USERSTREAM_SET_OPTION
Definition userspace.c:118
#define USERSTREAM_TELL
Definition userspace.c:104
#define USERSTREAM_WRITE
Definition userspace.c:101
#define USERSTREAM_EOF
Definition userspace.c:105
#define USERSTREAM_READ
Definition userspace.c:100
#define USERSTREAM_TRUNCATE
Definition userspace.c:119
#define STAT_PROP_ENTRY(name)
#define zend_catch
Definition zend.h:277
#define zend_try
Definition zend.h:270
#define zend_end_try()
Definition zend.h:280
#define zend_bailout()
Definition zend.h:268
ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *class_type)
Definition zend_API.c:1849
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1300
ZEND_API bool zend_is_callable_ex(zval *callable, zend_object *object, uint32_t check_flags, zend_string **callable_name, zend_fcall_info_cache *fcc, char **error)
Definition zend_API.c:4271
ZEND_API void add_index_long(zval *arg, zend_ulong index, zend_long n)
Definition zend_API.c:2033
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
#define RETURN_FALSE
Definition zend_API.h:1058
#define IS_CALLABLE_SUPPRESS_DEPRECATIONS
Definition zend_API.h:412
#define ZVAL_STRING(z, s)
Definition zend_API.h:956
ZEND_API zend_result zend_call_method_if_exists(zend_object *object, zend_string *method_name, zval *retval, uint32_t param_count, zval *params)
#define RETURN_THROWS()
Definition zend_API.h:1060
#define ZVAL_STRINGL(z, s, l)
Definition zend_API.h:952
#define RETURN_TRUE
Definition zend_API.h:1059
#define array_init(arg)
Definition zend_API.h:537
#define estrndup(s, length)
Definition zend_alloc.h:165
#define ecalloc(nmemb, size)
Definition zend_alloc.h:158
#define efree(ptr)
Definition zend_alloc.h:155
#define emalloc(size)
Definition zend_alloc.h:151
struct _zval_struct zval
strcmp(string $string1, string $string2)
zval * args
#define ZEND_ACC_IMPLICIT_ABSTRACT_CLASS
#define ZEND_ACC_EXPLICIT_ABSTRACT_CLASS
#define ZEND_ACC_INTERFACE
#define ZEND_ACC_TRAIT
#define E_NOTICE
Definition zend_errors.h:26
#define E_WARNING
Definition zend_errors.h:24
#define LOCK_UN
#define LOCK_EX
#define LOCK_SH
#define EG(v)
ZEND_API zend_resource * zend_register_resource(void *rsrc_pointer, int rsrc_type)
Definition zend_list.c:87
ZEND_API zend_result ZEND_FASTCALL zend_list_delete(zend_resource *res)
Definition zend_list.c:46
ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, const char *type_name, int module_number)
Definition zend_list.c:265
int32_t zend_long
Definition zend_long.h:42
int32_t zend_off_t
Definition zend_long.h:44
#define ZEND_LONG_FMT
Definition zend_long.h:87
struct _zend_string zend_string
ZEND_API bool ZEND_FASTCALL zend_is_true(const zval *op)
ZEND_API void ZEND_FASTCALL convert_to_long(zval *op)
#define zval_is_true(op)
#define convert_to_string(op)
#define LONG_MAX
#define ZEND_ASSERT(c)
struct _zend_class_entry zend_class_entry
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define IS_TRUE
Definition zend_types.h:603
#define ZVAL_UNDEF(z)
#define IS_FALSE
Definition zend_types.h:602
#define IS_UNDEF
Definition zend_types.h:600
#define ZVAL_NULL(z)
#define ZVAL_LONG(z, l)
#define IS_STRING
Definition zend_types.h:606
struct _zend_resource zend_resource
Definition zend_types.h:99
struct _zend_array HashTable
Definition zend_types.h:386
#define Z_OBJ_P(zval_p)
Definition zend_types.h:990
#define IS_ARRAY
Definition zend_types.h:607
#define Z_STR_P(zval_p)
Definition zend_types.h:972
#define ZVAL_NEW_REF(z, r)
#define GC_ADDREF(p)
Definition zend_types.h:709
#define Z_REFVAL(zval)
#define Z_STRVAL(zval)
Definition zend_types.h:974
@ FAILURE
Definition zend_types.h:61
#define Z_STRLEN(zval)
Definition zend_types.h:977
#define IS_LONG
Definition zend_types.h:604
#define ZVAL_COPY(z, v)
ZEND_RESULT_CODE zend_result
Definition zend_types.h:64
#define Z_ISREF(zval)
Definition zend_types.h:953
#define Z_TYPE(zval)
Definition zend_types.h:659
#define Z_LVAL_P(zval_p)
Definition zend_types.h:966
#define Z_LVAL(zval)
Definition zend_types.h:965
#define Z_OBJ(zval)
Definition zend_types.h:989
ZEND_API void zval_ptr_dtor(zval *zval_ptr)
zval retval
object
zval * ret
value