/* +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to the Modified BSD License that is | | bundled with this package in the file LICENSE, and is available | | through the World Wide Web at . | | | | SPDX-License-Identifier: BSD-3-Clause | +----------------------------------------------------------------------+ | Authors: Jakub Zelenka | +----------------------------------------------------------------------+ */ #ifndef PHP_STREAM_ERRORS_H #define PHP_STREAM_ERRORS_H #include "php.h" #include "php_streams.h" #include "stream_errors_decl.h" BEGIN_EXTERN_C() /* Maximum operation nesting depth */ #define PHP_STREAM_ERROR_MAX_DEPTH 1000 /* Operations pool size to prevent extra allocations */ #define PHP_STREAM_ERROR_OPERATION_POOL_SIZE 8 /* Shorthand for error code enum values */ #define PHP_STREAM_EC(name) ZEND_ENUM_StreamErrorCode_##name /* Error code range boundaries (case_id based, ranges are [start, end)) */ #define STREAM_EC_IO_START PHP_STREAM_EC(ReadFailed) #define STREAM_EC_IO_END PHP_STREAM_EC(Disabled) #define STREAM_EC_FS_START PHP_STREAM_EC(Disabled) #define STREAM_EC_FS_END PHP_STREAM_EC(NotImplemented) #define STREAM_EC_WRAPPER_START PHP_STREAM_EC(NotImplemented) #define STREAM_EC_WRAPPER_END PHP_STREAM_EC(FilterNotFound) #define STREAM_EC_FILTER_START PHP_STREAM_EC(FilterNotFound) #define STREAM_EC_FILTER_END PHP_STREAM_EC(CastFailed) #define STREAM_EC_CAST_START PHP_STREAM_EC(CastFailed) #define STREAM_EC_CAST_END PHP_STREAM_EC(NetworkSendFailed) #define STREAM_EC_NETWORK_START PHP_STREAM_EC(NetworkSendFailed) #define STREAM_EC_NETWORK_END PHP_STREAM_EC(ArchivingFailed) #define STREAM_EC_ENCODING_START PHP_STREAM_EC(ArchivingFailed) #define STREAM_EC_ENCODING_END PHP_STREAM_EC(AllocationFailed) #define STREAM_EC_RESOURCE_START PHP_STREAM_EC(AllocationFailed) #define STREAM_EC_RESOURCE_END PHP_STREAM_EC(LockFailed) #define STREAM_EC_LOCK_START PHP_STREAM_EC(LockFailed) #define STREAM_EC_LOCK_END PHP_STREAM_EC(UserspaceNotImplemented) #define STREAM_EC_USERSPACE_START PHP_STREAM_EC(UserspaceNotImplemented) #define STREAM_EC_USERSPACE_END (PHP_STREAM_EC(UserspaceCallFailed) + 1) /* Wrapper name for PHP errors */ #define PHP_STREAM_ERROR_WRAPPER_DEFAULT_NAME ":na" #define PHP_STREAM_ERROR_WRAPPER_NAME(_wrapper) \ (_wrapper ? _wrapper->wops->label : PHP_STREAM_ERROR_WRAPPER_DEFAULT_NAME) /* Error entry in chain (internal linked list) */ typedef struct _php_stream_error_entry { zend_string *message; zend_enum_StreamErrorCode code; char *wrapper_name; char *docref; int severity; bool terminating; struct _php_stream_error_entry *next; } php_stream_error_entry; /* Active error operation */ typedef struct _php_stream_error_operation { php_stream_error_entry *first_error; php_stream_error_entry *last_error; uint32_t error_count; } php_stream_error_operation; /* Stored completed operation */ typedef struct _php_stream_stored_error { php_stream_error_entry *first_error; uint32_t error_count; struct _php_stream_stored_error *next; } php_stream_stored_error; typedef struct { php_stream_error_operation *current_operation; uint32_t operation_depth; uint32_t operation_floor; uint32_t refused_operations; php_stream_stored_error *stored_errors; uint32_t stored_count; php_stream_error_operation operation_pool[PHP_STREAM_ERROR_OPERATION_POOL_SIZE]; php_stream_error_operation *overflow_operations; uint32_t overflow_capacity; } php_stream_error_state; /* Error operation management */ PHPAPI php_stream_error_operation *php_stream_error_operation_begin(void); PHPAPI void php_stream_error_operation_end(const php_stream_context *context); PHPAPI void php_stream_error_operation_end_for_stream(const php_stream *stream); PHPAPI void php_stream_error_operation_abort(void); /* State cleanup function */ PHPAPI void php_stream_error_state_cleanup(void); /* Retrieve last stored errors as array of StreamError objects */ PHPAPI void php_stream_error_get_last(zval *return_value); /* Clear all stored errors */ PHPAPI void php_stream_error_clear_stored(void); /* Wrapper error reporting functions */ PHPAPI void php_stream_wrapper_error_with_name(const char *wrapper_name, const php_stream_context *context, const char *docref, int options, int severity, bool terminating, zend_enum_StreamErrorCode code, const char *fmt, ...) ZEND_ATTRIBUTE_FORMAT(printf, 8, 9); PHPAPI void php_stream_wrapper_error( const php_stream_wrapper *wrapper, const php_stream_context *context, const char *docref, int options, int severity, bool terminating, zend_enum_StreamErrorCode code, const char *fmt, ...) ZEND_ATTRIBUTE_FORMAT(printf, 8, 9); PHPAPI void php_stream_error(const php_stream *stream, const char *docref, int severity, bool terminating, zend_enum_StreamErrorCode code, const char *fmt, ...) ZEND_ATTRIBUTE_FORMAT(printf, 6, 7); /* Legacy wrapper error log functions */ PHPAPI void php_stream_wrapper_log_error(const php_stream_wrapper *wrapper, const php_stream_context *context, int options, int severity, bool terminating, zend_enum_StreamErrorCode code, const char *fmt, ...) ZEND_ATTRIBUTE_FORMAT(printf, 7, 8); PHPAPI void php_stream_display_wrapper_name_errors(const char *wrapper_name, const php_stream_context *context, zend_enum_StreamErrorCode code, const char *caption); PHPAPI void php_stream_display_wrapper_errors(const php_stream_wrapper *wrapper, const php_stream_context *context, zend_enum_StreamErrorCode code, const char *caption); PHPAPI void php_stream_tidy_wrapper_name_error_log(const char *wrapper_name); PHPAPI void php_stream_tidy_wrapper_error_log(const php_stream_wrapper *wrapper); /* Convenience macros - code argument is the bare case name (e.g. RenameFailed) */ #define php_stream_wrapper_warn(wrapper, context, options, code, ...) \ php_stream_wrapper_error(wrapper, context, NULL, options, E_WARNING, true, \ PHP_STREAM_EC(code), __VA_ARGS__) #define php_stream_wrapper_warn_name(wrapper_name, context, options, code, ...) \ php_stream_wrapper_error_with_name( \ wrapper_name, context, NULL, options, E_WARNING, true, \ PHP_STREAM_EC(code), __VA_ARGS__) #define php_stream_wrapper_warn_nt(wrapper, context, options, code, ...) \ php_stream_wrapper_error(wrapper, context, NULL, options, E_WARNING, false, \ PHP_STREAM_EC(code), __VA_ARGS__) #define php_stream_wrapper_notice(wrapper, context, options, code, ...) \ php_stream_wrapper_error(wrapper, context, NULL, options, E_NOTICE, false, \ PHP_STREAM_EC(code), __VA_ARGS__) #define php_stream_warn(stream, code, ...) \ php_stream_error(stream, NULL, E_WARNING, true, PHP_STREAM_EC(code), __VA_ARGS__) #define php_stream_warn_nt(stream, code, ...) \ php_stream_error(stream, NULL, E_WARNING, false, PHP_STREAM_EC(code), __VA_ARGS__) #define php_stream_warn_docref(stream, docref, code, ...) \ php_stream_error(stream, docref, E_WARNING, true, PHP_STREAM_EC(code), __VA_ARGS__) #define php_stream_notice(stream, code, ...) \ php_stream_error(stream, NULL, E_NOTICE, false, PHP_STREAM_EC(code), __VA_ARGS__) #define php_stream_fatal(stream, code, ...) \ php_stream_error(stream, NULL, E_ERROR, true, PHP_STREAM_EC(code), __VA_ARGS__) /* Legacy log variants */ #define php_stream_wrapper_log_warn(wrapper, context, options, code, ...) \ php_stream_wrapper_log_error(wrapper, context, options, E_WARNING, true, \ PHP_STREAM_EC(code), __VA_ARGS__) #define php_stream_wrapper_log_warn_nt(wrapper, context, options, code, ...) \ php_stream_wrapper_log_error(wrapper, context, options, E_WARNING, false, \ PHP_STREAM_EC(code), __VA_ARGS__) #define php_stream_wrapper_log_notice(wrapper, context, options, code, ...) \ php_stream_wrapper_log_error(wrapper, context, options, E_NOTICE, false, \ PHP_STREAM_EC(code), __VA_ARGS__) END_EXTERN_C() #endif /* PHP_STREAM_ERRORS_H */