PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - Zend - zend_stream.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 118 160 73.8 %
Date: 2015-08-29 Functions: 11 13 84.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2015 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             : /* $Id$ */
      23             : 
      24             : 
      25             : #include "zend.h"
      26             : #include "zend_compile.h"
      27             : #include "zend_stream.h"
      28             : 
      29             : #if HAVE_MMAP
      30             : # if HAVE_UNISTD_H
      31             : #  include <unistd.h>
      32             : #  if defined(_SC_PAGESIZE)
      33             : #    define REAL_PAGE_SIZE sysconf(_SC_PAGESIZE);
      34             : #  elif defined(_SC_PAGE_SIZE)
      35             : #    define REAL_PAGE_SIZE sysconf(_SC_PAGE_SIZE);
      36             : #  endif
      37             : # endif
      38             : # if HAVE_SYS_MMAN_H
      39             : #  include <sys/mman.h>
      40             : # endif
      41             : # ifndef REAL_PAGE_SIZE
      42             : #  ifdef PAGE_SIZE
      43             : #   define REAL_PAGE_SIZE PAGE_SIZE
      44             : #  else
      45             : #   define REAL_PAGE_SIZE 4096
      46             : #  endif
      47             : # endif
      48             : #endif
      49             : 
      50             : ZEND_DLIMPORT int isatty(int fd);
      51             : 
      52          12 : static size_t zend_stream_stdio_reader(void *handle, char *buf, size_t len) /* {{{ */
      53             : {
      54          12 :         return fread(buf, 1, len, (FILE*)handle);
      55             : } /* }}} */
      56             : 
      57       41928 : static void zend_stream_stdio_closer(void *handle) /* {{{ */
      58             : {
      59       41928 :         if (handle && (FILE*)handle != stdin) {
      60       41922 :                 fclose((FILE*)handle);
      61             :         }
      62       41928 : } /* }}} */
      63             : 
      64           0 : static size_t zend_stream_stdio_fsizer(void *handle) /* {{{ */
      65             : {
      66             :         zend_stat_t buf;
      67           0 :         if (handle && zend_fstat(fileno((FILE*)handle), &buf) == 0) {
      68             : #ifdef S_ISREG
      69           0 :                 if (!S_ISREG(buf.st_mode)) {
      70           0 :                         return 0;
      71             :                 }
      72             : #endif
      73           0 :                 return buf.st_size;
      74             :         }
      75           0 :         return 0;
      76             : } /* }}} */
      77             : 
      78       42216 : static void zend_stream_unmap(zend_stream *stream) { /* {{{ */
      79             : #if HAVE_MMAP
      80       42216 :         if (stream->mmap.map) {
      81       41920 :                 munmap(stream->mmap.map, stream->mmap.len + ZEND_MMAP_AHEAD);
      82             :         } else
      83             : #endif
      84         296 :         if (stream->mmap.buf) {
      85         296 :                 efree(stream->mmap.buf);
      86             :         }
      87       42216 :         stream->mmap.len = 0;
      88       42216 :         stream->mmap.pos = 0;
      89       42216 :         stream->mmap.map = 0;
      90       42216 :         stream->mmap.buf = 0;
      91       42216 :         stream->handle   = stream->mmap.old_handle;
      92       42216 : } /* }}} */
      93             : 
      94       42216 : static void zend_stream_mmap_closer(zend_stream *stream) /* {{{ */
      95             : {
      96       42216 :         zend_stream_unmap(stream);
      97       42216 :         if (stream->mmap.old_closer && stream->handle) {
      98       42214 :                 stream->mmap.old_closer(stream->handle);
      99             :         }
     100       42216 : } /* }}} */
     101             : 
     102       42807 : static inline int zend_stream_is_mmap(zend_file_handle *file_handle) { /* {{{ */
     103       42807 :         return file_handle->type == ZEND_HANDLE_MAPPED;
     104             : } /* }}} */
     105             : 
     106       42216 : static size_t zend_stream_fsize(zend_file_handle *file_handle) /* {{{ */
     107             : {
     108             :         zend_stat_t buf;
     109             : 
     110       42216 :         if (zend_stream_is_mmap(file_handle)) {
     111           0 :                 return file_handle->handle.stream.mmap.len;
     112             :         }
     113       42216 :         if (file_handle->type == ZEND_HANDLE_STREAM || file_handle->type == ZEND_HANDLE_MAPPED) {
     114         288 :                 return file_handle->handle.stream.fsizer(file_handle->handle.stream.handle);
     115             :         }
     116       41928 :         if (file_handle->handle.fp && zend_fstat(fileno(file_handle->handle.fp), &buf) == 0) {
     117             : #ifdef S_ISREG
     118       41928 :                 if (!S_ISREG(buf.st_mode)) {
     119           6 :                         return 0;
     120             :                 }
     121             : #endif
     122       41922 :                 return buf.st_size;
     123             :         }
     124             : 
     125           0 :         return -1;
     126             : } /* }}} */
     127             : 
     128        8462 : ZEND_API int zend_stream_open(const char *filename, zend_file_handle *handle) /* {{{ */
     129             : {
     130        8462 :         if (zend_stream_open_function) {
     131        8462 :                 return zend_stream_open_function(filename, handle);
     132             :         }
     133           0 :         handle->type = ZEND_HANDLE_FP;
     134           0 :         handle->opened_path = NULL;
     135           0 :         handle->handle.fp = zend_fopen(filename, &handle->opened_path);
     136           0 :         handle->filename = filename;
     137           0 :         handle->free_filename = 0;
     138           0 :         memset(&handle->handle.stream.mmap, 0, sizeof(zend_mmap));
     139             : 
     140           0 :         return (handle->handle.fp) ? SUCCESS : FAILURE;
     141             : } /* }}} */
     142             : 
     143           0 : static int zend_stream_getc(zend_file_handle *file_handle) /* {{{ */
     144             : {
     145             :         char buf;
     146             : 
     147           0 :         if (file_handle->handle.stream.reader(file_handle->handle.stream.handle, &buf, sizeof(buf))) {
     148           0 :                 return (int)buf;
     149             :         }
     150           0 :         return EOF;
     151             : } /* }}} */
     152             : 
     153         591 : static size_t zend_stream_read(zend_file_handle *file_handle, char *buf, size_t len) /* {{{ */
     154             : {
     155         591 :         if (!zend_stream_is_mmap(file_handle) && file_handle->handle.stream.isatty) {
     156           0 :                 int c = '*';
     157             :                 size_t n;
     158             : 
     159             : #ifdef NETWARE
     160             :                 /*
     161             :                         c != 4 check is there as fread of a character in NetWare LibC gives 4 upon ^D character.
     162             :                         Ascii value 4 is actually EOT character which is not defined anywhere in the LibC
     163             :                         or else we can use instead of hardcoded 4.
     164             :                 */
     165             :                 for (n = 0; n < len && (c = zend_stream_getc(file_handle)) != EOF && c != 4 && c != '\n'; ++n) {
     166             : #else
     167           0 :                 for (n = 0; n < len && (c = zend_stream_getc(file_handle)) != EOF && c != '\n'; ++n)  {
     168             : #endif
     169           0 :                         buf[n] = (char)c;
     170             :                 }
     171           0 :                 if (c == '\n') {
     172           0 :                         buf[n++] = (char)c;
     173             :                 }
     174             : 
     175           0 :                 return n;
     176             :         }
     177         591 :         return file_handle->handle.stream.reader(file_handle->handle.stream.handle, buf, len);
     178             : } /* }}} */
     179             : 
     180       50461 : ZEND_API int zend_stream_fixup(zend_file_handle *file_handle, char **buf, size_t *len) /* {{{ */
     181             : {
     182             :         size_t size;
     183             :         zend_stream_type old_type;
     184             : 
     185       50461 :         if (file_handle->type == ZEND_HANDLE_FILENAME) {
     186        2849 :                 if (zend_stream_open(file_handle->filename, file_handle) == FAILURE) {
     187          51 :                         return FAILURE;
     188             :                 }
     189             :         }
     190             : 
     191       50410 :         switch (file_handle->type) {
     192             :                 case ZEND_HANDLE_FD:
     193           0 :                         file_handle->type = ZEND_HANDLE_FP;
     194           0 :                         file_handle->handle.fp = fdopen(file_handle->handle.fd, "rb");
     195             :                         /* no break; */
     196             :                 case ZEND_HANDLE_FP:
     197       41928 :                         if (!file_handle->handle.fp) {
     198           0 :                                 return FAILURE;
     199             :                         }
     200       41928 :                         memset(&file_handle->handle.stream.mmap, 0, sizeof(zend_mmap));
     201       41928 :                         file_handle->handle.stream.isatty     = isatty(fileno((FILE *)file_handle->handle.stream.handle)) ? 1 : 0;
     202       41928 :                         file_handle->handle.stream.reader     = (zend_stream_reader_t)zend_stream_stdio_reader;
     203       41928 :                         file_handle->handle.stream.closer     = (zend_stream_closer_t)zend_stream_stdio_closer;
     204       41928 :                         file_handle->handle.stream.fsizer     = (zend_stream_fsizer_t)zend_stream_stdio_fsizer;
     205       41928 :                         memset(&file_handle->handle.stream.mmap, 0, sizeof(file_handle->handle.stream.mmap));
     206             :                         /* no break; */
     207             :                 case ZEND_HANDLE_STREAM:
     208             :                         /* nothing to do */
     209       42216 :                         break;
     210             : 
     211             :                 case ZEND_HANDLE_MAPPED:
     212        8194 :                         file_handle->handle.stream.mmap.pos = 0;
     213        8194 :                         *buf = file_handle->handle.stream.mmap.buf;
     214        8194 :                         *len = file_handle->handle.stream.mmap.len;
     215        8194 :                         return SUCCESS;
     216             : 
     217             :                 default:
     218           0 :                         return FAILURE;
     219             :         }
     220             : 
     221       42216 :         size = zend_stream_fsize(file_handle);
     222       42216 :         if (size == (size_t)-1) {
     223           0 :                 return FAILURE;
     224             :         }
     225             : 
     226       42216 :         old_type = file_handle->type;
     227       42216 :         file_handle->type = ZEND_HANDLE_STREAM;  /* we might still be _FP but we need fsize() work */
     228             : 
     229       42218 :         if (old_type == ZEND_HANDLE_FP && !file_handle->handle.stream.isatty && size) {
     230             : #if HAVE_MMAP
     231       41922 :                 size_t page_size = REAL_PAGE_SIZE;
     232             : 
     233       83844 :                 if (file_handle->handle.fp &&
     234             :                     size != 0 &&
     235       41922 :                     ((size - 1) % page_size) <= page_size - ZEND_MMAP_AHEAD) {
     236             :                         /*  *buf[size] is zeroed automatically by the kernel */
     237       41920 :                         *buf = mmap(0, size + ZEND_MMAP_AHEAD, PROT_READ, MAP_PRIVATE, fileno(file_handle->handle.fp), 0);
     238       41920 :                         if (*buf != MAP_FAILED) {
     239       41920 :                                 zend_long offset = ftell(file_handle->handle.fp);
     240       41920 :                                 file_handle->handle.stream.mmap.map = *buf;
     241             : 
     242       41920 :                                 if (offset != -1) {
     243       41920 :                                         *buf += offset;
     244       41920 :                                         size -= offset;
     245             :                                 }
     246       41920 :                                 file_handle->handle.stream.mmap.buf = *buf;
     247       41920 :                                 file_handle->handle.stream.mmap.len = size;
     248             : 
     249       41920 :                                 goto return_mapped;
     250             :                         }
     251             :                 }
     252             : #endif
     253           2 :                 file_handle->handle.stream.mmap.map = 0;
     254           2 :                 file_handle->handle.stream.mmap.buf = *buf = safe_emalloc(1, size, ZEND_MMAP_AHEAD);
     255           2 :                 file_handle->handle.stream.mmap.len = zend_stream_read(file_handle, *buf, size);
     256             :         } else {
     257         294 :                 size_t read, remain = 4*1024;
     258         294 :                 *buf = emalloc(remain);
     259         294 :                 size = 0;
     260             : 
     261         883 :                 while ((read = zend_stream_read(file_handle, *buf + size, remain)) > 0) {
     262         295 :                         size   += read;
     263         295 :                         remain -= read;
     264             : 
     265         295 :                         if (remain == 0) {
     266           4 :                                 *buf   = safe_erealloc(*buf, size, 2, 0);
     267           4 :                                 remain = size;
     268             :                         }
     269             :                 }
     270         294 :                 file_handle->handle.stream.mmap.map = 0;
     271         294 :                 file_handle->handle.stream.mmap.len = size;
     272         294 :                 if (size && remain < ZEND_MMAP_AHEAD) {
     273           0 :                         *buf = safe_erealloc(*buf, size, 1, ZEND_MMAP_AHEAD);
     274             :                 }
     275         294 :                 file_handle->handle.stream.mmap.buf = *buf;
     276             :         }
     277             : 
     278         296 :         if (file_handle->handle.stream.mmap.len == 0) {
     279           2 :                 *buf = erealloc(*buf, ZEND_MMAP_AHEAD);
     280           2 :                 file_handle->handle.stream.mmap.buf = *buf;
     281             :         }
     282             : 
     283             :         if (ZEND_MMAP_AHEAD) {
     284         296 :                 memset(file_handle->handle.stream.mmap.buf + file_handle->handle.stream.mmap.len, 0, ZEND_MMAP_AHEAD);
     285             :         }
     286             : #if HAVE_MMAP
     287             : return_mapped:
     288             : #endif
     289       42216 :         file_handle->type = ZEND_HANDLE_MAPPED;
     290       42216 :         file_handle->handle.stream.mmap.pos        = 0;
     291       42216 :         file_handle->handle.stream.mmap.old_handle = file_handle->handle.stream.handle;
     292       42216 :         file_handle->handle.stream.mmap.old_closer = file_handle->handle.stream.closer;
     293       42216 :         file_handle->handle.stream.handle          = &file_handle->handle.stream;
     294       42216 :         file_handle->handle.stream.closer          = (zend_stream_closer_t)zend_stream_mmap_closer;
     295             : 
     296       42216 :         *buf = file_handle->handle.stream.mmap.buf;
     297       42216 :         *len = file_handle->handle.stream.mmap.len;
     298             : 
     299       42216 :         return SUCCESS;
     300             : } /* }}} */
     301             : 
     302       50416 : ZEND_API void zend_file_handle_dtor(zend_file_handle *fh) /* {{{ */
     303             : {
     304       50416 :         switch (fh->type) {
     305             :                 case ZEND_HANDLE_FD:
     306             :                         /* nothing to do */
     307           0 :                         break;
     308             :                 case ZEND_HANDLE_FP:
     309           0 :                         fclose(fh->handle.fp);
     310           0 :                         break;
     311             :                 case ZEND_HANDLE_STREAM:
     312             :                 case ZEND_HANDLE_MAPPED:
     313       50416 :                         if (fh->handle.stream.closer && fh->handle.stream.handle) {
     314       50416 :                                 fh->handle.stream.closer(fh->handle.stream.handle);
     315             :                         }
     316       50416 :                         fh->handle.stream.handle = NULL;
     317             :                         break;
     318             :                 case ZEND_HANDLE_FILENAME:
     319             :                         /* We're only supposed to get here when destructing the used_files hash,
     320             :                          * which doesn't really contain open files, but references to their names/paths
     321             :                          */
     322             :                         break;
     323             :         }
     324       50416 :         if (fh->opened_path) {
     325       29250 :                 zend_string_release(fh->opened_path);
     326       29250 :                 fh->opened_path = NULL;
     327             :         }
     328       50416 :         if (fh->free_filename && fh->filename) {
     329           0 :                 efree((char*)fh->filename);
     330           0 :                 fh->filename = NULL;
     331             :         }
     332       50416 : }
     333             : /* }}} */
     334             : 
     335       28967 : ZEND_API int zend_compare_file_handles(zend_file_handle *fh1, zend_file_handle *fh2) /* {{{ */
     336             : {
     337       28967 :         if (fh1->type != fh2->type) {
     338           0 :                 return 0;
     339             :         }
     340       28967 :         switch (fh1->type) {
     341             :                 case ZEND_HANDLE_FD:
     342           0 :                         return fh1->handle.fd == fh2->handle.fd;
     343             :                 case ZEND_HANDLE_FP:
     344           0 :                         return fh1->handle.fp == fh2->handle.fp;
     345             :                 case ZEND_HANDLE_STREAM:
     346           0 :                         return fh1->handle.stream.handle == fh2->handle.stream.handle;
     347             :                 case ZEND_HANDLE_MAPPED:
     348       78778 :                         return (fh1->handle.stream.handle == &fh1->handle.stream &&
     349       20844 :                                 fh2->handle.stream.handle == &fh2->handle.stream &&
     350           0 :                                 fh1->handle.stream.mmap.old_handle == fh2->handle.stream.mmap.old_handle)
     351       28967 :                                 || fh1->handle.stream.handle == fh2->handle.stream.handle;
     352             :                 default:
     353           0 :                         return 0;
     354             :         }
     355             :         return 0;
     356             : } /* }}} */

Generated by: LCOV version 1.10

Generated at Sat, 29 Aug 2015 10:22:11 +0000 (3 days ago)

Copyright © 2005-2015 The PHP Group
All rights reserved.