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: 2014-04-10 Functions: 11 13 84.6 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Thu, 10 Apr 2014 08:53:46 +0000 (9 days ago)

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