@@ -594,6 +594,104 @@ PHP_FUNCTION(stream_get_wrappers)
594594}
595595/* }}} */
596596
597+ /* Helper function to convert error list to array */
598+ static void php_stream_errors_list_to_array (zend_llist * list , zval * return_value )
599+ {
600+ php_stream_error_entry * * err_entry_p ;
601+ zend_llist_position pos ;
602+
603+ for (err_entry_p = zend_llist_get_first_ex (list , & pos );
604+ err_entry_p ;
605+ err_entry_p = zend_llist_get_next_ex (list , & pos )) {
606+ php_stream_error_entry * entry = * err_entry_p ;
607+ zval error_array ;
608+ array_init (& error_array );
609+
610+ add_assoc_str (& error_array , "message" , zend_string_copy (entry -> message ));
611+ add_assoc_long (& error_array , "code" , entry -> code );
612+ add_assoc_long (& error_array , "severity" , entry -> severity );
613+ add_assoc_bool (& error_array , "terminal" , entry -> terminal );
614+
615+ if (entry -> wrapper_name ) {
616+ add_assoc_string (& error_array , "wrapper" , entry -> wrapper_name );
617+ }
618+ if (entry -> param ) {
619+ add_assoc_string (& error_array , "param" , entry -> param );
620+ }
621+ if (entry -> docref ) {
622+ add_assoc_string (& error_array , "docref" , entry -> docref );
623+ }
624+
625+ add_next_index_zval (return_value , & error_array );
626+ }
627+ }
628+
629+ /* Retrieves list of stored stream errors */
630+ PHP_FUNCTION (stream_get_errors )
631+ {
632+ zval * subject = NULL ;
633+ php_stream * stream = NULL ;
634+ char * wrapper_name = NULL ;
635+ size_t wrapper_name_len = 0 ;
636+ bool get_all_wrappers = false;
637+
638+ ZEND_PARSE_PARAMETERS_START (0 , 1 )
639+ Z_PARAM_OPTIONAL
640+ Z_PARAM_ZVAL (subject )
641+ ZEND_PARSE_PARAMETERS_END ();
642+
643+ /* Determine what we're querying for */
644+ if (subject == NULL ) {
645+ /* No parameter - get all wrapper errors */
646+ get_all_wrappers = true;
647+ } else if (Z_TYPE_P (subject ) == IS_RESOURCE ) {
648+ /* Stream resource - get errors for this stream */
649+ php_stream_from_zval_no_verify (stream , subject );
650+ if (stream == NULL ) {
651+ zend_argument_type_error (1 , "must be a valid stream resource" );
652+ RETURN_THROWS ();
653+ }
654+ } else if (Z_TYPE_P (subject ) == IS_STRING ) {
655+ /* Wrapper name - get errors for this wrapper */
656+ wrapper_name = Z_STRVAL_P (subject );
657+ wrapper_name_len = Z_STRLEN_P (subject );
658+ } else {
659+ zend_argument_type_error (1 , "must be a stream resource, string, or null" );
660+ RETURN_THROWS ();
661+ }
662+
663+ array_init (return_value );
664+
665+ /* Handle stream errors */
666+ if (stream ) {
667+ if (stream -> error_list ) {
668+ php_stream_errors_list_to_array (stream -> error_list , return_value );
669+ }
670+ } else if (get_all_wrappers ) {
671+ /* Get errors from all wrappers */
672+ if (FG (wrapper_stored_errors )) {
673+ zend_string * key ;
674+ zval * val ;
675+ ZEND_HASH_FOREACH_STR_KEY_VAL (FG (wrapper_stored_errors ), key , val ) {
676+ if (key ) {
677+ zend_llist * list = (zend_llist * ) Z_PTR_P (val );
678+ php_stream_errors_list_to_array (list , return_value );
679+ }
680+ } ZEND_HASH_FOREACH_END ();
681+ }
682+ } else if (wrapper_name ) {
683+ /* Get errors for specific wrapper */
684+ if (FG (wrapper_stored_errors )) {
685+ zend_llist * list = zend_hash_str_find_ptr (
686+ FG (wrapper_stored_errors ), wrapper_name , wrapper_name_len );
687+
688+ if (list ) {
689+ php_stream_errors_list_to_array (list , return_value );
690+ }
691+ }
692+ }
693+ }
694+
597695/* {{{ stream_select related functions */
598696static int stream_array_to_fd_set (const HashTable * stream_array , fd_set * fds , php_socket_t * max_fd )
599697{
0 commit comments