This repository has been archived on 2018-05-01. You can view files and clone it, but cannot push or open issues or pull requests.
ext-ioctl/src/ioctl.c

183 lines
4.3 KiB
C

//
// ext-ioctl/ioctl.c
//
// @Author CismonX
//
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <php.h>
#include <ext/standard/info.h>
#include <sys/ioctl.h>
#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