1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
| // 资源名称
#define PHP_DONIE_RES_NAME_FILE "Donie's File Descriptor"
// 资源类型
static int le_donie_file_descriptor;
static int le_donie_file_descriptor_persist;
// 资源析构函数
static void php_donie_file_descriptor_dtor(zend_rsrc_list_entry *rsrc TSRMLS_CC)
{
FILE *fp = (FILE*)rsrc->ptr;
fclose(fp);
}
// 在扩展的MINIT方法里创建资源类型
PHP_MINIT_FUNCTION(donie)
{
/* create a new resource type */
le_donie_file_descriptor = zend_register_list_destructors_ex(
php_donie_file_descriptor_dtor, NULL, PHP_DONIE_RES_NAME_FILE, module_number
);
/* create a persistent resource type */
le_donie_file_descriptor_persist = zend_register_list_destructors_ex(
NULL, php_donie_file_descriptor_dtor, PHP_DONIE_RES_NAME_FILE, module_number
);
return SUCCESS;
}
// 文件打开操作
PHP_FUNCTION(donie_fopen)
{
FILE *fp;
char *filename, *mode;
int filename_len, mode_len;
zend_bool persist = 0;
char *hash_key;
int hash_key_len;
list_entry *persist_file;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &filename, &filename_len, &mode, &mode_len, &persist) == FAILURE)
{
RETURN_NULL();
}
if (!filename_len || !mode_len)
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid file name or mode.");
RETURN_FALSE;
}
/* reuse persistent resource if exists */
hash_key_len = spprintf(&hash_key, 0, "php_donie_file_descriptor:%s-%s", filename, mode);
if (zend_hash_find(&EG(persistent_list), hash_key, hash_key_len+1, (void **)&persist_file) == SUCCESS)
{
ZEND_REGISTER_RESOURCE(return_value, persist_file->ptr, le_donie_file_descriptor_persist);
efree(hash_key);
return;
}
fp = fopen(filename, mode);
if (!fp)
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed opening %s with mode %s.", filename, mode);
RETURN_FALSE;
}
/* this is the key point for registering resources */
if (persist)
{
ZEND_REGISTER_RESOURCE(return_value, fp, le_donie_file_descriptor_persist);
list_entry le;
le.type = le_donie_file_descriptor_persist;
le.ptr = fp;
zend_hash_update(&EG(persistent_list), hash_key, hash_key_len+1, (void*)&le, sizeof(list_entry), NULL);
}
else
{
ZEND_REGISTER_RESOURCE(return_value, fp, le_donie_file_descriptor);
}
efree(hash_key);
}
// 文件写操作
PHP_FUNCTION(donie_fwrite)
{
FILE *fp;
zval *file_resource;
char *data;
int data_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &file_resource, &data, &data_len) == FAILURE)
{
RETURN_NULL();
}
ZEND_FETCH_RESOURCE2(fp, FILE*, &file_resource, -1, PHP_DONIE_RES_NAME_FILE, le_donie_file_descriptor, le_donie_file_descriptor_persist);
RETURN_LONG(fwrite(data, 1, data_len, fp));
}
// 文件关闭操作
PHP_FUNCTION(donie_fclose)
{
FILE *fp;
zval *file_resource;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &file_resource) == FAILURE)
{
RETURN_NULL();
}
ZEND_FETCH_RESOURCE2(fp, FILE*, &file_resource, -1, PHP_DONIE_RES_NAME_FILE, le_donie_file_descriptor, le_donie_file_descriptor_persist);
zend_hash_index_del(&EG(regular_list), Z_RESVAL_P(file_resource));
RETURN_TRUE;
}
|