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

LTP GCOV extension - code coverage report
Current view: directory - var/php_gcov/PHP_5_2/main/streams - plain_wrapper.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 555
Code covered: 75.7 % Executed lines: 420
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 The PHP Group                                |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt                                  |
      11                 :    | If you did not receive a copy of the PHP license and are unable to   |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@php.net so we can mail you a copy immediately.               |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Authors: Wez Furlong <wez@thebrainroom.com>                          |
      16                 :    +----------------------------------------------------------------------+
      17                 :  */
      18                 : 
      19                 : /* $Id: plain_wrapper.c 275506 2009-02-10 16:14:27Z iliaa $ */
      20                 : 
      21                 : #include "php.h"
      22                 : #include "php_globals.h"
      23                 : #include "php_network.h"
      24                 : #include "php_open_temporary_file.h"
      25                 : #include "ext/standard/file.h"
      26                 : #include "ext/standard/flock_compat.h"
      27                 : #include "ext/standard/php_filestat.h"
      28                 : #include <stddef.h>
      29                 : #include <fcntl.h>
      30                 : #if HAVE_SYS_WAIT_H
      31                 : #include <sys/wait.h>
      32                 : #endif
      33                 : #if HAVE_SYS_FILE_H
      34                 : #include <sys/file.h>
      35                 : #endif
      36                 : #ifdef HAVE_SYS_MMAN_H
      37                 : #include <sys/mman.h>
      38                 : #endif
      39                 : #include "SAPI.h"
      40                 : 
      41                 : #include "php_streams_int.h"
      42                 : 
      43                 : #define php_stream_fopen_from_fd_int(fd, mode, persistent_id)   _php_stream_fopen_from_fd_int((fd), (mode), (persistent_id) STREAMS_CC TSRMLS_CC)
      44                 : #define php_stream_fopen_from_fd_int_rel(fd, mode, persistent_id)        _php_stream_fopen_from_fd_int((fd), (mode), (persistent_id) STREAMS_REL_CC TSRMLS_CC)
      45                 : #define php_stream_fopen_from_file_int(file, mode)      _php_stream_fopen_from_file_int((file), (mode) STREAMS_CC TSRMLS_CC)
      46                 : #define php_stream_fopen_from_file_int_rel(file, mode)   _php_stream_fopen_from_file_int((file), (mode) STREAMS_REL_CC TSRMLS_CC)
      47                 : 
      48                 : /* parse standard "fopen" modes into open() flags */
      49                 : PHPAPI int php_stream_parse_fopen_modes(const char *mode, int *open_flags)
      50           46906 : {
      51                 :         int flags;
      52                 : 
      53           46906 :         switch (mode[0]) {
      54                 :                 case 'r':
      55           24433 :                         flags = 0;
      56           24433 :                         break;
      57                 :                 case 'w':
      58           19844 :                         flags = O_TRUNC|O_CREAT;
      59           19844 :                         break;
      60                 :                 case 'a':
      61            1374 :                         flags = O_CREAT|O_APPEND;
      62            1374 :                         break;
      63                 :                 case 'x':
      64            1232 :                         flags = O_CREAT|O_EXCL;
      65            1232 :                         break;
      66                 :                 case 'c':
      67               0 :                         flags = O_CREAT;
      68               0 :                         break;
      69                 :                 default:
      70                 :                         /* unknown mode */
      71              23 :                         return FAILURE;
      72                 :         }
      73                 : 
      74           46883 :         if (strchr(mode, '+')) {
      75            4030 :                 flags |= O_RDWR;
      76           42853 :         } else if (flags) {
      77           19114 :                 flags |= O_WRONLY;
      78                 :         } else {
      79           23739 :                 flags |= O_RDONLY;
      80                 :         }
      81                 : 
      82                 : #if defined(_O_TEXT) && defined(O_BINARY)
      83                 :         if (strchr(mode, 't')) {
      84                 :                 flags |= _O_TEXT;
      85                 :         } else {
      86                 :                 flags |= O_BINARY;
      87                 :         }
      88                 : #endif
      89                 : 
      90           46883 :         *open_flags = flags;
      91           46883 :         return SUCCESS;
      92                 : }
      93                 : 
      94                 : 
      95                 : /* {{{ ------- STDIO stream implementation -------*/
      96                 : 
      97                 : typedef struct {
      98                 :         FILE *file;
      99                 :         int fd;                                 /* underlying file descriptor */
     100                 :         unsigned is_process_pipe:1;     /* use pclose instead of fclose */
     101                 :         unsigned is_pipe:1;                     /* don't try and seek */
     102                 :         unsigned cached_fstat:1;        /* sb is valid */
     103                 :         unsigned _reserved:29;
     104                 :         
     105                 :         int lock_flag;                  /* stores the lock state */
     106                 :         char *temp_file_name;   /* if non-null, this is the path to a temporary file that
     107                 :                                                          * is to be deleted when the stream is closed */
     108                 : #if HAVE_FLUSHIO
     109                 :         char last_op;
     110                 : #endif
     111                 : 
     112                 : #if HAVE_MMAP
     113                 :         char *last_mapped_addr;
     114                 :         size_t last_mapped_len;
     115                 : #endif
     116                 : #ifdef PHP_WIN32
     117                 :         char *last_mapped_addr;
     118                 :         HANDLE file_mapping;
     119                 : #endif
     120                 : 
     121                 :         struct stat sb;
     122                 : } php_stdio_stream_data;
     123                 : #define PHP_STDIOP_GET_FD(anfd, data)   anfd = (data)->file ? fileno((data)->file) : (data)->fd
     124                 : 
     125                 : static int do_fstat(php_stdio_stream_data *d, int force)
     126          124797 : {
     127          124797 :         if (!d->cached_fstat || force) {
     128                 :                 int fd;
     129                 :                 int r;
     130                 :            
     131          124797 :                 PHP_STDIOP_GET_FD(fd, d);
     132          124797 :                 r = fstat(fd, &d->sb);
     133          124797 :                 d->cached_fstat = r == 0;
     134                 : 
     135          124797 :                 return r;
     136                 :         }
     137               0 :         return 0;
     138                 : }
     139                 : 
     140                 : static php_stream *_php_stream_fopen_from_fd_int(int fd, const char *mode, const char *persistent_id STREAMS_DC TSRMLS_DC)
     141           81902 : {
     142                 :         php_stdio_stream_data *self;
     143                 :         
     144           81902 :         self = pemalloc_rel_orig(sizeof(*self), persistent_id);
     145           81902 :         memset(self, 0, sizeof(*self));
     146           81902 :         self->file = NULL;
     147           81902 :         self->is_pipe = 0;
     148           81902 :         self->lock_flag = LOCK_UN;
     149           81902 :         self->is_process_pipe = 0;
     150           81902 :         self->temp_file_name = NULL;
     151           81902 :         self->fd = fd;
     152                 :         
     153           81902 :         return php_stream_alloc_rel(&php_stream_stdio_ops, self, persistent_id, mode);
     154                 : }
     155                 : 
     156                 : static php_stream *_php_stream_fopen_from_file_int(FILE *file, const char *mode STREAMS_DC TSRMLS_DC)
     157           40239 : {
     158                 :         php_stdio_stream_data *self;
     159                 :         
     160           40239 :         self = emalloc_rel_orig(sizeof(*self));
     161           40239 :         memset(self, 0, sizeof(*self));
     162           40239 :         self->file = file;
     163           40239 :         self->is_pipe = 0;
     164           40239 :         self->lock_flag = LOCK_UN;
     165           40239 :         self->is_process_pipe = 0;
     166           40239 :         self->temp_file_name = NULL;
     167           40239 :         self->fd = fileno(file);
     168                 : 
     169           40239 :         return php_stream_alloc_rel(&php_stream_stdio_ops, self, 0, mode);
     170                 : }
     171                 : 
     172                 : PHPAPI php_stream *_php_stream_fopen_temporary_file(const char *dir, const char *pfx, char **opened_path STREAMS_DC TSRMLS_DC)
     173               0 : {
     174               0 :         int fd = php_open_temporary_fd(dir, pfx, opened_path TSRMLS_CC);
     175                 : 
     176               0 :         if (fd != -1)   {
     177               0 :                 php_stream *stream = php_stream_fopen_from_fd_int_rel(fd, "r+b", NULL);
     178               0 :                 if (stream) {
     179               0 :                         return stream;
     180                 :                 }
     181               0 :                 close(fd);
     182                 : 
     183               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to allocate stream");
     184                 : 
     185               0 :                 return NULL;
     186                 :         }
     187               0 :         return NULL;
     188                 : }
     189                 : 
     190                 : PHPAPI php_stream *_php_stream_fopen_tmpfile(int dummy STREAMS_DC TSRMLS_DC)
     191              73 : {
     192              73 :         char *opened_path = NULL;
     193              73 :         int fd = php_open_temporary_fd(NULL, "php", &opened_path TSRMLS_CC);
     194                 : 
     195              73 :         if (fd != -1)   {
     196              73 :                 php_stream *stream = php_stream_fopen_from_fd_int_rel(fd, "r+b", NULL);
     197              73 :                 if (stream) {
     198              73 :                         php_stdio_stream_data *self = (php_stdio_stream_data*)stream->abstract;
     199              73 :                         stream->wrapper = &php_plain_files_wrapper;
     200              73 :                         stream->orig_path = estrdup(opened_path);
     201                 : 
     202              73 :                         self->temp_file_name = opened_path;
     203              73 :                         self->lock_flag = LOCK_UN;
     204                 :                         
     205              73 :                         return stream;
     206                 :                 }
     207               0 :                 close(fd);
     208                 : 
     209               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to allocate stream");
     210                 : 
     211               0 :                 return NULL;
     212                 :         }
     213               0 :         return NULL;
     214                 : }
     215                 : 
     216                 : PHPAPI php_stream *_php_stream_fopen_from_fd(int fd, const char *mode, const char *persistent_id STREAMS_DC TSRMLS_DC)
     217           77751 : {
     218           77751 :         php_stream *stream = php_stream_fopen_from_fd_int_rel(fd, mode, persistent_id);
     219                 : 
     220           77751 :         if (stream) {
     221           77751 :                 php_stdio_stream_data *self = (php_stdio_stream_data*)stream->abstract;
     222                 : 
     223                 : #ifdef S_ISFIFO
     224                 :                 /* detect if this is a pipe */
     225           77751 :                 if (self->fd >= 0) {
     226           77751 :                         self->is_pipe = (do_fstat(self, 0) == 0 && S_ISFIFO(self->sb.st_mode)) ? 1 : 0;
     227                 :                 }
     228                 : #elif defined(PHP_WIN32)
     229                 :                 {
     230                 :                         zend_uintptr_t handle = _get_osfhandle(self->fd);
     231                 : 
     232                 :                         if (handle != (zend_uintptr_t)INVALID_HANDLE_VALUE) {
     233                 :                                 self->is_pipe = GetFileType((HANDLE)handle) == FILE_TYPE_PIPE;
     234                 :                         }
     235                 :                 }
     236                 : #endif
     237                 :         
     238           77751 :                 if (self->is_pipe) {
     239           40428 :                         stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
     240                 :                 } else {
     241           37323 :                         stream->position = lseek(self->fd, 0, SEEK_CUR);
     242                 : #ifdef ESPIPE
     243           37323 :                         if (stream->position == (off_t)-1 && errno == ESPIPE) {
     244               0 :                                 stream->position = 0;
     245               0 :                                 stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
     246               0 :                                 self->is_pipe = 1;
     247                 :                         }
     248                 : #endif
     249                 :                 }
     250                 :         }
     251                 : 
     252           77751 :         return stream;
     253                 : }
     254                 : 
     255                 : PHPAPI php_stream *_php_stream_fopen_from_file(FILE *file, const char *mode STREAMS_DC TSRMLS_DC)
     256           40239 : {
     257           40239 :         php_stream *stream = php_stream_fopen_from_file_int_rel(file, mode);
     258                 : 
     259           40239 :         if (stream) {
     260           40239 :                 php_stdio_stream_data *self = (php_stdio_stream_data*)stream->abstract;
     261                 : 
     262                 : #ifdef S_ISFIFO
     263                 :                 /* detect if this is a pipe */
     264           40239 :                 if (self->fd >= 0) {
     265           40239 :                         self->is_pipe = (do_fstat(self, 0) == 0 && S_ISFIFO(self->sb.st_mode)) ? 1 : 0;
     266                 :                 }
     267                 : #elif defined(PHP_WIN32)
     268                 :                 {
     269                 :                         zend_uintptr_t handle = _get_osfhandle(self->fd);
     270                 : 
     271                 :                         if (handle != (zend_uintptr_t)INVALID_HANDLE_VALUE) {
     272                 :                                 self->is_pipe = GetFileType((HANDLE)handle) == FILE_TYPE_PIPE;
     273                 :                         }
     274                 :                 }
     275                 : #endif
     276                 :         
     277           40239 :                 if (self->is_pipe) {
     278           40233 :                         stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
     279                 :                 } else {
     280               6 :                         stream->position = ftell(file);
     281                 :                 }
     282                 :         }
     283                 : 
     284           40239 :         return stream;
     285                 : }
     286                 : 
     287                 : PHPAPI php_stream *_php_stream_fopen_from_pipe(FILE *file, const char *mode STREAMS_DC TSRMLS_DC)
     288             124 : {
     289                 :         php_stdio_stream_data *self;
     290                 :         php_stream *stream;
     291                 : 
     292             124 :         self = emalloc_rel_orig(sizeof(*self));
     293             124 :         memset(self, 0, sizeof(*self));
     294             124 :         self->file = file;
     295             124 :         self->is_pipe = 1;
     296             124 :         self->lock_flag = LOCK_UN;
     297             124 :         self->is_process_pipe = 1;
     298             124 :         self->fd = fileno(file);
     299             124 :         self->temp_file_name = NULL;
     300                 : 
     301             124 :         stream = php_stream_alloc_rel(&php_stream_stdio_ops, self, 0, mode);
     302             124 :         stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
     303             124 :         return stream;
     304                 : }
     305                 : 
     306                 : static size_t php_stdiop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
     307           86127 : {
     308           86127 :         php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract;
     309                 : 
     310                 :         assert(data != NULL);
     311                 : 
     312           86127 :         if (data->fd >= 0) {
     313           86127 :                 int bytes_written = write(data->fd, buf, count);
     314           86127 :                 if (bytes_written < 0) return 0;
     315           86072 :                 return (size_t) bytes_written;
     316                 :         } else {
     317                 : 
     318                 : #if HAVE_FLUSHIO
     319                 :                 if (!data->is_pipe && data->last_op == 'r') {
     320                 :                         fseek(data->file, 0, SEEK_CUR);
     321                 :                 }
     322                 :                 data->last_op = 'w';
     323                 : #endif
     324                 : 
     325               0 :                 return fwrite(buf, 1, count, data->file);
     326                 :         }
     327                 : }
     328                 : 
     329                 : static size_t php_stdiop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
     330          684826 : {
     331          684826 :         php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract;
     332                 :         size_t ret;
     333                 : 
     334                 :         assert(data != NULL);
     335                 : 
     336          684826 :         if (data->fd >= 0) {
     337          684823 :                 ret = read(data->fd, buf, count);
     338                 : 
     339          684823 :                 if (ret == (size_t)-1 && errno == EINTR) {
     340                 :                         /* Read was interrupted, retry once,
     341                 :                            If read still fails, giveup with feof==0
     342                 :                            so script can retry if desired */
     343               0 :                         ret = read(data->fd, buf, count);
     344                 :                 }
     345                 : 
     346          684823 :                 stream->eof = (ret == 0 || (ret == (size_t)-1 && errno != EWOULDBLOCK && errno != EINTR && errno != EBADF));
     347                 :                                 
     348                 :         } else {
     349                 : #if HAVE_FLUSHIO
     350                 :                 if (!data->is_pipe && data->last_op == 'w')
     351                 :                         fseek(data->file, 0, SEEK_CUR);
     352                 :                 data->last_op = 'r';
     353                 : #endif
     354                 : 
     355               3 :                 ret = fread(buf, 1, count, data->file);
     356                 : 
     357               3 :                 stream->eof = feof(data->file);
     358                 :         }
     359          684826 :         return ret;
     360                 : }
     361                 : 
     362                 : static int php_stdiop_close(php_stream *stream, int close_handle TSRMLS_DC)
     363          122373 : {
     364                 :         int ret;
     365          122373 :         php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract;
     366                 : 
     367                 :         assert(data != NULL);
     368                 : 
     369                 : #if HAVE_MMAP
     370          122373 :         if (data->last_mapped_addr) {
     371               0 :                 munmap(data->last_mapped_addr, data->last_mapped_len);
     372               0 :                 data->last_mapped_addr = NULL;
     373                 :         }
     374                 : #elif defined(PHP_WIN32)
     375                 :         if (data->last_mapped_addr) {
     376                 :                 UnmapViewOfFile(data->last_mapped_addr);
     377                 :                 data->last_mapped_addr = NULL;
     378                 :         }
     379                 :         if (data->file_mapping) {
     380                 :                 CloseHandle(data->file_mapping);
     381                 :                 data->file_mapping = NULL;
     382                 :         }
     383                 : #endif
     384                 :         
     385          122373 :         if (close_handle) {
     386          122373 :                 if (data->lock_flag != LOCK_UN) {
     387              54 :                         php_stream_lock(stream, LOCK_UN);
     388                 :                 }
     389          122373 :                 if (data->file) {
     390           40541 :                         if (data->is_process_pipe) {
     391             124 :                                 errno = 0;
     392             124 :                                 ret = pclose(data->file);
     393                 : 
     394                 : #if HAVE_SYS_WAIT_H
     395             124 :                                 if (WIFEXITED(ret)) {
     396             124 :                                         ret = WEXITSTATUS(ret);
     397                 :                                 }
     398                 : #endif
     399                 :                         } else {
     400           40417 :                                 ret = fclose(data->file);
     401           40417 :                                 data->file = NULL;
     402                 :                         }
     403           81832 :                 } else if (data->fd != -1) {
     404           81832 :                         ret = close(data->fd);
     405           81832 :                         data->fd = -1;
     406                 :                 } else {
     407               0 :                         return 0; /* everything should be closed already -> success */
     408                 :                 }
     409          122373 :                 if (data->temp_file_name) {
     410              73 :                         unlink(data->temp_file_name);
     411                 :                         /* temporary streams are never persistent */
     412              73 :                         efree(data->temp_file_name);
     413              73 :                         data->temp_file_name = NULL;
     414                 :                 }
     415                 :         } else {
     416               0 :                 ret = 0;
     417               0 :                 data->file = NULL;
     418               0 :                 data->fd = -1;
     419                 :         }
     420                 : 
     421          122373 :         pefree(data, stream->is_persistent);
     422                 : 
     423          122373 :         return ret;
     424                 : }
     425                 : 
     426                 : static int php_stdiop_flush(php_stream *stream TSRMLS_DC)
     427          123143 : {
     428          123143 :         php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract;
     429                 : 
     430                 :         assert(data != NULL);
     431                 : 
     432                 :         /*
     433                 :          * stdio buffers data in user land. By calling fflush(3), this
     434                 :          * data is send to the kernel using write(2). fsync'ing is
     435                 :          * something completely different.
     436                 :          */
     437          123143 :         if (data->file) {
     438           40547 :                 return fflush(data->file);
     439                 :         }
     440           82596 :         return 0;
     441                 : }
     442                 : 
     443                 : static int php_stdiop_seek(php_stream *stream, off_t offset, int whence, off_t *newoffset TSRMLS_DC)
     444           11840 : {
     445           11840 :         php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract;
     446                 :         int ret;
     447                 : 
     448                 :         assert(data != NULL);
     449                 : 
     450           11840 :         if (data->is_pipe) {
     451               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot seek on a pipe");
     452               0 :                 return -1;
     453                 :         }
     454                 : 
     455           11840 :         if (data->fd >= 0) {
     456                 :                 off_t result;
     457                 :                 
     458           11840 :                 result = lseek(data->fd, offset, whence);
     459           11840 :                 if (result == (off_t)-1)
     460             189 :                         return -1;
     461                 : 
     462           11651 :                 *newoffset = result;
     463           11651 :                 return 0;
     464                 :                 
     465                 :         } else {
     466               0 :                 ret = fseek(data->file, offset, whence);
     467               0 :                 *newoffset = ftell(data->file);
     468               0 :                 return ret;
     469                 :         }
     470                 : }
     471                 : 
     472                 : static int php_stdiop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC)
     473         2454291 : {
     474                 :         int fd;
     475         2454291 :         php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract;
     476                 : 
     477                 :         assert(data != NULL);
     478                 :         
     479                 :         /* as soon as someone touches the stdio layer, buffering may ensue,
     480                 :          * so we need to stop using the fd directly in that case */
     481                 : 
     482         2454291 :         switch (castas) {
     483                 :                 case PHP_STREAM_AS_STDIO:
     484              71 :                         if (ret) {
     485                 : 
     486              71 :                                 if (data->file == NULL) {
     487                 :                                         /* we were opened as a plain file descriptor, so we
     488                 :                                          * need fdopen now */
     489              70 :                                         data->file = fdopen(data->fd, stream->mode);
     490              70 :                                         if (data->file == NULL) {
     491               0 :                                                 return FAILURE;
     492                 :                                         }
     493                 :                                 }
     494                 :                                 
     495              71 :                                 *(FILE**)ret = data->file;
     496              71 :                                 data->fd = -1;
     497                 :                         }
     498              71 :                         return SUCCESS;
     499                 : 
     500                 :                 case PHP_STREAM_AS_FD_FOR_SELECT:
     501         2453968 :                         PHP_STDIOP_GET_FD(fd, data);
     502         2453968 :                         if (fd < 0) {
     503               0 :                                 return FAILURE;
     504                 :                         }
     505         2453968 :                         if (ret) {
     506         2453968 :                                 *(int*)ret = fd;
     507                 :                         }
     508         2453968 :                         return SUCCESS;
     509                 : 
     510                 :                 case PHP_STREAM_AS_FD:
     511             252 :                         PHP_STDIOP_GET_FD(fd, data);
     512                 : 
     513             252 :                         if (fd < 0) {
     514               0 :                                 return FAILURE;
     515                 :                         }
     516             252 :                         if (data->file) {
     517               8 :                                 fflush(data->file);
     518                 :                         }
     519             252 :                         if (ret) {
     520             249 :                                 *(int*)ret = fd;
     521                 :                         }
     522             252 :                         return SUCCESS;
     523                 :                 default:
     524               0 :                         return FAILURE;
     525                 :         }
     526                 : }
     527                 : 
     528                 : static int php_stdiop_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC)
     529            2183 : {
     530                 :         int ret;
     531            2183 :         php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract;
     532                 : 
     533                 :         assert(data != NULL);
     534                 : 
     535            2183 :         ret = do_fstat(data, 1);
     536            2183 :         memcpy(&ssb->sb, &data->sb, sizeof(ssb->sb));
     537            2183 :         return ret;
     538                 : }
     539                 : 
     540                 : static int php_stdiop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC)
     541           25666 : {
     542           25666 :         php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract;
     543                 :         size_t size;
     544                 :         int fd;
     545                 : #ifdef O_NONBLOCK
     546                 :         /* FIXME: make this work for win32 */
     547                 :         int flags;
     548                 :         int oldval;
     549                 : #endif
     550                 :         
     551           25666 :         PHP_STDIOP_GET_FD(fd, data);
     552                 :         
     553           25666 :         switch(option) {
     554                 :                 case PHP_STREAM_OPTION_BLOCKING:
     555               1 :                         if (fd == -1)
     556               0 :                                 return -1;
     557                 : #ifdef O_NONBLOCK
     558               1 :                         flags = fcntl(fd, F_GETFL, 0);
     559               1 :                         oldval = (flags & O_NONBLOCK) ? 0 : 1;
     560               1 :                         if (value)
     561               0 :                                 flags &= ~O_NONBLOCK;
     562                 :                         else
     563               1 :                                 flags |= O_NONBLOCK;
     564                 :                         
     565               1 :                         if (-1 == fcntl(fd, F_SETFL, flags))
     566               0 :                                 return -1;
     567               1 :                         return oldval;
     568                 : #else
     569                 :                         return -1; /* not yet implemented */
     570                 : #endif
     571                 :                         
     572                 :                 case PHP_STREAM_OPTION_WRITE_BUFFER:
     573                 : 
     574               0 :                         if (data->file == NULL) {
     575               0 :                                 return -1;
     576                 :                         }
     577                 :                         
     578               0 :                         if (ptrparam)
     579               0 :                                 size = *(size_t *)ptrparam;
     580                 :                         else
     581               0 :                                 size = BUFSIZ;
     582                 : 
     583               0 :                         switch(value) {
     584                 :                                 case PHP_STREAM_BUFFER_NONE:
     585               0 :                                         stream->flags |= PHP_STREAM_FLAG_NO_BUFFER;
     586               0 :                                         return setvbuf(data->file, NULL, _IONBF, 0);
     587                 :                                         
     588                 :                                 case PHP_STREAM_BUFFER_LINE:
     589               0 :                                         stream->flags ^= PHP_STREAM_FLAG_NO_BUFFER;
     590               0 :                                         return setvbuf(data->file, NULL, _IOLBF, size);
     591                 :                                         
     592                 :                                 case PHP_STREAM_BUFFER_FULL:
     593               0 :                                         stream->flags ^= PHP_STREAM_FLAG_NO_BUFFER;
     594               0 :                                         return setvbuf(data->file, NULL, _IOFBF, size);
     595                 : 
     596                 :                                 default:
     597               0 :                                         return -1;
     598                 :                         }
     599                 :                         break;
     600                 :                 
     601                 :                 case PHP_STREAM_OPTION_LOCKING:
     602             301 :                         if (fd == -1) {
     603               0 :                                 return -1;
     604                 :                         }
     605                 : 
     606             301 :                         if ((zend_uintptr_t) ptrparam == PHP_STREAM_LOCK_SUPPORTED) {
     607              52 :                                 return 0;
     608                 :                         }
     609                 : 
     610             249 :                         if (!flock(fd, value)) {
     611             249 :                                 data->lock_flag = value;
     612             249 :                                 return 0;
     613                 :                         } else {
     614               0 :                                 return -1;
     615                 :                         }
     616                 :                         break;
     617                 : 
     618                 :                 case PHP_STREAM_OPTION_MMAP_API:
     619                 : #if HAVE_MMAP
     620                 :                         {
     621            1537 :                                 php_stream_mmap_range *range = (php_stream_mmap_range*)ptrparam;
     622                 :                                 int prot, flags;
     623                 :                                 
     624            1537 :                                 switch (value) {
     625                 :                                         case PHP_STREAM_MMAP_SUPPORTED:
     626             546 :                                                 return fd == -1 ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK;
     627                 : 
     628                 :                                         case PHP_STREAM_MMAP_MAP_RANGE:
     629             546 :                                                 do_fstat(data, 1);
     630             546 :                                                 if (range->length == 0 && range->offset > 0 && range->offset < data->sb.st_size) {
     631              17 :                                                         range->length = data->sb.st_size - range->offset;
     632                 :                                                 }
     633             546 :                                                 if (range->length == 0 || range->length > data->sb.st_size) {
     634             517 :                                                         range->length = data->sb.st_size;
     635                 :                                                 }
     636             546 :                                                 if (range->offset >= data->sb.st_size) {
     637              84 :                                                         range->offset = data->sb.st_size;
     638              84 :                                                         range->length = 0;
     639                 :                                                 }
     640             546 :                                                 switch (range->mode) {
     641                 :                                                         case PHP_STREAM_MAP_MODE_READONLY:
     642               0 :                                                                 prot = PROT_READ;
     643               0 :                                                                 flags = MAP_PRIVATE;
     644               0 :                                                                 break;
     645                 :                                                         case PHP_STREAM_MAP_MODE_READWRITE:
     646               0 :                                                                 prot = PROT_READ | PROT_WRITE;
     647               0 :                                                                 flags = MAP_PRIVATE;
     648               0 :                                                                 break;
     649                 :                                                         case PHP_STREAM_MAP_MODE_SHARED_READONLY:
     650             546 :                                                                 prot = PROT_READ;
     651             546 :                                                                 flags = MAP_SHARED;
     652             546 :                                                                 break;
     653                 :                                                         case PHP_STREAM_MAP_MODE_SHARED_READWRITE:
     654               0 :                                                                 prot = PROT_READ | PROT_WRITE;
     655               0 :                                                                 flags = MAP_SHARED;
     656               0 :                                                                 break;
     657                 :                                                         default:
     658               0 :                                                                 return PHP_STREAM_OPTION_RETURN_ERR;
     659                 :                                                 }
     660             546 :                                                 range->mapped = (char*)mmap(NULL, range->length, prot, flags, fd, range->offset);
     661             546 :                                                 if (range->mapped == (char*)MAP_FAILED) {
     662             101 :                                                         range->mapped = NULL;
     663             101 :                                                         return PHP_STREAM_OPTION_RETURN_ERR;
     664                 :                                                 }
     665                 :                                                 /* remember the mapping */
     666             445 :                                                 data->last_mapped_addr = range->mapped;
     667             445 :                                                 data->last_mapped_len = range->length;
     668             445 :                                                 return PHP_STREAM_OPTION_RETURN_OK;
     669                 : 
     670                 :                                         case PHP_STREAM_MMAP_UNMAP:
     671             445 :                                                 if (data->last_mapped_addr) {
     672             445 :                                                         munmap(data->last_mapped_addr, data->last_mapped_len);
     673             445 :                                                         data->last_mapped_addr = NULL;
     674                 : 
     675             445 :                                                         return PHP_STREAM_OPTION_RETURN_OK;
     676                 :                                                 }
     677               0 :                                                 return PHP_STREAM_OPTION_RETURN_ERR;
     678                 :                                 }
     679                 :                         }
     680                 : #elif defined(PHP_WIN32)
     681                 :                         {
     682                 :                                 php_stream_mmap_range *range = (php_stream_mmap_range*)ptrparam;
     683                 :                                 HANDLE hfile = (HANDLE)_get_osfhandle(fd);
     684                 :                                 DWORD prot, acc, loffs = 0, delta = 0;
     685                 : 
     686                 :                                 switch (value) {
     687                 :                                         case PHP_STREAM_MMAP_SUPPORTED:
     688                 :                                                 return hfile == INVALID_HANDLE_VALUE ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK;
     689                 : 
     690                 :                                         case PHP_STREAM_MMAP_MAP_RANGE:
     691                 :                                                 switch (range->mode) {
     692                 :                                                         case PHP_STREAM_MAP_MODE_READONLY:
     693                 :                                                                 prot = PAGE_READONLY;
     694                 :                                                                 acc = FILE_MAP_READ;
     695                 :                                                                 break;
     696                 :                                                         case PHP_STREAM_MAP_MODE_READWRITE:
     697                 :                                                                 prot = PAGE_READWRITE;
     698                 :                                                                 acc = FILE_MAP_READ | FILE_MAP_WRITE;
     699                 :                                                                 break;
     700                 :                                                         case PHP_STREAM_MAP_MODE_SHARED_READONLY:
     701                 :                                                                 prot = PAGE_READONLY;
     702                 :                                                                 acc = FILE_MAP_READ;
     703                 :                                                                 /* TODO: we should assign a name for the mapping */
     704                 :                                                                 break;
     705                 :                                                         case PHP_STREAM_MAP_MODE_SHARED_READWRITE:
     706                 :                                                                 prot = PAGE_READWRITE;
     707                 :                                                                 acc = FILE_MAP_READ | FILE_MAP_WRITE;
     708                 :                                                                 /* TODO: we should assign a name for the mapping */
     709                 :                                                                 break;
     710                 :                                                 }
     711                 : 
     712                 :                                                 /* create a mapping capable of viewing the whole file (this costs no real resources) */
     713                 :                                                 data->file_mapping = CreateFileMapping(hfile, NULL, prot, 0, 0, NULL);
     714                 : 
     715                 :                                                 if (data->file_mapping == NULL) {
     716                 :                                                         return PHP_STREAM_OPTION_RETURN_ERR;
     717                 :                                                 }
     718                 : 
     719                 :                                                 size = GetFileSize(hfile, NULL);
     720                 :                                                 if (range->length == 0 && range->offset > 0 && range->offset < size) {
     721                 :                                                         range->length = size - range->offset;
     722                 :                                                 }
     723                 :                                                 if (range->length == 0 || range->length > size) {
     724                 :                                                         range->length = size;
     725                 :                                                 }
     726                 :                                                 if (range->offset >= size) {
     727                 :                                                         range->offset = size;
     728                 :                                                         range->length = 0;
     729                 :                                                 }
     730                 : 
     731                 :                                                 /* figure out how big a chunk to map to be able to view the part that we need */
     732                 :                                                 if (range->offset != 0) {
     733                 :                                                         SYSTEM_INFO info;
     734                 :                                                         DWORD gran;
     735                 : 
     736                 :                                                         GetSystemInfo(&info);
     737                 :                                                         gran = info.dwAllocationGranularity;
     738                 :                                                         loffs = (range->offset / gran) * gran;
     739                 :                                                         delta = range->offset - loffs;
     740                 :                                                 }
     741                 : 
     742                 :                                                 data->last_mapped_addr = MapViewOfFile(data->file_mapping, acc, 0, loffs, range->length + delta);
     743                 : 
     744                 :                                                 if (data->last_mapped_addr) {
     745                 :                                                         /* give them back the address of the start offset they requested */
     746                 :                                                         range->mapped = data->last_mapped_addr + delta;
     747                 :                                                         return PHP_STREAM_OPTION_RETURN_OK;
     748                 :                                                 }
     749                 : 
     750                 :                                                 CloseHandle(data->file_mapping);
     751                 :                                                 data->file_mapping = NULL;
     752                 : 
     753                 :                                                 return PHP_STREAM_OPTION_RETURN_ERR;
     754                 : 
     755                 :                                         case PHP_STREAM_MMAP_UNMAP:
     756                 :                                                 if (data->last_mapped_addr) {
     757                 :                                                         UnmapViewOfFile(data->last_mapped_addr);
     758                 :                                                         data->last_mapped_addr = NULL;
     759                 :                                                         CloseHandle(data->file_mapping);
     760                 :                                                         data->file_mapping = NULL;
     761                 :                                                         return PHP_STREAM_OPTION_RETURN_OK;
     762                 :                                                 }
     763                 :                                                 return PHP_STREAM_OPTION_RETURN_ERR;
     764                 : 
     765                 :                                         default:
     766                 :                                                 return PHP_STREAM_OPTION_RETURN_ERR;
     767                 :                                 }
     768                 :                         }
     769                 : 
     770                 : #endif
     771               0 :                         return PHP_STREAM_OPTION_RETURN_NOTIMPL;
     772                 : 
     773                 :                 case PHP_STREAM_OPTION_TRUNCATE_API:
     774             774 :                         switch (value) {
     775                 :                                 case PHP_STREAM_TRUNCATE_SUPPORTED:
     776             377 :                                         return fd == -1 ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK;
     777                 : 
     778                 :                                 case PHP_STREAM_TRUNCATE_SET_SIZE: {
     779             397 :                                         ptrdiff_t new_size = *(ptrdiff_t*)ptrparam;
     780             397 :                                         if (new_size < 0) {
     781              50 :                                                 return PHP_STREAM_OPTION_RETURN_ERR;
     782                 :                                         }
     783             347 :                                         return ftruncate(fd, new_size) == 0 ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR;
     784                 :                                 }
     785                 :                         }
     786                 :                         
     787                 :                 default:
     788           23053 :                         return PHP_STREAM_OPTION_RETURN_NOTIMPL;
     789                 :         }
     790                 : }
     791                 : 
     792                 : PHPAPI php_stream_ops   php_stream_stdio_ops = {
     793                 :         php_stdiop_write, php_stdiop_read,
     794                 :         php_stdiop_close, php_stdiop_flush,
     795                 :         "STDIO",
     796                 :         php_stdiop_seek,
     797                 :         php_stdiop_cast,
     798                 :         php_stdiop_stat,
     799                 :         php_stdiop_set_option
     800                 : };
     801                 : /* }}} */
     802                 : 
     803                 : /* {{{ plain files opendir/readdir implementation */
     804                 : static size_t php_plain_files_dirstream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
     805           49355 : {
     806           49355 :         DIR *dir = (DIR*)stream->abstract;
     807                 :         /* avoid libc5 readdir problems */
     808                 :         char entry[sizeof(struct dirent)+MAXPATHLEN];
     809           49355 :         struct dirent *result = (struct dirent *)&entry;
     810           49355 :         php_stream_dirent *ent = (php_stream_dirent*)buf;
     811                 : 
     812                 :         /* avoid problems if someone mis-uses the stream */
     813           49355 :         if (count != sizeof(php_stream_dirent))
     814               0 :                 return 0;
     815                 : 
     816           49355 :         if (php_readdir_r(dir, (struct dirent *)entry, &result) == 0 && result) {
     817           46826 :                 PHP_STRLCPY(ent->d_name, result->d_name, sizeof(ent->d_name), strlen(result->d_name));
     818           46826 :                 return sizeof(php_stream_dirent);
     819                 :         }
     820            2529 :         return 0;
     821                 : }
     822                 : 
     823                 : static int php_plain_files_dirstream_close(php_stream *stream, int close_handle TSRMLS_DC)
     824            2663 : {
     825            2663 :         return closedir((DIR *)stream->abstract);
     826                 : }
     827                 : 
     828                 : static int php_plain_files_dirstream_rewind(php_stream *stream, off_t offset, int whence, off_t *newoffs TSRMLS_DC)
     829              10 : {
     830              10 :         rewinddir((DIR *)stream->abstract);
     831              10 :         return 0;
     832                 : }
     833                 : 
     834                 : static php_stream_ops   php_plain_files_dirstream_ops = {
     835                 :         NULL, php_plain_files_dirstream_read,
     836                 :         php_plain_files_dirstream_close, NULL,
     837                 :         "dir",
     838                 :         php_plain_files_dirstream_rewind,
     839                 :         NULL, /* cast */
     840                 :         NULL, /* stat */
     841                 :         NULL  /* set_option */
     842                 : };
     843                 : 
     844                 : static php_stream *php_plain_files_dir_opener(php_stream_wrapper *wrapper, char *path, char *mode,
     845                 :                 int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
     846            2745 : {
     847            2745 :         DIR *dir = NULL;
     848            2745 :         php_stream *stream = NULL;
     849                 : 
     850            2745 :         if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path TSRMLS_CC)) {
     851              24 :                 return NULL;
     852                 :         }
     853                 :         
     854            2721 :         if (PG(safe_mode) &&(!php_checkuid(path, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
     855               0 :                 return NULL;
     856                 :         }
     857                 :         
     858            2721 :         dir = VCWD_OPENDIR(path);
     859                 : 
     860                 : #ifdef PHP_WIN32
     861                 :         if (dir && dir->finished) {
     862                 :                 closedir(dir);
     863                 :                 dir = NULL;
     864                 :         }
     865                 : #endif
     866            2721 :         if (dir) {
     867            2663 :                 stream = php_stream_alloc(&php_plain_files_dirstream_ops, dir, 0, mode);
     868            2663 :                 if (stream == NULL)
     869               0 :                         closedir(dir);
     870                 :         }
     871                 :                 
     872            2721 :         return stream;
     873                 : }
     874                 : /* }}} */
     875                 : 
     876                 : /* {{{ php_stream_fopen */
     877                 : PHPAPI php_stream *_php_stream_fopen(const char *filename, const char *mode, char **opened_path, int options STREAMS_DC TSRMLS_DC)
     878           46906 : {
     879           46906 :         char *realpath = NULL;
     880                 :         int open_flags;
     881                 :         int fd;
     882                 :         php_stream *ret;
     883           46906 :         int persistent = options & STREAM_OPEN_PERSISTENT;
     884           46906 :         char *persistent_id = NULL;
     885                 : 
     886           46906 :         if (FAILURE == php_stream_parse_fopen_modes(mode, &open_flags)) {
     887              23 :                 if (options & REPORT_ERRORS) {
     888               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "`%s' is not a valid mode for fopen", mode);
     889                 :                 }
     890              23 :                 return NULL;
     891                 :         }
     892                 :         
     893           46883 :         if ((realpath = expand_filepath(filename, NULL TSRMLS_CC)) == NULL) {
     894               0 :                 return NULL;
     895                 :         }
     896                 : 
     897           46883 :         if (persistent) {
     898              13 :                 spprintf(&persistent_id, 0, "streams_stdio_%d_%s", open_flags, realpath);
     899              13 :                 switch (php_stream_from_persistent_id(persistent_id, &ret TSRMLS_CC)) {
     900                 :                         case PHP_STREAM_PERSISTENT_SUCCESS:
     901               0 :                                 if (opened_path) {
     902               0 :                                         *opened_path = realpath;
     903               0 :                                         realpath = NULL;
     904                 :                                 }
     905                 :                                 /* fall through */
     906                 : 
     907                 :                         case PHP_STREAM_PERSISTENT_FAILURE:
     908               0 :                                 if (realpath) {
     909               0 :                                         efree(realpath);
     910                 :                                 }
     911               0 :                                 efree(persistent_id);;
     912               0 :                                 return ret;
     913                 :                 }
     914                 :         }
     915                 :         
     916           46883 :         fd = open(realpath, open_flags, 0666);
     917                 : 
     918           46883 :         if (fd != -1)   {
     919                 : 
     920           41401 :                 if (options & STREAM_OPEN_FOR_INCLUDE) {
     921            4078 :                         ret = php_stream_fopen_from_fd_int_rel(fd, mode, persistent_id);
     922                 :                 } else {
     923           37323 :                         ret = php_stream_fopen_from_fd_rel(fd, mode, persistent_id);
     924                 :                 }
     925                 : 
     926           41401 :                 if (ret)        {
     927           41401 :                         if (opened_path) {
     928            4130 :                                 *opened_path = realpath;
     929            4130 :                                 realpath = NULL;
     930                 :                         }
     931           41401 :                         if (realpath) {
     932           37271 :                                 efree(realpath);
     933                 :                         }
     934           41401 :                         if (persistent_id) {
     935              13 :                                 efree(persistent_id);
     936                 :                         }
     937                 : 
     938                 :                         /* WIN32 always set ISREG flag */
     939                 : #ifndef PHP_WIN32
     940                 :                         /* sanity checks for include/require.
     941                 :                          * We check these after opening the stream, so that we save
     942                 :                          * on fstat() syscalls */
     943           41401 :                         if (options & STREAM_OPEN_FOR_INCLUDE) {
     944            4078 :                                 php_stdio_stream_data *self = (php_stdio_stream_data*)ret->abstract;
     945                 :                                 int r;
     946                 : 
     947            4078 :                                 r = do_fstat(self, 0);
     948            4078 :                                 if ((r == 0 && !S_ISREG(self->sb.st_mode))) {
     949               1 :                                         if (opened_path) {
     950               1 :                                                 efree(*opened_path);
     951               1 :                                                 *opened_path = NULL;
     952                 :                                         }
     953               1 :                                         php_stream_close(ret);
     954               1 :                                         return NULL;
     955                 :                                 }
     956                 :                         }
     957                 : #endif
     958                 : 
     959           41400 :                         return ret;
     960                 :                 }
     961               0 :                 close(fd);
     962                 :         }
     963            5482 :         efree(realpath);
     964            5482 :         if (persistent_id) {
     965               0 :                 efree(persistent_id);
     966                 :         }
     967            5482 :         return NULL;
     968                 : }
     969                 : /* }}} */
     970                 : 
     971                 : 
     972                 : static php_stream *php_plain_files_stream_opener(php_stream_wrapper *wrapper, char *path, char *mode,
     973                 :                 int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
     974           41691 : {
     975           41691 :         if ((options & USE_PATH) && PG(include_path) != NULL) {
     976            4317 :                 return php_stream_fopen_with_path_rel(path, mode, PG(include_path), opened_path, options);
     977                 :         }
     978                 : 
     979           37374 :         if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path TSRMLS_CC)) {
     980              40 :                 return NULL;
     981                 :         }
     982                 : 
     983           37334 :         if ((options & ENFORCE_SAFE_MODE) && PG(safe_mode) && (!php_checkuid(path, mode, CHECKUID_CHECK_MODE_PARAM)))
     984               0 :                 return NULL;
     985                 : 
     986           37334 :         return php_stream_fopen_rel(path, mode, opened_path, options);
     987                 : }
     988                 : 
     989                 : static int php_plain_files_url_stater(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC)
     990           63884 : {
     991                 : 
     992           63884 :         if (strncmp(url, "file://", sizeof("file://") - 1) == 0) {
     993               0 :                 url += sizeof("file://") - 1;
     994                 :         }
     995                 : 
     996           63884 :         if (PG(safe_mode) &&(!php_checkuid_ex(url, NULL, CHECKUID_CHECK_FILE_AND_DIR, (flags & PHP_STREAM_URL_STAT_QUIET) ? CHECKUID_NO_ERRORS : 0))) {
     997               0 :                 return -1;
     998                 :         }
     999                 : 
    1000           63884 :         if (php_check_open_basedir_ex(url, (flags & PHP_STREAM_URL_STAT_QUIET) ? 0 : 1 TSRMLS_CC)) {
    1001               8 :                 return -1;
    1002                 :         }
    1003                 : 
    1004                 : #ifdef HAVE_SYMLINK
    1005           63876 :         if (flags & PHP_STREAM_URL_STAT_LINK) {
    1006             106 :                 return VCWD_LSTAT(url, &ssb->sb);
    1007                 :         } else
    1008                 : #endif
    1009           63770 :                 return VCWD_STAT(url, &ssb->sb);
    1010                 : }
    1011                 : 
    1012                 : static int php_plain_files_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC)
    1013          132131 : {
    1014                 :         char *p;
    1015                 :         int ret;
    1016                 : 
    1017          132131 :         if ((p = strstr(url, "://")) != NULL) {
    1018               0 :                 url = p + 3;
    1019                 :         }
    1020                 : 
    1021          132131 :         if (options & ENFORCE_SAFE_MODE) {
    1022          132131 :                 if (PG(safe_mode) && !php_checkuid(url, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
    1023               0 :                         return 0;
    1024                 :                 }
    1025                 : 
    1026          132131 :                 if (php_check_open_basedir(url TSRMLS_CC)) {
    1027               7 :                         return 0;
    1028                 :                 }
    1029                 :         }
    1030                 : 
    1031          132124 :         ret = VCWD_UNLINK(url);
    1032          132124 :         if (ret == -1) {
    1033          115145 :                 if (options & REPORT_ERRORS) {
    1034          115145 :                         php_error_docref1(NULL TSRMLS_CC, url, E_WARNING, "%s", strerror(errno));
    1035                 :                 }
    1036          115145 :                 return 0;
    1037                 :         }
    1038                 : 
    1039                 :         /* Clear stat cache */
    1040           16979 :         php_clear_stat_cache(TSRMLS_C);
    1041                 : 
    1042           16979 :         return 1;
    1043                 : }
    1044                 : 
    1045                 : static int php_plain_files_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC)
    1046              81 : {
    1047                 :         char *p;
    1048                 :         int ret;
    1049                 : 
    1050              81 :         if (!url_from || !url_to) {
    1051               0 :                 return 0;
    1052                 :         }
    1053                 : 
    1054              81 :         if ((p = strstr(url_from, "://")) != NULL) {
    1055               0 :                 url_from = p + 3;
    1056                 :         }
    1057                 : 
    1058              81 :         if ((p = strstr(url_to, "://")) != NULL) {
    1059               0 :                 url_to = p + 3;
    1060                 :         }
    1061                 : 
    1062              81 :         if (PG(safe_mode) && (!php_checkuid(url_from, NULL, CHECKUID_CHECK_FILE_AND_DIR) ||
    1063                 :                                 !php_checkuid(url_to, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
    1064               0 :                 return 0;
    1065                 :         }
    1066                 : 
    1067              81 :         if (php_check_open_basedir(url_from TSRMLS_CC) || php_check_open_basedir(url_to TSRMLS_CC)) {
    1068               5 :                 return 0;
    1069                 :         }
    1070                 : 
    1071              76 :         ret = VCWD_RENAME(url_from, url_to);
    1072                 : 
    1073              76 :         if (ret == -1) {
    1074                 : #ifdef EXDEV
    1075              26 :                 if (errno == EXDEV) {
    1076                 :                         struct stat sb;
    1077               0 :                         if (php_copy_file(url_from, url_to TSRMLS_CC) == SUCCESS) {
    1078               0 :                                 if (VCWD_STAT(url_from, &sb) == 0) {
    1079                 : #if !defined(TSRM_WIN32) && !defined(NETWARE)
    1080               0 :                                         if (VCWD_CHMOD(url_to, sb.st_mode)) {
    1081               0 :                                                 if (errno == EPERM) {
    1082               0 :                                                         php_error_docref2(NULL TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno));
    1083               0 :                                                         VCWD_UNLINK(url_from);
    1084               0 :                                                         return 1;
    1085                 :                                                 }
    1086               0 :                                                 php_error_docref2(NULL TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno));
    1087               0 :                                                 return 0;
    1088                 :                                         }
    1089               0 :                                         if (VCWD_CHOWN(url_to, sb.st_uid, sb.st_gid)) {
    1090               0 :                                                 if (errno == EPERM) {
    1091               0 :                                                         php_error_docref2(NULL TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno));
    1092               0 :                                                         VCWD_UNLINK(url_from);
    1093               0 :                                                         return 1;
    1094                 :                                                 }
    1095               0 :                                                 php_error_docref2(NULL TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno));
    1096               0 :                                                 return 0;
    1097                 :                                         }
    1098                 : #endif
    1099               0 :                                         VCWD_UNLINK(url_from);
    1100               0 :                                         return 1;
    1101                 :                                 }
    1102                 :                         }
    1103               0 :                         php_error_docref2(NULL TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno));
    1104               0 :                         return 0;
    1105                 :                 }
    1106                 : #endif
    1107              26 :                 php_error_docref2(NULL TSRMLS_CC, url_from, url_to, E_WARNING, "%s", strerror(errno));
    1108              26 :         return 0;
    1109                 :         }
    1110                 : 
    1111                 :         /* Clear stat cache */
    1112              50 :         php_clear_stat_cache(TSRMLS_C);
    1113                 : 
    1114              50 :         return 1;
    1115                 : }
    1116                 : 
    1117                 : static int php_plain_files_mkdir(php_stream_wrapper *wrapper, char *dir, int mode, int options, php_stream_context *context TSRMLS_DC)
    1118            1623 : {
    1119            1623 :         int ret, recursive = options & PHP_STREAM_MKDIR_RECURSIVE;
    1120                 :         char *p;
    1121                 : 
    1122            1623 :         if ((p = strstr(dir, "://")) != NULL) {
    1123               0 :                 dir = p + 3;
    1124                 :         }
    1125                 : 
    1126            1623 :         if (!recursive) {
    1127            1078 :                 ret = php_mkdir(dir, mode TSRMLS_CC);
    1128                 :         } else {
    1129                 :                 /* we look for directory separator from the end of string, thus hopefuly reducing our work load */
    1130                 :                 char *e, *buf;
    1131                 :                 struct stat sb;
    1132             545 :                 int dir_len = strlen(dir);
    1133             545 :                 int offset = 0;
    1134                 : 
    1135             545 :                 buf = estrndup(dir, dir_len);
    1136                 : 
    1137                 : #ifdef PHP_WIN32
    1138                 :                 e = buf;
    1139                 :                 while (*e) {
    1140                 :                         if (*e == '/') {
    1141                 :                                 *e = DEFAULT_SLASH;
    1142                 :                         }
    1143                 :                         e++;
    1144                 :                 }
    1145                 : #else
    1146             545 :                 e = buf + dir_len;
    1147                 : #endif
    1148                 : 
    1149             545 :                 if ((p = memchr(buf, DEFAULT_SLASH, dir_len))) {
    1150             531 :                         offset = p - buf + 1;
    1151                 :                 }
    1152                 : 
    1153             545 :                 if (p && dir_len == 1) {
    1154                 :                         /* buf == "DEFAULT_SLASH" */  
    1155                 :                 }
    1156                 :                 else {
    1157                 :                         /* find a top level directory we need to create */
    1158            1637 :                         while ( (p = strrchr(buf + offset, DEFAULT_SLASH)) || (offset != 1 && (p = strrchr(buf, DEFAULT_SLASH))) ) {
    1159            1077 :                                 int n = 0;
    1160                 : 
    1161            1077 :                                 *p = '\0';
    1162            2155 :                                 while (p > buf && *(p-1) == DEFAULT_SLASH) {
    1163               1 :                                         ++n;
    1164               1 :                                         --p;
    1165               1 :                                         *p = '\0';
    1166                 :                                 }
    1167            1077 :                                 if (VCWD_STAT(buf, &sb) == 0) {
    1168                 :                                         while (1) {
    1169             530 :                                                 *p = DEFAULT_SLASH;
    1170             530 :                                                 if (!n) break;
    1171               0 :                                                 --n;
    1172               0 :                                                 ++p;
    1173               0 :                                         }
    1174             530 :                                         break;
    1175                 :                                 }
    1176                 :                         }
    1177                 :                 }
    1178                 : 
    1179             545 :                 if (p == buf) {
    1180               0 :                         ret = php_mkdir(dir, mode TSRMLS_CC);
    1181             545 :                 } else if (!(ret = php_mkdir(buf, mode TSRMLS_CC))) {
    1182             544 :                         if (!p) {
    1183              15 :                                 p = buf;
    1184                 :                         }
    1185                 :                         /* create any needed directories if the creation of the 1st directory worked */
    1186           10394 :                         while (++p != e) {
    1187            9306 :                                 if (*p == '\0') {
    1188             548 :                                         *p = DEFAULT_SLASH;
    1189             548 :                                         if ((*(p+1) != '\0') &&
    1190                 :                                             (ret = VCWD_MKDIR(buf, (mode_t)mode)) < 0) {
    1191               0 :                                                 if (options & REPORT_ERRORS) {
    1192               0 :                                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
    1193                 :                                                 }
    1194               0 :                                                 break;
    1195                 :                                         }
    1196                 :                                 }
    1197                 :                         }
    1198                 :                 }
    1199             545 :                 efree(buf);
    1200                 :         }
    1201            1623 :         if (ret < 0) {
    1202                 :                 /* Failure */
    1203              49 :                 return 0;
    1204                 :         } else {
    1205                 :                 /* Success */
    1206            1574 :                 return 1;
    1207                 :         }
    1208                 : }
    1209                 : 
    1210                 : static int php_plain_files_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC)
    1211            1636 : {
    1212            1636 :         if (PG(safe_mode) &&(!php_checkuid(url, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
    1213               0 :                 return 0;
    1214                 :         }
    1215                 : 
    1216            1636 :         if (php_check_open_basedir(url TSRMLS_CC)) {
    1217               5 :                 return 0;
    1218                 :         }
    1219                 : 
    1220            1631 :         if (VCWD_RMDIR(url) < 0) {
    1221              30 :                 php_error_docref1(NULL TSRMLS_CC, url, E_WARNING, "%s", strerror(errno));
    1222              30 :                 return 0;
    1223                 :         }
    1224                 : 
    1225                 :         /* Clear stat cache */
    1226            1601 :         php_clear_stat_cache(TSRMLS_C);
    1227                 : 
    1228            1601 :         return 1;
    1229                 : }
    1230                 : 
    1231                 : static php_stream_wrapper_ops php_plain_files_wrapper_ops = {
    1232                 :         php_plain_files_stream_opener,
    1233                 :         NULL,
    1234                 :         NULL,
    1235                 :         php_plain_files_url_stater,
    1236                 :         php_plain_files_dir_opener,
    1237                 :         "plainfile",
    1238                 :         php_plain_files_unlink,
    1239                 :         php_plain_files_rename,
    1240                 :         php_plain_files_mkdir,
    1241                 :         php_plain_files_rmdir
    1242                 : };
    1243                 : 
    1244                 : php_stream_wrapper php_plain_files_wrapper = {
    1245                 :         &php_plain_files_wrapper_ops,
    1246                 :         NULL,
    1247                 :         0
    1248                 : };
    1249                 : 
    1250                 : /* {{{ php_stream_fopen_with_path */
    1251                 : PHPAPI php_stream *_php_stream_fopen_with_path(char *filename, char *mode, char *path, char **opened_path, int options STREAMS_DC TSRMLS_DC)
    1252            4317 : {
    1253                 :         /* code ripped off from fopen_wrappers.c */
    1254                 :         char *pathbuf, *ptr, *end;
    1255                 :         char *exec_fname;
    1256                 :         char trypath[MAXPATHLEN];
    1257                 :         struct stat sb;
    1258                 :         php_stream *stream;
    1259                 :         int path_length;
    1260                 :         int filename_length;
    1261                 :         int exec_fname_length;
    1262                 : 
    1263            4317 :         if (opened_path) {
    1264            4122 :                 *opened_path = NULL;
    1265                 :         }
    1266                 : 
    1267            4317 :         if(!filename) {
    1268               0 :                 return NULL;
    1269                 :         }
    1270                 : 
    1271            4317 :         filename_length = strlen(filename);
    1272                 : 
    1273                 :         /* Relative path open */
    1274            4317 :         if (*filename == '.' && (IS_SLASH(filename[1]) || filename[1] == '.')) {
    1275                 :                 /* further checks, we could have ....... filenames */
    1276               8 :                 ptr = filename + 1;
    1277               8 :                 if (*ptr == '.') {
    1278               6 :                         while (*(++ptr) == '.');
    1279               6 :                         if (!IS_SLASH(*ptr)) { /* not a relative path after all */
    1280               1 :                                 goto not_relative_path;
    1281                 :                         }
    1282                 :                 }
    1283                 : 
    1284                 : 
    1285               7 :                 if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(filename TSRMLS_CC)) {
    1286               6 :                         return NULL;
    1287                 :                 }
    1288                 : 
    1289               1 :                 if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM))) {
    1290               0 :                         return NULL;
    1291                 :                 }
    1292               1 :                 return php_stream_fopen_rel(filename, mode, opened_path, options);
    1293                 :         }
    1294                 : 
    1295                 :         /*
    1296                 :          * files in safe_mode_include_dir (or subdir) are excluded from
    1297                 :          * safe mode GID/UID checks
    1298                 :          */
    1299                 : 
    1300            4310 : not_relative_path:
    1301                 : 
    1302                 :         /* Absolute path open */
    1303            4310 :         if (IS_ABSOLUTE_PATH(filename, filename_length)) {
    1304                 : 
    1305            1580 :                 if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(filename TSRMLS_CC)) {
    1306               0 :                         return NULL;
    1307                 :                 }
    1308                 : 
    1309            1580 :                 if ((php_check_safe_mode_include_dir(filename TSRMLS_CC)) == 0)
    1310                 :                         /* filename is in safe_mode_include_dir (or subdir) */
    1311            1580 :                         return php_stream_fopen_rel(filename, mode, opened_path, options);
    1312                 : 
    1313               0 :                 if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM)))
    1314               0 :                         return NULL;
    1315                 : 
    1316               0 :                 return php_stream_fopen_rel(filename, mode, opened_path, options);
    1317                 :         }
    1318                 :         
    1319                 : #ifdef PHP_WIN32
    1320                 :         if (IS_SLASH(filename[0])) {
    1321                 :                 size_t cwd_len;
    1322                 :                 char *cwd;
    1323                 :                 cwd = virtual_getcwd_ex(&cwd_len TSRMLS_CC);
    1324                 :                 /* getcwd() will return always return [DRIVE_LETTER]:/) on windows. */
    1325                 :                 *(cwd+3) = '\0';
    1326                 :         
    1327                 :                 if (snprintf(trypath, MAXPATHLEN, "%s%s", cwd, filename) >= MAXPATHLEN) {
    1328                 :                         php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s/%s path was truncated to %d", cwd, filename, MAXPATHLEN);
    1329                 :                 }
    1330                 :                 
    1331                 :                 free(cwd);
    1332                 :                 
    1333                 :                 if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(trypath TSRMLS_CC)) {
    1334                 :                         return NULL;
    1335                 :                 }
    1336                 :                 if ((php_check_safe_mode_include_dir(trypath TSRMLS_CC)) == 0) {
    1337                 :                         return php_stream_fopen_rel(trypath, mode, opened_path, options);
    1338                 :                 }       
    1339                 :                 if (PG(safe_mode) && (!php_checkuid(trypath, mode, CHECKUID_CHECK_MODE_PARAM))) {
    1340                 :                         return NULL;
    1341                 :                 }
    1342                 :                 
    1343                 :                 return php_stream_fopen_rel(trypath, mode, opened_path, options);
    1344                 :         }
    1345                 : #endif
    1346                 : 
    1347            2730 :         if (!path || (path && !*path)) {
    1348               0 :                 if (PG(safe_mode) && (!php_checkuid(filename, mode, CHECKUID_CHECK_MODE_PARAM))) {
    1349               0 :                         return NULL;
    1350                 :                 }
    1351               0 :                 return php_stream_fopen_rel(filename, mode, opened_path, options);
    1352                 :         }
    1353                 : 
    1354                 :         /* check in provided path */
    1355                 :         /* append the calling scripts' current working directory
    1356                 :          * as a fall back case
    1357                 :          */
    1358            2730 :         if (zend_is_executing(TSRMLS_C)) {
    1359            2729 :                 exec_fname = zend_get_executed_filename(TSRMLS_C);
    1360            2729 :                 exec_fname_length = strlen(exec_fname);
    1361            2729 :                 path_length = strlen(path);
    1362                 : 
    1363           58085 :                 while ((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
    1364            2729 :                 if ((exec_fname && exec_fname[0] == '[')
    1365                 :                                 || exec_fname_length<=0) {
    1366                 :                         /* [no active file] or no path */
    1367               0 :                         pathbuf = estrdup(path);
    1368                 :                 } else {
    1369            2729 :                         pathbuf = (char *) emalloc(exec_fname_length + path_length +1 +1);
    1370            2729 :                         memcpy(pathbuf, path, path_length);
    1371            2729 :                         pathbuf[path_length] = DEFAULT_DIR_SEPARATOR;
    1372            2729 :                         memcpy(pathbuf+path_length+1, exec_fname, exec_fname_length);
    1373            2729 :                         pathbuf[path_length + exec_fname_length +1] = '\0';
    1374                 :                 }
    1375                 :         } else {
    1376               1 :                 pathbuf = estrdup(path);
    1377                 :         }
    1378                 : 
    1379            2730 :         ptr = pathbuf;
    1380                 : 
    1381           10835 :         while (ptr && *ptr) {
    1382            8061 :                 end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
    1383            8061 :                 if (end != NULL) {
    1384            5411 :                         *end = '\0';
    1385            5411 :                         end++;
    1386                 :                 }
    1387            8061 :                 if (*ptr == '\0') {
    1388              22 :                         goto stream_skip;
    1389                 :                 }
    1390            8039 :                 if (snprintf(trypath, MAXPATHLEN, "%s/%s", ptr, filename) >= MAXPATHLEN) {
    1391               0 :                         php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s/%s path was truncated to %d", ptr, filename, MAXPATHLEN);
    1392                 :                 }
    1393                 : 
    1394            8039 :                 if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir_ex(trypath, 0 TSRMLS_CC)) {
    1395              48 :                         goto stream_skip;
    1396                 :                 }
    1397                 :                 
    1398            7991 :                 if (PG(safe_mode)) {
    1399               0 :                         if (VCWD_STAT(trypath, &sb) == 0) {
    1400                 :                                 /* file exists ... check permission */
    1401               0 :                                 if ((php_check_safe_mode_include_dir(trypath TSRMLS_CC) == 0) ||
    1402                 :                                                 php_checkuid_ex(trypath, mode, CHECKUID_CHECK_MODE_PARAM, CHECKUID_NO_ERRORS)) {
    1403                 :                                         /* UID ok, or trypath is in safe_mode_include_dir */
    1404               0 :                                         stream = php_stream_fopen_rel(trypath, mode, opened_path, options);
    1405               0 :                                         goto stream_done;
    1406                 :                                 }
    1407                 :                         }
    1408               0 :                         goto stream_skip;
    1409                 :                 }
    1410            7991 :                 stream = php_stream_fopen_rel(trypath, mode, opened_path, options);
    1411            7991 :                 if (stream) {
    1412            2686 : stream_done:
    1413            2686 :                         efree(pathbuf);
    1414            2686 :                         return stream;
    1415                 :                 }
    1416            5375 : stream_skip:
    1417            5375 :                 ptr = end;
    1418                 :         } /* end provided path */
    1419                 : 
    1420              44 :         efree(pathbuf);
    1421              44 :         return NULL;
    1422                 : 
    1423                 : }
    1424                 : /* }}} */
    1425                 : 
    1426                 : /*
    1427                 :  * Local variables:
    1428                 :  * tab-width: 4
    1429                 :  * c-basic-offset: 4
    1430                 :  * End:
    1431                 :  * vim600: noet sw=4 ts=4 fdm=marker
    1432                 :  * vim<600: noet sw=4 ts=4
    1433                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:29 +0000 (5 days ago)

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