// // ext-ioctl/ioctl.c // // @Author CismonX // #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "php_ioctl.h" #define ERRNO_SET(zval, err) \ if (zval) { \ ZVAL_DEREF(zval); \ ZVAL_LONG(zval, err); \ } PHP_FUNCTION(ioctl) { zval *fd; zend_long request; zend_string *argp = NULL; zval *err = NULL; ZEND_PARSE_PARAMETERS_START(2, 4) Z_PARAM_ZVAL(fd) Z_PARAM_LONG(request) Z_PARAM_OPTIONAL Z_PARAM_STR(argp) Z_PARAM_ZVAL(err) ZEND_PARSE_PARAMETERS_END(); php_stream *stream; int fd_num; if (Z_TYPE_P(fd) == IS_LONG) { fd_num = Z_LVAL_P(fd); } else if (UNEXPECTED(Z_TYPE_P(fd) != IS_RESOURCE)) { ERRNO_SET(err, -1); php_error_docref(NULL, E_WARNING, "Invalid fd. Resource or integer expected."); RETURN_FALSE; } else { php_stream_from_zval(stream, fd); struct { FILE *file; int fd; } *stream_data = stream->abstract; if (stream_data == NULL) { ERRNO_SET(err, -2); php_error_docref(NULL, E_WARNING, "Unexpected error. Failed to fetch stream data."); RETURN_FALSE; } fd_num = stream_data->fd; } int result = ioctl(fd_num, (int)request, argp ? ZSTR_VAL(argp) : NULL); if (result == -1) { ERRNO_SET(err, errno); RETURN_FALSE; } RETVAL_LONG(result); } ZEND_BEGIN_ARG_INFO(ioctl_arginfo, 0) ZEND_ARG_INFO(0, fd) ZEND_ARG_TYPE_INFO(0, request, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, argp, IS_STRING, 0) ZEND_ARG_INFO(1, errno) ZEND_END_ARG_INFO() #ifdef IOCTL_ENABLE_HELPER_FUNCTIONS PHP_FUNCTION(str_alloc) { zend_long len; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_LONG(len); ZEND_PARSE_PARAMETERS_END(); if (len < 0) { php_error_docref(NULL, E_WARNING, "Buffer length should be positive."); RETURN_EMPTY_STRING(); } zend_string *buf = zend_string_alloc(len, 0); #ifdef PHP_DEBUG // Make the string nul-terminated to prevent warnings on debug builds of PHP. ZSTR_VAL(buf)[len] = '\0'; #endif RETVAL_STR(buf); } ZEND_BEGIN_ARG_INFO(str_alloc_arginfo, 0) ZEND_ARG_TYPE_INFO(0, len, IS_LONG, 0) ZEND_END_ARG_INFO() PHP_FUNCTION(str2ptr) { zend_string *str; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_STR(str); ZEND_PARSE_PARAMETERS_END(); RETVAL_LONG((zend_long)ZSTR_VAL(str)); } ZEND_BEGIN_ARG_INFO(str2ptr_arginfo, 0) ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0) ZEND_END_ARG_INFO() PHP_FUNCTION(ptr2str) { zend_long ptr; zend_long length; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_LONG(ptr) Z_PARAM_LONG(length) ZEND_PARSE_PARAMETERS_END(); RETVAL_STR(zend_string_init((char*)ptr, length, 0)); } ZEND_BEGIN_ARG_INFO(ptr2str_arginfo, 0) ZEND_ARG_TYPE_INFO(0, ptr, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, length, IS_LONG, 0) ZEND_END_ARG_INFO() PHP_FUNCTION(res2fd) { zval *res; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ZVAL(res) ZEND_PARSE_PARAMETERS_END(); php_stream* stream; php_stream_from_zval(stream, res); struct { FILE *file; int fd; } *stream_data = stream->abstract; if (stream_data) { RETURN_LONG(stream_data->fd); } RETVAL_LONG(-1); } ZEND_BEGIN_ARG_INFO(res2fd_arginfo, 0) ZEND_ARG_TYPE_INFO(0, res, IS_RESOURCE, 0) ZEND_END_ARG_INFO() #endif // IOCTL_ENABLE_HELPER_FUNCTIONS zend_function_entry ioctl_functions[] = { PHP_FE(ioctl, ioctl_arginfo) #ifdef IOCTL_ENABLE_HELPER_FUNCTIONS PHP_FE(str_alloc, str_alloc_arginfo) PHP_FE(str2ptr, str2ptr_arginfo) PHP_FE(ptr2str, ptr2str_arginfo) PHP_FE(res2fd, res2fd_arginfo) #endif // IOCTL_ENABLE_HELPER_FUNCTIONS PHP_FE_END }; PHP_MINFO_FUNCTION(ioctl) { php_info_print_table_start(); php_info_print_table_header(2, "ioctl support", "enabled"); php_info_print_table_end(); } zend_module_entry ioctl_module_entry = { STANDARD_MODULE_HEADER, "ioctl", ioctl_functions, NULL, NULL, NULL, NULL, PHP_MINFO(ioctl), PHP_IOCTL_VERSION, STANDARD_MODULE_PROPERTIES }; #ifdef COMPILE_DL_IOCTL ZEND_GET_MODULE(ioctl) #endif