2003-02-18 09:37:54 +00:00
|
|
|
/*
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| Zend Engine |
|
|
|
|
+----------------------------------------------------------------------+
|
2019-01-30 09:23:29 +00:00
|
|
|
| Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
|
2003-02-18 09:37:54 +00:00
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| This source file is subject to version 2.00 of the Zend license, |
|
2008-03-16 21:06:55 +00:00
|
|
|
| that is bundled with this package in the file LICENSE, and is |
|
2003-06-10 20:04:29 +00:00
|
|
|
| available through the world-wide-web at the following url: |
|
2003-02-18 09:37:54 +00:00
|
|
|
| http://www.zend.com/license/2_00.txt. |
|
|
|
|
| If you did not receive a copy of the Zend license and are unable to |
|
|
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
|
|
| license@zend.com so we can mail you a copy immediately. |
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| Authors: Wez Furlong <wez@thebrainroom.com> |
|
2008-03-16 21:06:55 +00:00
|
|
|
| Scott MacVicar <scottmac@php.net> |
|
|
|
|
| Nuno Lopes <nlopess@php.net> |
|
|
|
|
| Marcus Boerger <helly@php.net> |
|
2003-02-18 09:37:54 +00:00
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "zend.h"
|
|
|
|
#include "zend_compile.h"
|
2014-08-16 09:16:11 +00:00
|
|
|
#include "zend_stream.h"
|
2003-02-18 09:37:54 +00:00
|
|
|
|
|
|
|
ZEND_DLIMPORT int isatty(int fd);
|
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
static size_t zend_stream_stdio_reader(void *handle, char *buf, size_t len) /* {{{ */
|
2003-02-18 09:37:54 +00:00
|
|
|
{
|
|
|
|
return fread(buf, 1, len, (FILE*)handle);
|
2008-03-16 21:06:55 +00:00
|
|
|
} /* }}} */
|
2003-02-18 09:37:54 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
static void zend_stream_stdio_closer(void *handle) /* {{{ */
|
2003-02-18 09:37:54 +00:00
|
|
|
{
|
2008-03-16 21:06:55 +00:00
|
|
|
if (handle && (FILE*)handle != stdin) {
|
2003-02-18 09:37:54 +00:00
|
|
|
fclose((FILE*)handle);
|
2008-03-16 21:06:55 +00:00
|
|
|
}
|
|
|
|
} /* }}} */
|
2003-02-18 09:37:54 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
static size_t zend_stream_stdio_fsizer(void *handle) /* {{{ */
|
2005-06-04 16:16:19 +00:00
|
|
|
{
|
2014-08-16 09:16:11 +00:00
|
|
|
zend_stat_t buf;
|
|
|
|
if (handle && zend_fstat(fileno((FILE*)handle), &buf) == 0) {
|
2008-09-10 10:28:39 +00:00
|
|
|
#ifdef S_ISREG
|
|
|
|
if (!S_ISREG(buf.st_mode)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
2008-03-16 21:06:55 +00:00
|
|
|
return buf.st_size;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
} /* }}} */
|
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
static void zend_stream_unmap(zend_stream *stream) { /* {{{ */
|
2008-03-16 21:06:55 +00:00
|
|
|
if (stream->mmap.buf) {
|
|
|
|
efree(stream->mmap.buf);
|
|
|
|
}
|
|
|
|
stream->mmap.len = 0;
|
|
|
|
stream->mmap.buf = 0;
|
|
|
|
stream->handle = stream->mmap.old_handle;
|
|
|
|
} /* }}} */
|
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
static void zend_stream_mmap_closer(zend_stream *stream) /* {{{ */
|
2008-03-16 21:06:55 +00:00
|
|
|
{
|
2014-12-13 22:06:14 +00:00
|
|
|
zend_stream_unmap(stream);
|
2008-03-16 21:06:55 +00:00
|
|
|
if (stream->mmap.old_closer && stream->handle) {
|
2014-12-13 22:06:14 +00:00
|
|
|
stream->mmap.old_closer(stream->handle);
|
2008-03-16 21:06:55 +00:00
|
|
|
}
|
|
|
|
} /* }}} */
|
|
|
|
|
|
|
|
static inline int zend_stream_is_mmap(zend_file_handle *file_handle) { /* {{{ */
|
|
|
|
return file_handle->type == ZEND_HANDLE_MAPPED;
|
|
|
|
} /* }}} */
|
2005-06-04 16:16:19 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
static size_t zend_stream_fsize(zend_file_handle *file_handle) /* {{{ */
|
2008-03-16 21:06:55 +00:00
|
|
|
{
|
2014-08-29 10:53:37 +00:00
|
|
|
zend_stat_t buf;
|
2008-03-16 21:06:55 +00:00
|
|
|
|
|
|
|
if (zend_stream_is_mmap(file_handle)) {
|
|
|
|
return file_handle->handle.stream.mmap.len;
|
|
|
|
}
|
|
|
|
if (file_handle->type == ZEND_HANDLE_STREAM || file_handle->type == ZEND_HANDLE_MAPPED) {
|
2014-12-13 22:06:14 +00:00
|
|
|
return file_handle->handle.stream.fsizer(file_handle->handle.stream.handle);
|
2008-03-16 21:06:55 +00:00
|
|
|
}
|
2014-08-29 10:53:37 +00:00
|
|
|
if (file_handle->handle.fp && zend_fstat(fileno(file_handle->handle.fp), &buf) == 0) {
|
2008-09-10 10:28:39 +00:00
|
|
|
#ifdef S_ISREG
|
|
|
|
if (!S_ISREG(buf.st_mode)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
2008-03-16 21:06:55 +00:00
|
|
|
return buf.st_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
} /* }}} */
|
2005-06-04 16:16:19 +00:00
|
|
|
|
2019-07-16 14:21:45 +00:00
|
|
|
ZEND_API void zend_stream_init_fp(zend_file_handle *handle, FILE *fp, const char *filename) {
|
|
|
|
memset(handle, 0, sizeof(zend_file_handle));
|
|
|
|
handle->type = ZEND_HANDLE_FP;
|
|
|
|
handle->handle.fp = fp;
|
|
|
|
handle->filename = filename;
|
|
|
|
}
|
|
|
|
|
2019-07-16 14:40:54 +00:00
|
|
|
ZEND_API void zend_stream_init_filename(zend_file_handle *handle, const char *filename) {
|
|
|
|
memset(handle, 0, sizeof(zend_file_handle));
|
|
|
|
handle->type = ZEND_HANDLE_FILENAME;
|
|
|
|
handle->filename = filename;
|
|
|
|
}
|
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
ZEND_API int zend_stream_open(const char *filename, zend_file_handle *handle) /* {{{ */
|
2003-02-18 09:37:54 +00:00
|
|
|
{
|
2003-02-20 21:48:46 +00:00
|
|
|
if (zend_stream_open_function) {
|
2014-12-13 22:06:14 +00:00
|
|
|
return zend_stream_open_function(filename, handle);
|
2003-02-18 09:37:54 +00:00
|
|
|
}
|
|
|
|
handle->type = ZEND_HANDLE_FP;
|
|
|
|
handle->opened_path = NULL;
|
2014-12-13 22:06:14 +00:00
|
|
|
handle->handle.fp = zend_fopen(filename, &handle->opened_path);
|
2010-10-14 21:33:10 +00:00
|
|
|
handle->filename = filename;
|
2008-03-16 21:06:55 +00:00
|
|
|
memset(&handle->handle.stream.mmap, 0, sizeof(zend_mmap));
|
2015-01-03 09:22:58 +00:00
|
|
|
|
2003-02-18 09:37:54 +00:00
|
|
|
return (handle->handle.fp) ? SUCCESS : FAILURE;
|
2008-03-16 21:06:55 +00:00
|
|
|
} /* }}} */
|
2003-02-18 09:37:54 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
static int zend_stream_getc(zend_file_handle *file_handle) /* {{{ */
|
2003-02-18 09:37:54 +00:00
|
|
|
{
|
2008-03-16 21:06:55 +00:00
|
|
|
char buf;
|
2003-02-18 09:37:54 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
if (file_handle->handle.stream.reader(file_handle->handle.stream.handle, &buf, sizeof(buf))) {
|
2008-03-16 21:06:55 +00:00
|
|
|
return (int)buf;
|
2003-02-18 09:37:54 +00:00
|
|
|
}
|
2008-03-16 21:06:55 +00:00
|
|
|
return EOF;
|
|
|
|
} /* }}} */
|
2003-02-18 09:37:54 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
static size_t zend_stream_read(zend_file_handle *file_handle, char *buf, size_t len) /* {{{ */
|
2003-02-18 09:37:54 +00:00
|
|
|
{
|
2008-03-16 21:06:55 +00:00
|
|
|
if (!zend_stream_is_mmap(file_handle) && file_handle->handle.stream.isatty) {
|
2004-09-27 09:03:40 +00:00
|
|
|
int c = '*';
|
2008-03-16 21:06:55 +00:00
|
|
|
size_t n;
|
2003-02-18 09:37:54 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
for (n = 0; n < len && (c = zend_stream_getc(file_handle)) != EOF && c != '\n'; ++n) {
|
2008-03-16 21:06:55 +00:00
|
|
|
buf[n] = (char)c;
|
|
|
|
}
|
|
|
|
if (c == '\n') {
|
2015-01-03 09:22:58 +00:00
|
|
|
buf[n++] = (char)c;
|
2008-03-16 21:06:55 +00:00
|
|
|
}
|
2003-02-18 09:37:54 +00:00
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
2014-12-13 22:06:14 +00:00
|
|
|
return file_handle->handle.stream.reader(file_handle->handle.stream.handle, buf, len);
|
2008-03-16 21:06:55 +00:00
|
|
|
} /* }}} */
|
2003-02-18 09:37:54 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
ZEND_API int zend_stream_fixup(zend_file_handle *file_handle, char **buf, size_t *len) /* {{{ */
|
2003-02-18 09:37:54 +00:00
|
|
|
{
|
2008-03-16 21:06:55 +00:00
|
|
|
size_t size;
|
2008-03-21 18:15:43 +00:00
|
|
|
zend_stream_type old_type;
|
2003-02-18 09:37:54 +00:00
|
|
|
|
2008-03-16 21:06:55 +00:00
|
|
|
if (file_handle->type == ZEND_HANDLE_FILENAME) {
|
2014-12-13 22:06:14 +00:00
|
|
|
if (zend_stream_open(file_handle->filename, file_handle) == FAILURE) {
|
2008-03-16 21:06:55 +00:00
|
|
|
return FAILURE;
|
|
|
|
}
|
2003-02-18 09:37:54 +00:00
|
|
|
}
|
|
|
|
|
2015-01-03 09:22:58 +00:00
|
|
|
switch (file_handle->type) {
|
2008-03-16 21:06:55 +00:00
|
|
|
case ZEND_HANDLE_FP:
|
|
|
|
if (!file_handle->handle.fp) {
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
memset(&file_handle->handle.stream.mmap, 0, sizeof(zend_mmap));
|
2018-08-19 04:32:00 +00:00
|
|
|
file_handle->handle.stream.isatty = isatty(fileno((FILE *)file_handle->handle.stream.handle));
|
2008-03-16 21:06:55 +00:00
|
|
|
file_handle->handle.stream.reader = (zend_stream_reader_t)zend_stream_stdio_reader;
|
|
|
|
file_handle->handle.stream.closer = (zend_stream_closer_t)zend_stream_stdio_closer;
|
|
|
|
file_handle->handle.stream.fsizer = (zend_stream_fsizer_t)zend_stream_stdio_fsizer;
|
|
|
|
memset(&file_handle->handle.stream.mmap, 0, sizeof(file_handle->handle.stream.mmap));
|
2015-01-03 09:22:58 +00:00
|
|
|
/* no break; */
|
2008-03-16 21:06:55 +00:00
|
|
|
case ZEND_HANDLE_STREAM:
|
|
|
|
/* nothing to do */
|
|
|
|
break;
|
2015-01-03 09:22:58 +00:00
|
|
|
|
2008-03-16 21:06:55 +00:00
|
|
|
case ZEND_HANDLE_MAPPED:
|
|
|
|
*buf = file_handle->handle.stream.mmap.buf;
|
|
|
|
*len = file_handle->handle.stream.mmap.len;
|
|
|
|
return SUCCESS;
|
2015-01-03 09:22:58 +00:00
|
|
|
|
2008-03-16 21:06:55 +00:00
|
|
|
default:
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
size = zend_stream_fsize(file_handle);
|
2008-03-16 21:06:55 +00:00
|
|
|
if (size == (size_t)-1) {
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
2008-03-21 18:15:43 +00:00
|
|
|
old_type = file_handle->type;
|
2008-03-16 21:06:55 +00:00
|
|
|
file_handle->type = ZEND_HANDLE_STREAM; /* we might still be _FP but we need fsize() work */
|
|
|
|
|
2008-03-21 18:15:43 +00:00
|
|
|
if (old_type == ZEND_HANDLE_FP && !file_handle->handle.stream.isatty && size) {
|
2008-03-16 21:06:55 +00:00
|
|
|
file_handle->handle.stream.mmap.buf = *buf = safe_emalloc(1, size, ZEND_MMAP_AHEAD);
|
2014-12-13 22:06:14 +00:00
|
|
|
file_handle->handle.stream.mmap.len = zend_stream_read(file_handle, *buf, size);
|
2008-03-16 21:06:55 +00:00
|
|
|
} else {
|
|
|
|
size_t read, remain = 4*1024;
|
|
|
|
*buf = emalloc(remain);
|
|
|
|
size = 0;
|
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
while ((read = zend_stream_read(file_handle, *buf + size, remain)) > 0) {
|
2008-03-16 21:06:55 +00:00
|
|
|
size += read;
|
|
|
|
remain -= read;
|
|
|
|
|
|
|
|
if (remain == 0) {
|
|
|
|
*buf = safe_erealloc(*buf, size, 2, 0);
|
|
|
|
remain = size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
file_handle->handle.stream.mmap.len = size;
|
|
|
|
if (size && remain < ZEND_MMAP_AHEAD) {
|
|
|
|
*buf = safe_erealloc(*buf, size, 1, ZEND_MMAP_AHEAD);
|
|
|
|
}
|
2008-04-29 08:08:21 +00:00
|
|
|
file_handle->handle.stream.mmap.buf = *buf;
|
2008-03-16 21:06:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (file_handle->handle.stream.mmap.len == 0) {
|
|
|
|
*buf = erealloc(*buf, ZEND_MMAP_AHEAD);
|
|
|
|
file_handle->handle.stream.mmap.buf = *buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ZEND_MMAP_AHEAD) {
|
|
|
|
memset(file_handle->handle.stream.mmap.buf + file_handle->handle.stream.mmap.len, 0, ZEND_MMAP_AHEAD);
|
|
|
|
}
|
|
|
|
file_handle->type = ZEND_HANDLE_MAPPED;
|
|
|
|
file_handle->handle.stream.mmap.old_handle = file_handle->handle.stream.handle;
|
|
|
|
file_handle->handle.stream.mmap.old_closer = file_handle->handle.stream.closer;
|
|
|
|
file_handle->handle.stream.handle = &file_handle->handle.stream;
|
|
|
|
file_handle->handle.stream.closer = (zend_stream_closer_t)zend_stream_mmap_closer;
|
|
|
|
|
|
|
|
*buf = file_handle->handle.stream.mmap.buf;
|
|
|
|
*len = file_handle->handle.stream.mmap.len;
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
} /* }}} */
|
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
ZEND_API void zend_file_handle_dtor(zend_file_handle *fh) /* {{{ */
|
2003-02-18 09:37:54 +00:00
|
|
|
{
|
2008-03-16 21:06:55 +00:00
|
|
|
switch (fh->type) {
|
|
|
|
case ZEND_HANDLE_FP:
|
|
|
|
fclose(fh->handle.fp);
|
|
|
|
break;
|
|
|
|
case ZEND_HANDLE_STREAM:
|
|
|
|
case ZEND_HANDLE_MAPPED:
|
|
|
|
if (fh->handle.stream.closer && fh->handle.stream.handle) {
|
2014-12-13 22:06:14 +00:00
|
|
|
fh->handle.stream.closer(fh->handle.stream.handle);
|
2008-03-16 21:06:55 +00:00
|
|
|
}
|
|
|
|
fh->handle.stream.handle = NULL;
|
|
|
|
break;
|
|
|
|
case ZEND_HANDLE_FILENAME:
|
|
|
|
/* We're only supposed to get here when destructing the used_files hash,
|
|
|
|
* which doesn't really contain open files, but references to their names/paths
|
|
|
|
*/
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (fh->opened_path) {
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(fh->opened_path, 0);
|
2008-03-16 21:06:55 +00:00
|
|
|
fh->opened_path = NULL;
|
|
|
|
}
|
2003-02-18 09:37:54 +00:00
|
|
|
}
|
2008-03-16 21:06:55 +00:00
|
|
|
/* }}} */
|
2003-02-18 09:37:54 +00:00
|
|
|
|
2008-03-16 21:06:55 +00:00
|
|
|
ZEND_API int zend_compare_file_handles(zend_file_handle *fh1, zend_file_handle *fh2) /* {{{ */
|
2005-06-04 16:16:19 +00:00
|
|
|
{
|
2008-03-16 21:06:55 +00:00
|
|
|
if (fh1->type != fh2->type) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
switch (fh1->type) {
|
|
|
|
case ZEND_HANDLE_FP:
|
|
|
|
return fh1->handle.fp == fh2->handle.fp;
|
|
|
|
case ZEND_HANDLE_STREAM:
|
|
|
|
return fh1->handle.stream.handle == fh2->handle.stream.handle;
|
|
|
|
case ZEND_HANDLE_MAPPED:
|
|
|
|
return (fh1->handle.stream.handle == &fh1->handle.stream &&
|
|
|
|
fh2->handle.stream.handle == &fh2->handle.stream &&
|
|
|
|
fh1->handle.stream.mmap.old_handle == fh2->handle.stream.mmap.old_handle)
|
|
|
|
|| fh1->handle.stream.handle == fh2->handle.stream.handle;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
} /* }}} */
|