2001-11-06 12:24:09 +00:00
|
|
|
/*
|
|
|
|
+----------------------------------------------------------------------+
|
2001-12-11 15:32:16 +00:00
|
|
|
| PHP Version 4 |
|
2001-11-06 12:24:09 +00:00
|
|
|
+----------------------------------------------------------------------+
|
2002-02-28 08:29:35 +00:00
|
|
|
| Copyright (c) 1997-2002 The PHP Group |
|
2001-11-06 12:24:09 +00:00
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| 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. |
|
|
|
|
+----------------------------------------------------------------------+
|
2002-02-28 08:29:35 +00:00
|
|
|
| Author: Sterling Hughes <sterling@php.net> |
|
2001-11-06 12:24:09 +00:00
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
*/
|
|
|
|
|
|
|
|
#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 <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
#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)
|
|
|
|
|
2002-03-24 21:16:02 +00:00
|
|
|
#define DIO_UNDEF_CONST -1
|
|
|
|
|
2001-11-06 12:24:09 +00:00
|
|
|
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);
|
2002-03-24 21:16:02 +00:00
|
|
|
#ifdef O_SYNC
|
2001-11-06 12:24:09 +00:00
|
|
|
RDIOC(O_SYNC);
|
2002-03-24 21:16:02 +00:00
|
|
|
#endif
|
2002-01-04 19:42:31 +00:00
|
|
|
RDIOC(O_NOCTTY);
|
2001-11-06 12:24:09 +00:00
|
|
|
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) {
|
2002-01-10 09:09:19 +00:00
|
|
|
php_error(E_WARNING, "%s(): cannot open file %s with flags %d and permissions %d: %s",
|
|
|
|
get_active_function_name(TSRMLS_C), file_name, flags, mode, strerror(errno));
|
2001-11-06 12:24:09 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
new_php_fd(&f, fd);
|
|
|
|
ZEND_REGISTER_RESOURCE(return_value, f, le_fd);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-06 17:09:09 +00:00
|
|
|
/* {{{ proto string dio_read(resource fd[, int n])
|
2001-11-06 12:24:09 +00:00
|
|
|
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();
|
|
|
|
}
|
2002-04-20 16:08:30 +00:00
|
|
|
|
2002-04-20 18:58:20 +00:00
|
|
|
data = erealloc(data, res + 1);
|
2001-11-06 12:24:09 +00:00
|
|
|
data[res] = 0;
|
2002-04-20 16:08:30 +00:00
|
|
|
|
2001-11-06 12:24:09 +00:00
|
|
|
RETURN_STRINGL(data, res, 0);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-12-06 17:09:09 +00:00
|
|
|
/* {{{ proto int dio_write(resource fd, string data[, int len])
|
2001-11-06 12:24:09 +00:00
|
|
|
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) {
|
2002-01-10 09:09:19 +00:00
|
|
|
php_error(E_WARNING, "%s(): cannot write data to file descriptor %d, %s",
|
|
|
|
get_active_function_name(TSRMLS_C), f->fd, strerror(errno));
|
2001-11-06 12:24:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2002-01-10 09:09:19 +00:00
|
|
|
php_error(E_WARNING, "%s(): couldn't truncate %d to %d bytes: %s",
|
|
|
|
get_active_function_name(TSRMLS_C), f->fd, offset, strerror(errno));
|
2001-11-06 12:24:09 +00:00
|
|
|
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) {
|
2002-01-10 09:09:19 +00:00
|
|
|
php_error(E_WARNING, "%s(): cannot stat %d: %s",
|
|
|
|
get_active_function_name(TSRMLS_C), f->fd, strerror(errno));
|
2001-11-06 12:24:09 +00:00
|
|
|
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;
|
2002-01-10 09:09:19 +00:00
|
|
|
zval *arg = NULL;
|
2001-11-06 12:24:09 +00:00
|
|
|
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};
|
2002-01-10 09:09:19 +00:00
|
|
|
HashTable *fh;
|
|
|
|
|
|
|
|
if (!arg) {
|
|
|
|
php_error(E_WARNING, "%s() expects argument 3 to be array or int, none given",
|
|
|
|
get_active_function_name(TSRMLS_C));
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
if (Z_TYPE_P(arg) == IS_ARRAY) {
|
|
|
|
fh = HASH_OF(arg);
|
2001-11-06 12:24:09 +00:00
|
|
|
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);
|
|
|
|
}
|
2002-01-10 09:09:19 +00:00
|
|
|
} else if (Z_TYPE_P(arg) == IS_LONG) {
|
2001-11-06 12:24:09 +00:00
|
|
|
lk.l_start = 0;
|
|
|
|
lk.l_len = 0;
|
|
|
|
lk.l_whence = SEEK_SET;
|
|
|
|
lk.l_type = Z_LVAL_P(arg);
|
2002-01-10 09:09:19 +00:00
|
|
|
} else {
|
|
|
|
php_error(E_WARNING, "%s() expects argument 3 to be array or int, %s given",
|
|
|
|
get_active_function_name(TSRMLS_C), zend_zval_type_name(arg));
|
|
|
|
RETURN_FALSE;
|
2001-11-06 12:24:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2002-01-10 09:09:19 +00:00
|
|
|
if (!arg || Z_TYPE_P(arg) != IS_LONG) {
|
|
|
|
php_error(E_WARNING, "%s() expects argument 3 to be int",
|
|
|
|
get_active_function_name(TSRMLS_C));
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2001-11-06 12:24:09 +00:00
|
|
|
new_php_fd(&new_f, fcntl(f->fd, cmd, Z_LVAL_P(arg)));
|
|
|
|
ZEND_REGISTER_RESOURCE(return_value, new_f, le_fd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
2002-01-10 09:09:19 +00:00
|
|
|
if (!arg || Z_TYPE_P(arg) != IS_LONG) {
|
|
|
|
php_error(E_WARNING, "%s() expects argument 3 to be int",
|
|
|
|
get_active_function_name(TSRMLS_C));
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2001-11-06 12:24:09 +00:00
|
|
|
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
|
|
|
|
*/
|