php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
zend_stream.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 2.00 of the Zend license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.zend.com/license/2_00.txt. |
11 | If you did not receive a copy of the Zend license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@zend.com so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Wez Furlong <wez@thebrainroom.com> |
16 | Scott MacVicar <scottmac@php.net> |
17 | Nuno Lopes <nlopess@php.net> |
18 | Marcus Boerger <helly@php.net> |
19 +----------------------------------------------------------------------+
20*/
21
22#include "zend.h"
23#include "zend_compile.h"
24#include "zend_stream.h"
25
27
28static ssize_t zend_stream_stdio_reader(void *handle, char *buf, size_t len) /* {{{ */
29{
30 return fread(buf, 1, len, (FILE*)handle);
31} /* }}} */
32
33static void zend_stream_stdio_closer(void *handle) /* {{{ */
34{
35 if (handle && (FILE*)handle != stdin) {
36 fclose((FILE*)handle);
37 }
38} /* }}} */
39
40static size_t zend_stream_stdio_fsizer(void *handle) /* {{{ */
41{
42 zend_stat_t buf = {0};
43 if (handle && zend_fstat(fileno((FILE*)handle), &buf) == 0) {
44#ifdef S_ISREG
45 if (!S_ISREG(buf.st_mode)) {
46 return 0;
47 }
48#endif
49 return buf.st_size;
50 }
51 return -1;
52} /* }}} */
53
54static size_t zend_stream_fsize(zend_file_handle *file_handle) /* {{{ */
55{
56 ZEND_ASSERT(file_handle->type == ZEND_HANDLE_STREAM);
57 if (file_handle->handle.stream.isatty) {
58 return 0;
59 }
60 return file_handle->handle.stream.fsizer(file_handle->handle.stream.handle);
61} /* }}} */
62
63ZEND_API void zend_stream_init_fp(zend_file_handle *handle, FILE *fp, const char *filename) {
64 memset(handle, 0, sizeof(zend_file_handle));
65 handle->type = ZEND_HANDLE_FP;
66 handle->handle.fp = fp;
67 handle->filename = filename ? zend_string_init(filename, strlen(filename), 0) : NULL;
68}
69
71 memset(handle, 0, sizeof(zend_file_handle));
73 handle->filename = filename ? zend_string_init(filename, strlen(filename), 0) : NULL;
74}
75
77 memset(handle, 0, sizeof(zend_file_handle));
79 handle->filename = zend_string_copy(filename);
80}
81
83{
84 zend_string *opened_path;
85
89 }
90
91 handle->handle.fp = zend_fopen(handle->filename, &opened_path);
92 if (!handle->handle.fp) {
93 return FAILURE;
94 }
95 handle->type = ZEND_HANDLE_FP;
96 return SUCCESS;
97} /* }}} */
98
99static int zend_stream_getc(zend_file_handle *file_handle) /* {{{ */
100{
101 char buf;
102
103 if (file_handle->handle.stream.reader(file_handle->handle.stream.handle, &buf, sizeof(buf))) {
104 return (int)buf;
105 }
106 return EOF;
107} /* }}} */
108
109static ssize_t zend_stream_read(zend_file_handle *file_handle, char *buf, size_t len) /* {{{ */
110{
111 if (file_handle->handle.stream.isatty) {
112 int c = '*';
113 size_t n;
114
115 for (n = 0; n < len && (c = zend_stream_getc(file_handle)) != EOF && c != '\n'; ++n) {
116 buf[n] = (char)c;
117 }
118 if (c == '\n') {
119 buf[n++] = (char)c;
120 }
121
122 return n;
123 }
124 return file_handle->handle.stream.reader(file_handle->handle.stream.handle, buf, len);
125} /* }}} */
126
127ZEND_API zend_result zend_stream_fixup(zend_file_handle *file_handle, char **buf, size_t *len) /* {{{ */
128{
129 size_t file_size;
130
131 if (file_handle->buf) {
132 *buf = file_handle->buf;
133 *len = file_handle->len;
134 return SUCCESS;
135 }
136
137 if (file_handle->type == ZEND_HANDLE_FILENAME) {
138 if (zend_stream_open(file_handle) == FAILURE) {
139 return FAILURE;
140 }
141 }
142
143 if (file_handle->type == ZEND_HANDLE_FP) {
144 if (!file_handle->handle.fp) {
145 return FAILURE;
146 }
147
148 file_handle->type = ZEND_HANDLE_STREAM;
149 file_handle->handle.stream.handle = file_handle->handle.fp;
150 file_handle->handle.stream.isatty = isatty(fileno((FILE *)file_handle->handle.stream.handle));
151 file_handle->handle.stream.reader = (zend_stream_reader_t)zend_stream_stdio_reader;
152 file_handle->handle.stream.closer = (zend_stream_closer_t)zend_stream_stdio_closer;
153 file_handle->handle.stream.fsizer = (zend_stream_fsizer_t)zend_stream_stdio_fsizer;
154 }
155
156 file_size = zend_stream_fsize(file_handle);
157 if (file_size == (size_t)-1) {
158 return FAILURE;
159 }
160
161 if (file_size) {
162 ssize_t read;
163 size_t size = 0;
164 *buf = safe_emalloc(1, file_size, ZEND_MMAP_AHEAD);
165 while ((read = zend_stream_read(file_handle, *buf + size, file_size - size)) > 0) {
166 size += read;
167 }
168 if (read < 0) {
169 efree(*buf);
170 return FAILURE;
171 }
172 file_handle->buf = *buf;
173 file_handle->len = size;
174 } else {
175 size_t size = 0, remain = 4*1024;
176 ssize_t read;
177 *buf = emalloc(remain);
178
179 while ((read = zend_stream_read(file_handle, *buf + size, remain)) > 0) {
180 size += read;
181 remain -= read;
182
183 if (remain == 0) {
184 *buf = safe_erealloc(*buf, size, 2, 0);
185 remain = size;
186 }
187 }
188 if (read < 0) {
189 efree(*buf);
190 return FAILURE;
191 }
192
193 file_handle->len = size;
194 if (size && remain < ZEND_MMAP_AHEAD) {
196 }
197 file_handle->buf = *buf;
198 }
199
200 if (file_handle->len == 0) {
202 file_handle->buf = *buf;
203 }
204
205 memset(file_handle->buf + file_handle->len, 0, ZEND_MMAP_AHEAD);
206
207 *buf = file_handle->buf;
208 *len = file_handle->len;
209
210 return SUCCESS;
211} /* }}} */
212
213static void zend_file_handle_dtor(zend_file_handle *fh) /* {{{ */
214{
215 switch (fh->type) {
216 case ZEND_HANDLE_FP:
217 if (fh->handle.fp) {
218 fclose(fh->handle.fp);
219 fh->handle.fp = NULL;
220 }
221 break;
223 if (fh->handle.stream.closer && fh->handle.stream.handle) {
225 }
226 fh->handle.stream.handle = NULL;
227 break;
229 /* We're only supposed to get here when destructing the used_files hash,
230 * which doesn't really contain open files, but references to their names/paths
231 */
232 break;
233 }
234 if (fh->opened_path) {
236 fh->opened_path = NULL;
237 }
238 if (fh->buf) {
239 efree(fh->buf);
240 fh->buf = NULL;
241 }
242 if (fh->filename) {
243 zend_string_release(fh->filename);
244 fh->filename = NULL;
245 }
246}
247/* }}} */
248
249/* return int to be compatible with Zend linked list API */
250static int zend_compare_file_handles(zend_file_handle *fh1, zend_file_handle *fh2) /* {{{ */
251{
252 if (fh1->type != fh2->type) {
253 return 0;
254 }
255 switch (fh1->type) {
257 return zend_string_equals(fh1->filename, fh2->filename);
258 case ZEND_HANDLE_FP:
259 return fh1->handle.fp == fh2->handle.fp;
261 return fh1->handle.stream.handle == fh2->handle.stream.handle;
262 default:
263 return 0;
264 }
265 return 0;
266} /* }}} */
267
269{
270 if (file_handle->in_list) {
271 zend_llist_del_element(&CG(open_files), file_handle, (int (*)(void *, void *)) zend_compare_file_handles);
272 /* zend_file_handle_dtor() operates on the copy, so we have to NULLify the original here */
273 file_handle->opened_path = NULL;
274 file_handle->filename = NULL;
275 } else {
276 zend_file_handle_dtor(file_handle);
277 }
278} /* }}} */
279
280void zend_stream_init(void) /* {{{ */
281{
282 zend_llist_init(&CG(open_files), sizeof(zend_file_handle), (void (*)(void *)) zend_file_handle_dtor, 0);
283} /* }}} */
284
285void zend_stream_shutdown(void) /* {{{ */
286{
287 zend_llist_destroy(&CG(open_files));
288} /* }}} */
size_t len
Definition apprentice.c:174
fclose($stream)
fread($stream, int $length)
DL_HANDLE handle
Definition ffi.c:3028
zend_long n
Definition ffi.c:4979
new_type size
Definition ffi.c:4365
memset(ptr, 0, type->size)
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
int fd
Definition phpdbg.h:282
zend_string * filename
Definition zend_stream.h:58
zend_string * opened_path
Definition zend_stream.h:59
zend_stream stream
Definition zend_stream.h:56
union _zend_file_handle::@045057025306333206016200356074063117305134322373 handle
zend_stream_closer_t closer
Definition zend_stream.h:50
void * handle
Definition zend_stream.h:46
zend_stream_fsizer_t fsizer
Definition zend_stream.h:49
zend_stream_reader_t reader
Definition zend_stream.h:48
ZEND_API FILE *(* zend_fopen)(zend_string *filename, zend_string **opened_path)
Definition zend.c:86
ZEND_API zend_result(* zend_stream_open_function)(zend_file_handle *handle)
Definition zend.c:87
#define safe_erealloc(ptr, nmemb, size, offset)
Definition zend_alloc.h:161
#define efree(ptr)
Definition zend_alloc.h:155
#define erealloc(ptr, size)
Definition zend_alloc.h:159
#define safe_emalloc(nmemb, size, offset)
Definition zend_alloc.h:154
#define emalloc(size)
Definition zend_alloc.h:151
strlen(string $string)
zend_string_release_ex(func->internal_function.function_name, 0)
#define ZEND_DLIMPORT
#define ZEND_API
#define CG(v)
struct _zend_file_handle zend_file_handle
ZEND_API void zend_llist_destroy(zend_llist *l)
Definition zend_llist.c:102
ZEND_API void zend_llist_del_element(zend_llist *l, void *element, int(*compare)(void *element1, void *element2))
Definition zend_llist.c:88
ZEND_API void zend_llist_init(zend_llist *l, size_t size, llist_dtor_func_t dtor, unsigned char persistent)
Definition zend_llist.c:24
struct _zend_string zend_string
#define ZEND_ASSERT(c)
ZEND_API zend_result zend_stream_fixup(zend_file_handle *file_handle, char **buf, size_t *len)
ZEND_DLIMPORT int isatty(int fd)
ZEND_API void zend_stream_init_filename_ex(zend_file_handle *handle, zend_string *filename)
Definition zend_stream.c:76
ZEND_API zend_result zend_stream_open(zend_file_handle *handle)
Definition zend_stream.c:82
void zend_stream_shutdown(void)
ZEND_API void zend_stream_init_fp(zend_file_handle *handle, FILE *fp, const char *filename)
Definition zend_stream.c:63
ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle)
ZEND_API void zend_stream_init_filename(zend_file_handle *handle, const char *filename)
Definition zend_stream.c:70
void zend_stream_init(void)
void(* zend_stream_closer_t)(void *handle)
Definition zend_stream.h:35
size_t(* zend_stream_fsizer_t)(void *handle)
Definition zend_stream.h:33
#define zend_fstat
Definition zend_stream.h:98
ssize_t(* zend_stream_reader_t)(void *handle, char *buf, size_t len)
Definition zend_stream.h:34
@ ZEND_HANDLE_STREAM
Definition zend_stream.h:42
@ ZEND_HANDLE_FILENAME
Definition zend_stream.h:40
@ ZEND_HANDLE_FP
Definition zend_stream.h:41
struct stat zend_stat_t
Definition zend_stream.h:94
#define ZEND_MMAP_AHEAD
Definition zend_stream.h:37
@ FAILURE
Definition zend_types.h:61
ZEND_RESULT_CODE zend_result
Definition zend_types.h:64
#define S_ISREG(mode)