123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- /*
- +----------------------------------------------------------------------+
- | Zend Engine |
- +----------------------------------------------------------------------+
- | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) |
- +----------------------------------------------------------------------+
- | This source file is subject to version 2.00 of the Zend license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | 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> |
- | Scott MacVicar <scottmac@php.net> |
- | Nuno Lopes <nlopess@php.net> |
- | Marcus Boerger <helly@php.net> |
- +----------------------------------------------------------------------+
- */
- #include "zend.h"
- #include "zend_compile.h"
- #include "zend_stream.h"
- #if HAVE_MMAP
- # if HAVE_UNISTD_H
- # include <unistd.h>
- # if defined(_SC_PAGESIZE)
- # define REAL_PAGE_SIZE sysconf(_SC_PAGESIZE);
- # elif defined(_SC_PAGE_SIZE)
- # define REAL_PAGE_SIZE sysconf(_SC_PAGE_SIZE);
- # endif
- # endif
- # if HAVE_SYS_MMAN_H
- # include <sys/mman.h>
- # endif
- # ifndef REAL_PAGE_SIZE
- # ifdef PAGE_SIZE
- # define REAL_PAGE_SIZE PAGE_SIZE
- # else
- # define REAL_PAGE_SIZE 4096
- # endif
- # endif
- #endif
- ZEND_DLIMPORT int isatty(int fd);
- static size_t zend_stream_stdio_reader(void *handle, char *buf, size_t len) /* {{{ */
- {
- return fread(buf, 1, len, (FILE*)handle);
- } /* }}} */
- static void zend_stream_stdio_closer(void *handle) /* {{{ */
- {
- if (handle && (FILE*)handle != stdin) {
- fclose((FILE*)handle);
- }
- } /* }}} */
- static size_t zend_stream_stdio_fsizer(void *handle) /* {{{ */
- {
- zend_stat_t buf;
- if (handle && zend_fstat(fileno((FILE*)handle), &buf) == 0) {
- #ifdef S_ISREG
- if (!S_ISREG(buf.st_mode)) {
- return 0;
- }
- #endif
- return buf.st_size;
- }
- return 0;
- } /* }}} */
- static void zend_stream_unmap(zend_stream *stream) { /* {{{ */
- #if HAVE_MMAP
- if (stream->mmap.map) {
- munmap(stream->mmap.map, stream->mmap.len + ZEND_MMAP_AHEAD);
- } else
- #endif
- if (stream->mmap.buf) {
- efree(stream->mmap.buf);
- }
- stream->mmap.len = 0;
- stream->mmap.pos = 0;
- stream->mmap.map = 0;
- stream->mmap.buf = 0;
- stream->handle = stream->mmap.old_handle;
- } /* }}} */
- static void zend_stream_mmap_closer(zend_stream *stream) /* {{{ */
- {
- zend_stream_unmap(stream);
- if (stream->mmap.old_closer && stream->handle) {
- stream->mmap.old_closer(stream->handle);
- }
- } /* }}} */
- static inline int zend_stream_is_mmap(zend_file_handle *file_handle) { /* {{{ */
- return file_handle->type == ZEND_HANDLE_MAPPED;
- } /* }}} */
- static size_t zend_stream_fsize(zend_file_handle *file_handle) /* {{{ */
- {
- zend_stat_t buf;
- 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) {
- return file_handle->handle.stream.fsizer(file_handle->handle.stream.handle);
- }
- if (file_handle->handle.fp && zend_fstat(fileno(file_handle->handle.fp), &buf) == 0) {
- #ifdef S_ISREG
- if (!S_ISREG(buf.st_mode)) {
- return 0;
- }
- #endif
- return buf.st_size;
- }
- return -1;
- } /* }}} */
- ZEND_API int zend_stream_open(const char *filename, zend_file_handle *handle) /* {{{ */
- {
- if (zend_stream_open_function) {
- return zend_stream_open_function(filename, handle);
- }
- handle->type = ZEND_HANDLE_FP;
- handle->opened_path = NULL;
- handle->handle.fp = zend_fopen(filename, &handle->opened_path);
- handle->filename = filename;
- handle->free_filename = 0;
- memset(&handle->handle.stream.mmap, 0, sizeof(zend_mmap));
- return (handle->handle.fp) ? SUCCESS : FAILURE;
- } /* }}} */
- static int zend_stream_getc(zend_file_handle *file_handle) /* {{{ */
- {
- char buf;
- if (file_handle->handle.stream.reader(file_handle->handle.stream.handle, &buf, sizeof(buf))) {
- return (int)buf;
- }
- return EOF;
- } /* }}} */
- static size_t zend_stream_read(zend_file_handle *file_handle, char *buf, size_t len) /* {{{ */
- {
- if (!zend_stream_is_mmap(file_handle) && file_handle->handle.stream.isatty) {
- int c = '*';
- size_t n;
- for (n = 0; n < len && (c = zend_stream_getc(file_handle)) != EOF && c != '\n'; ++n) {
- buf[n] = (char)c;
- }
- if (c == '\n') {
- buf[n++] = (char)c;
- }
- return n;
- }
- return file_handle->handle.stream.reader(file_handle->handle.stream.handle, buf, len);
- } /* }}} */
- ZEND_API int zend_stream_fixup(zend_file_handle *file_handle, char **buf, size_t *len) /* {{{ */
- {
- size_t size;
- zend_stream_type old_type;
- if (file_handle->type == ZEND_HANDLE_FILENAME) {
- if (zend_stream_open(file_handle->filename, file_handle) == FAILURE) {
- return FAILURE;
- }
- }
- switch (file_handle->type) {
- case ZEND_HANDLE_FD:
- file_handle->type = ZEND_HANDLE_FP;
- file_handle->handle.fp = fdopen(file_handle->handle.fd, "rb");
- /* no break; */
- case ZEND_HANDLE_FP:
- if (!file_handle->handle.fp) {
- return FAILURE;
- }
- memset(&file_handle->handle.stream.mmap, 0, sizeof(zend_mmap));
- file_handle->handle.stream.isatty = isatty(fileno((FILE *)file_handle->handle.stream.handle)) ? 1 : 0;
- 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));
- /* no break; */
- case ZEND_HANDLE_STREAM:
- /* nothing to do */
- break;
- case ZEND_HANDLE_MAPPED:
- file_handle->handle.stream.mmap.pos = 0;
- *buf = file_handle->handle.stream.mmap.buf;
- *len = file_handle->handle.stream.mmap.len;
- return SUCCESS;
- default:
- return FAILURE;
- }
- size = zend_stream_fsize(file_handle);
- if (size == (size_t)-1) {
- return FAILURE;
- }
- old_type = file_handle->type;
- file_handle->type = ZEND_HANDLE_STREAM; /* we might still be _FP but we need fsize() work */
- if (old_type == ZEND_HANDLE_FP && !file_handle->handle.stream.isatty && size) {
- #if HAVE_MMAP
- size_t page_size = REAL_PAGE_SIZE;
- if (file_handle->handle.fp &&
- size != 0 &&
- ((size - 1) % page_size) <= page_size - ZEND_MMAP_AHEAD) {
- /* *buf[size] is zeroed automatically by the kernel */
- *buf = mmap(0, size + ZEND_MMAP_AHEAD, PROT_READ, MAP_PRIVATE, fileno(file_handle->handle.fp), 0);
- if (*buf != MAP_FAILED) {
- zend_long offset = ftell(file_handle->handle.fp);
- file_handle->handle.stream.mmap.map = *buf;
- if (offset != -1) {
- *buf += offset;
- size -= offset;
- }
- file_handle->handle.stream.mmap.buf = *buf;
- file_handle->handle.stream.mmap.len = size;
- goto return_mapped;
- }
- }
- #endif
- file_handle->handle.stream.mmap.map = 0;
- file_handle->handle.stream.mmap.buf = *buf = safe_emalloc(1, size, ZEND_MMAP_AHEAD);
- file_handle->handle.stream.mmap.len = zend_stream_read(file_handle, *buf, size);
- } else {
- size_t read, remain = 4*1024;
- *buf = emalloc(remain);
- size = 0;
- while ((read = zend_stream_read(file_handle, *buf + size, remain)) > 0) {
- size += read;
- remain -= read;
- if (remain == 0) {
- *buf = safe_erealloc(*buf, size, 2, 0);
- remain = size;
- }
- }
- file_handle->handle.stream.mmap.map = 0;
- file_handle->handle.stream.mmap.len = size;
- if (size && remain < ZEND_MMAP_AHEAD) {
- *buf = safe_erealloc(*buf, size, 1, ZEND_MMAP_AHEAD);
- }
- file_handle->handle.stream.mmap.buf = *buf;
- }
- 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);
- }
- #if HAVE_MMAP
- return_mapped:
- #endif
- file_handle->type = ZEND_HANDLE_MAPPED;
- file_handle->handle.stream.mmap.pos = 0;
- 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;
- } /* }}} */
- ZEND_API void zend_file_handle_dtor(zend_file_handle *fh) /* {{{ */
- {
- switch (fh->type) {
- case ZEND_HANDLE_FD:
- /* nothing to do */
- break;
- 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) {
- fh->handle.stream.closer(fh->handle.stream.handle);
- }
- 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) {
- zend_string_release_ex(fh->opened_path, 0);
- fh->opened_path = NULL;
- }
- if (fh->free_filename && fh->filename) {
- efree((char*)fh->filename);
- fh->filename = NULL;
- }
- }
- /* }}} */
- ZEND_API int zend_compare_file_handles(zend_file_handle *fh1, zend_file_handle *fh2) /* {{{ */
- {
- if (fh1->type != fh2->type) {
- return 0;
- }
- switch (fh1->type) {
- case ZEND_HANDLE_FD:
- return fh1->handle.fd == fh2->handle.fd;
- 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;
- } /* }}} */
- /*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * indent-tabs-mode: t
- * End:
- * vim600: sw=4 ts=4 fdm=marker
- * vim<600: sw=4 ts=4
- */
|