From ef537403e682950acfff8fce19fbad8ce4176bab Mon Sep 17 00:00:00 2001 From: Sterling Hughes Date: Tue, 6 Nov 2001 12:24:09 +0000 Subject: [PATCH] @ Add Direct I/O extension for lowlevel access to the POSIX layer. (sterling) --- ext/dio/EXPERIMENTAL | 0 ext/dio/Makefile.in | 8 + ext/dio/config.m4 | 6 + ext/dio/dio.c | 402 +++++++++++++++++++++++++++++++++++++++++ ext/dio/php_dio.h | 63 +++++++ ext/dio/tests/001.phpt | 23 +++ 6 files changed, 502 insertions(+) create mode 100644 ext/dio/EXPERIMENTAL create mode 100644 ext/dio/Makefile.in create mode 100644 ext/dio/config.m4 create mode 100644 ext/dio/dio.c create mode 100644 ext/dio/php_dio.h create mode 100644 ext/dio/tests/001.phpt diff --git a/ext/dio/EXPERIMENTAL b/ext/dio/EXPERIMENTAL new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ext/dio/Makefile.in b/ext/dio/Makefile.in new file mode 100644 index 0000000000..c9ac3faf74 --- /dev/null +++ b/ext/dio/Makefile.in @@ -0,0 +1,8 @@ +# $Id$ + +LTLIBRARY_NAME = libdio.la +LTLIBRARY_SOURCES = dio.c +LTLIBRARY_SHARED_NAME = dio.la +LTLIBRARY_SHARED_LIBADD = $(DIO_SHARED_LIBADD) + +include $(top_srcdir)/build/dynlib.mk diff --git a/ext/dio/config.m4 b/ext/dio/config.m4 new file mode 100644 index 0000000000..4ad2cf6522 --- /dev/null +++ b/ext/dio/config.m4 @@ -0,0 +1,6 @@ +PHP_ARG_ENABLE(dio, whether to enable dio support, +[ --enable-dio Enable dio support]) + +if test "$PHP_DIO" != "no"; then + PHP_EXTENSION(dio, $ext_shared) +fi diff --git a/ext/dio/dio.c b/ext/dio/dio.c new file mode 100644 index 0000000000..5ee3d48816 --- /dev/null +++ b/ext/dio/dio.c @@ -0,0 +1,402 @@ +/* + +----------------------------------------------------------------------+ + | PHP version 4.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Sterling Hughes | + +----------------------------------------------------------------------+ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/info.h" +#include "php_dio.h" + +#include +#include +#include +#include + +#define le_fd_name "Direct I/O File Descriptor" +static int le_fd; + +function_entry dio_functions[] = { + PHP_FE(dio_open, NULL) + PHP_FE(dio_truncate, NULL) + PHP_FE(dio_stat, NULL) + PHP_FE(dio_seek, NULL) + PHP_FE(dio_fcntl, NULL) + PHP_FE(dio_read, NULL) + PHP_FE(dio_write, NULL) + PHP_FE(dio_close, NULL) + {NULL, NULL, NULL} +}; + + +zend_module_entry dio_module_entry = { + STANDARD_MODULE_HEADER, + "dio", + dio_functions, + PHP_MINIT(dio), + NULL, + NULL, + NULL, + PHP_MINFO(dio), + "0.1", + STANDARD_MODULE_PROPERTIES +}; + + +#ifdef COMPILE_DL_DIO +ZEND_GET_MODULE(dio) +#endif + + +static void _dio_close_fd(zend_rsrc_list_entry *rsrc TSRMLS_DC) +{ + php_fd_t *f = (php_fd_t *) rsrc->ptr; + close(f->fd); + free(f); +} + +#define RDIOC(c) REGISTER_LONG_CONSTANT(#c, c, CONST_CS | CONST_PERSISTENT) + +PHP_MINIT_FUNCTION(dio) +{ + le_fd = zend_register_list_destructors_ex(_dio_close_fd, NULL, le_fd_name, module_number); + + RDIOC(O_RDONLY); + RDIOC(O_WRONLY); + RDIOC(O_RDWR); + RDIOC(O_CREAT); + RDIOC(O_EXCL); + RDIOC(O_TRUNC); + RDIOC(O_APPEND); + RDIOC(O_NONBLOCK); + RDIOC(O_NDELAY); + RDIOC(O_SYNC); + RDIOC(S_IRWXU); + RDIOC(S_IRUSR); + RDIOC(S_IWUSR); + RDIOC(S_IXUSR); + RDIOC(S_IRWXG); + RDIOC(S_IRGRP); + RDIOC(S_IWGRP); + RDIOC(S_IXGRP); + RDIOC(S_IRWXO); + RDIOC(S_IROTH); + RDIOC(S_IWOTH); + RDIOC(S_IXOTH); + RDIOC(F_DUPFD); + RDIOC(F_GETFD); + RDIOC(F_GETFL); + RDIOC(F_SETFL); + RDIOC(F_GETLK); + RDIOC(F_SETLK); + RDIOC(F_SETLKW); + RDIOC(F_SETOWN); + RDIOC(F_GETOWN); + RDIOC(F_UNLCK); + RDIOC(F_RDLCK); + RDIOC(F_WRLCK); + + return SUCCESS; +} + +PHP_MINFO_FUNCTION(dio) +{ + php_info_print_table_start(); + php_info_print_table_header(2, "dio support", "enabled"); + php_info_print_table_end(); +} + +static void new_php_fd(php_fd_t **f, int fd) +{ + *f = malloc(sizeof(php_fd_t)); + (*f)->fd = fd; +} + +/* {{{ proto resource dio_open(string filename, int flags[, int mode]) + Open a new filename with specified permissions of flags and creation permissions of mode */ +PHP_FUNCTION(dio_open) +{ + php_fd_t *f; + char *file_name; + int file_name_length; + int flags; + mode_t mode = 0; + int fd; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|l", &file_name, &file_name_length, &flags, &mode) == FAILURE) { + return; + } + + if (ZEND_NUM_ARGS() == 3) { + fd = open(file_name, flags, mode); + } + else { + fd = open(file_name, flags); + } + + if (fd == -1) { + php_error(E_WARNING, "Cannot open file %s with flags %d and permissions %d: %s", + file_name, flags, mode, strerror(errno)); + RETURN_FALSE; + } + + new_php_fd(&f, fd); + ZEND_REGISTER_RESOURCE(return_value, f, le_fd); +} +/* }}} */ + +/* {{{ string dio_read(resource fd[, int n]) + Read n bytes from fd and return them, if n is not specified, read 1k */ +PHP_FUNCTION(dio_read) +{ + zval *r_fd; + php_fd_t *f; + char *data; + int bytes = 1024; + ssize_t res; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &r_fd, &bytes) == FAILURE) { + return; + } + ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd); + + data = emalloc(bytes + 1); + res = read(f->fd, data, bytes); + if (res <= 0) { + RETURN_NULL(); + } + + data[res] = 0; + RETURN_STRINGL(data, res, 0); +} +/* }}} */ + +/* {{{ int dio_write(resource fd, string data[, int len]) + Write data to fd with optional truncation at length */ +PHP_FUNCTION(dio_write) +{ + zval *r_fd; + php_fd_t *f; + char *data; + size_t data_len; + size_t trunc_len = 0; + ssize_t res; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &r_fd, &data, &data_len, &trunc_len) == FAILURE) { + return; + } + ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd); + + res = write(f->fd, data, trunc_len ? trunc_len : data_len); + if (res == -1) { + php_error(E_WARNING, "Cannot write data to file descriptor %d, %s", f->fd, strerror(errno)); + } + + RETURN_LONG(res); +} +/* }}} */ + +/* {{{ proto bool dio_truncate(resource fd, int offset) + Truncate file descriptor fd to offset bytes */ +PHP_FUNCTION(dio_truncate) +{ + zval *r_fd; + php_fd_t *f; + off_t offset; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &r_fd, &offset) == FAILURE) { + return; + } + ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd); + + if (ftruncate(f->fd, offset) == -1) { + php_error(E_WARNING, "Couldn't truncate %d to %d bytes: %s", f->fd, offset, strerror(errno)); + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ + +#define ADD_FIELD(f, v) add_assoc_long_ex(return_value, (f), sizeof(f), v); + +/* {{{ proto array dio_stat(resource fd) + Get stat information about the file descriptor fd */ +PHP_FUNCTION(dio_stat) +{ + zval *r_fd; + php_fd_t *f; + struct stat s; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &r_fd) == FAILURE) { + return; + } + ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd); + + if (fstat(f->fd, &s) == -1) { + php_error(E_WARNING, "Cannot stat %d: %s", f->fd, strerror(errno)); + RETURN_FALSE; + } + + array_init(return_value); + ADD_FIELD("device", s.st_dev); + ADD_FIELD("inode", s.st_ino); + ADD_FIELD("mode", s.st_mode); + ADD_FIELD("nlink", s.st_nlink); + ADD_FIELD("uid", s.st_uid); + ADD_FIELD("gid", s.st_gid); + ADD_FIELD("device_type", s.st_rdev); + ADD_FIELD("size", s.st_size); + ADD_FIELD("block_size", s.st_blksize); + ADD_FIELD("blocks", s.st_blocks); + ADD_FIELD("atime", s.st_atime); + ADD_FIELD("mtime", s.st_mtime); + ADD_FIELD("ctime", s.st_ctime); +} +/* }}} */ + +/* {{{ proto int dio_seek(resource fd, int pos, int whence) + Seek to pos on fd from whence */ +PHP_FUNCTION(dio_seek) +{ + zval *r_fd; + php_fd_t *f; + off_t offset; + int whence = SEEK_SET; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|l", &r_fd, &offset, &whence) == FAILURE) { + return; + } + ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd); + + RETURN_LONG(lseek(f->fd, offset, whence)); +} +/* }}} */ + +/* {{{ proto mixed dio_fcntl(resource fd, int cmd[, mixed arg]) + Perform a c library fcntl on fd */ +PHP_FUNCTION(dio_fcntl) +{ + zval *r_fd; + zval *arg; + php_fd_t *f; + int cmd; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|z", &r_fd, &cmd, &arg) == FAILURE) { + return; + } + ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd); + + switch (cmd) { + case F_SETLK: + case F_SETLKW: { + zval **element; + struct flock lk = {0}; + HashTable *fh = HASH_OF(arg); + if (fh) { + if (zend_hash_find(fh, "start", 5, (void **) &element) == FAILURE) { + lk.l_start = 0; + } + else { + lk.l_start = Z_LVAL_PP(element); + } + + if (zend_hash_find(fh, "length", 6, (void **) &element) == FAILURE) { + lk.l_len = 0; + } + else { + lk.l_len = Z_LVAL_PP(element); + } + + if (zend_hash_find(fh, "whence", 6, (void **) &element) == FAILURE) { + lk.l_whence = 0; + } + else { + lk.l_whence = SEEK_SET; + } + + if (zend_hash_find(fh, "type", 6, (void **) &element) == FAILURE) { + lk.l_type = 0; + } + else { + lk.l_type = Z_LVAL_PP(element); + } + } + else { + lk.l_start = 0; + lk.l_len = 0; + lk.l_whence = SEEK_SET; + lk.l_type = Z_LVAL_P(arg); + } + + RETURN_LONG(fcntl(f->fd, cmd, &lk)); + break; + } + case F_GETLK: { + struct flock lk = {0}; + + fcntl(f->fd, cmd, &lk); + + array_init(return_value); + add_assoc_long(return_value, "type", lk.l_type); + add_assoc_long(return_value, "whence", lk.l_whence); + add_assoc_long(return_value, "start", lk.l_start); + add_assoc_long(return_value, "length", lk.l_len); + add_assoc_long(return_value, "pid", lk.l_pid); + + break; + } + case F_DUPFD: { + php_fd_t *new_f; + + new_php_fd(&new_f, fcntl(f->fd, cmd, Z_LVAL_P(arg))); + ZEND_REGISTER_RESOURCE(return_value, new_f, le_fd); + break; + } + default: + RETURN_LONG(fcntl(f->fd, cmd, Z_LVAL_P(arg))); + } +} +/* }}} */ + +/* {{{ proto void dio_close(resource fd) + Close the file descriptor given by fd */ +PHP_FUNCTION(dio_close) +{ + zval *r_fd; + php_fd_t *f; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &r_fd) == FAILURE) { + return; + } + ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd); + + zend_list_delete(Z_LVAL_P(r_fd)); +} +/* }}} */ + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 4 + * End: + * vim600: fdm=marker + * vim: sw=4 ts=4 noet + */ diff --git a/ext/dio/php_dio.h b/ext/dio/php_dio.h new file mode 100644 index 0000000000..65d9c6672e --- /dev/null +++ b/ext/dio/php_dio.h @@ -0,0 +1,63 @@ +/* + +----------------------------------------------------------------------+ + | PHP version 4.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Sterling Hughes | | + +----------------------------------------------------------------------+ + */ + +#ifndef PHP_DIO_H +#define PHP_DIO_H + +extern zend_module_entry dio_module_entry; +#define phpext_dio_ptr &dio_module_entry + +#ifdef PHP_WIN32 +#define PHP_DIO_API __declspec(dllexport) +#else +#define PHP_DIO_API +#endif + +#ifdef ZTS +#include "TSRM.h" +#endif + +PHP_MINIT_FUNCTION(dio); +PHP_MSHUTDOWN_FUNCTION(dio); +PHP_RINIT_FUNCTION(dio); +PHP_RSHUTDOWN_FUNCTION(dio); +PHP_MINFO_FUNCTION(dio); + +PHP_FUNCTION(dio_open); +PHP_FUNCTION(dio_truncate); +PHP_FUNCTION(dio_stat); +PHP_FUNCTION(dio_seek); +PHP_FUNCTION(dio_read); +PHP_FUNCTION(dio_write); +PHP_FUNCTION(dio_fcntl); +PHP_FUNCTION(dio_close); + +typedef struct { + int fd; +} php_fd_t; + +#endif + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ diff --git a/ext/dio/tests/001.phpt b/ext/dio/tests/001.phpt new file mode 100644 index 0000000000..d527e1a961 --- /dev/null +++ b/ext/dio/tests/001.phpt @@ -0,0 +1,23 @@ +--TEST-- +Check for dio presence +--SKIPIF-- + +--POST-- +--GET-- +--FILE-- + +--EXPECT-- +dio extension is available \ No newline at end of file -- 2.40.0