Diff for /embedaddon/php/main/streams/streams.c between versions 1.1 and 1.1.1.4

version 1.1, 2012/02/21 23:48:05 version 1.1.1.4, 2013/10/14 08:02:43
Line 2 Line 2
    +----------------------------------------------------------------------+     +----------------------------------------------------------------------+
    | PHP Version 5                                                        |     | PHP Version 5                                                        |
    +----------------------------------------------------------------------+     +----------------------------------------------------------------------+
   | Copyright (c) 1997-2012 The PHP Group                                |   | Copyright (c) 1997-2013 The PHP Group                                |
    +----------------------------------------------------------------------+     +----------------------------------------------------------------------+
    | This source file is subject to version 3.01 of the PHP license,      |     | This source file is subject to version 3.01 of the PHP license,      |
    | that is bundled with this package in the file LICENSE, and is        |     | that is bundled with this package in the file LICENSE, and is        |
Line 105  PHP_RSHUTDOWN_FUNCTION(streams) Line 105  PHP_RSHUTDOWN_FUNCTION(streams)
         return SUCCESS;          return SUCCESS;
 }  }
   
   PHPAPI php_stream *php_stream_encloses(php_stream *enclosing, php_stream *enclosed)
   {
           php_stream *orig = enclosed->enclosing_stream;
   
           php_stream_auto_cleanup(enclosed);
           enclosed->enclosing_stream = enclosing;
           return orig;
   }
   
 PHPAPI int php_stream_from_persistent_id(const char *persistent_id, php_stream **stream TSRMLS_DC)  PHPAPI int php_stream_from_persistent_id(const char *persistent_id, php_stream **stream TSRMLS_DC)
 {  {
         zend_rsrc_list_entry *le;          zend_rsrc_list_entry *le;
Line 148  PHPAPI int php_stream_from_persistent_id(const char *p Line 157  PHPAPI int php_stream_from_persistent_id(const char *p
   
 /* }}} */  /* }}} */
   
   static zend_llist *php_get_wrapper_errors_list(php_stream_wrapper *wrapper TSRMLS_DC)
   {
       zend_llist *list = NULL;
       if (!FG(wrapper_errors)) {
           return NULL;
       } else {
           zend_hash_find(FG(wrapper_errors), (const char*)&wrapper,
               sizeof wrapper, (void**)&list);
           return list;
       }
   }
   
 /* {{{ wrapper error reporting */  /* {{{ wrapper error reporting */
 void php_stream_display_wrapper_errors(php_stream_wrapper *wrapper, const char *path, const char *caption TSRMLS_DC)  void php_stream_display_wrapper_errors(php_stream_wrapper *wrapper, const char *path, const char *caption TSRMLS_DC)
 {  {
         char *tmp = estrdup(path);          char *tmp = estrdup(path);
         char *msg;          char *msg;
         int free_msg = 0;          int free_msg = 0;
         php_stream_wrapper orig_wrapper;  
   
         if (wrapper) {          if (wrapper) {
                if (wrapper->err_count > 0) {                zend_llist *err_list = php_get_wrapper_errors_list(wrapper TSRMLS_CC);
                        int i;                if (err_list) {
                        size_t l;                        size_t l = 0;
                         int brlen;                          int brlen;
                        char *br;                        int i;
                         int count = zend_llist_count(err_list);
                         const char *br;
                         const char **err_buf_p;
                         zend_llist_position pos;
   
                         if (PG(html_errors)) {                          if (PG(html_errors)) {
                                 brlen = 7;                                  brlen = 7;
Line 171  void php_stream_display_wrapper_errors(php_stream_wrap Line 195  void php_stream_display_wrapper_errors(php_stream_wrap
                                 br = "\n";                                  br = "\n";
                         }                          }
   
                        for (i = 0, l = 0; i < wrapper->err_count; i++) {                        for (err_buf_p = zend_llist_get_first_ex(err_list, &pos), i = 0;
                                l += strlen(wrapper->err_stack[i]);                                        err_buf_p;
                                if (i < wrapper->err_count - 1) {                                        err_buf_p = zend_llist_get_next_ex(err_list, &pos), i++) {
                                 l += strlen(*err_buf_p);
                                 if (i < count - 1) {
                                         l += brlen;                                          l += brlen;
                                 }                                  }
                         }                          }
                         msg = emalloc(l + 1);                          msg = emalloc(l + 1);
                         msg[0] = '\0';                          msg[0] = '\0';
                        for (i = 0; i < wrapper->err_count; i++) {                        for (err_buf_p = zend_llist_get_first_ex(err_list, &pos), i = 0;
                                strcat(msg, wrapper->err_stack[i]);                                        err_buf_p;
                                if (i < wrapper->err_count - 1) {                                        err_buf_p = zend_llist_get_next_ex(err_list, &pos), i++) {
                                 strcat(msg, *err_buf_p);
                                 if (i < count - 1) {
                                         strcat(msg, br);                                          strcat(msg, br);
                                 }                                  }
                         }                          }
Line 189  void php_stream_display_wrapper_errors(php_stream_wrap Line 217  void php_stream_display_wrapper_errors(php_stream_wrap
                         free_msg = 1;                          free_msg = 1;
                 } else {                  } else {
                         if (wrapper == &php_plain_files_wrapper) {                          if (wrapper == &php_plain_files_wrapper) {
                                msg = strerror(errno);                                msg = strerror(errno); /* TODO: not ts on linux */
                         } else {                          } else {
                                 msg = "operation failed";                                  msg = "operation failed";
                         }                          }
Line 199  void php_stream_display_wrapper_errors(php_stream_wrap Line 227  void php_stream_display_wrapper_errors(php_stream_wrap
         }          }
   
         php_strip_url_passwd(tmp);          php_strip_url_passwd(tmp);
         if (wrapper) {  
                 /* see bug #52935 */  
                 orig_wrapper = *wrapper;  
                 wrapper->err_stack = NULL;  
                 wrapper->err_count = 0;  
         }  
         php_error_docref1(NULL TSRMLS_CC, tmp, E_WARNING, "%s: %s", caption, msg);          php_error_docref1(NULL TSRMLS_CC, tmp, E_WARNING, "%s: %s", caption, msg);
         if (wrapper) {  
                 *wrapper = orig_wrapper;  
         }  
         efree(tmp);          efree(tmp);
         if (free_msg) {          if (free_msg) {
                 efree(msg);                  efree(msg);
Line 217  void php_stream_display_wrapper_errors(php_stream_wrap Line 236  void php_stream_display_wrapper_errors(php_stream_wrap
   
 void php_stream_tidy_wrapper_error_log(php_stream_wrapper *wrapper TSRMLS_DC)  void php_stream_tidy_wrapper_error_log(php_stream_wrapper *wrapper TSRMLS_DC)
 {  {
        if (wrapper) {        if (wrapper && FG(wrapper_errors)) {
                /* tidy up the error stack */                zend_hash_del(FG(wrapper_errors), (const char*)&wrapper, sizeof wrapper);
                int i; 
 
                for (i = 0; i < wrapper->err_count; i++) { 
                        efree(wrapper->err_stack[i]); 
                } 
                if (wrapper->err_stack) { 
                        efree(wrapper->err_stack); 
                } 
                wrapper->err_stack = NULL; 
                wrapper->err_count = 0; 
         }          }
 }  }
   
   static void wrapper_error_dtor(void *error)
   {
           efree(*(char**)error);
   }
   
 PHPAPI void php_stream_wrapper_log_error(php_stream_wrapper *wrapper, int options TSRMLS_DC, const char *fmt, ...)  PHPAPI void php_stream_wrapper_log_error(php_stream_wrapper *wrapper, int options TSRMLS_DC, const char *fmt, ...)
 {  {
         va_list args;          va_list args;
Line 245  PHPAPI void php_stream_wrapper_log_error(php_stream_wr Line 259  PHPAPI void php_stream_wrapper_log_error(php_stream_wr
                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", buffer);                  php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", buffer);
                 efree(buffer);                  efree(buffer);
         } else {          } else {
                /* append to stack */                zend_llist *list = NULL;
                wrapper->err_stack = erealloc(wrapper->err_stack, (wrapper->err_count + 1) * sizeof(char *));                if (!FG(wrapper_errors)) {
                if (wrapper->err_stack) {                        ALLOC_HASHTABLE(FG(wrapper_errors));
                        wrapper->err_stack[wrapper->err_count++] = buffer;                        zend_hash_init(FG(wrapper_errors), 8, NULL,
                                         (dtor_func_t)zend_llist_destroy, 0);
                 } else {
                         zend_hash_find(FG(wrapper_errors), (const char*)&wrapper,
                                 sizeof wrapper, (void**)&list);
                 }                  }
   
                   if (!list) {
                           zend_llist new_list;
                           zend_llist_init(&new_list, sizeof buffer, wrapper_error_dtor, 0);
                           zend_hash_update(FG(wrapper_errors), (const char*)&wrapper,
                                   sizeof wrapper, &new_list, sizeof new_list, (void**)&list);
                   }
   
                   /* append to linked list */
                   zend_llist_add_element(list, &buffer);
         }          }
 }  }
   
Line 305  fprintf(stderr, "stream_alloc: %s:%p persistent=%s\n", Line 333  fprintf(stderr, "stream_alloc: %s:%p persistent=%s\n",
         ret->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, ret, persistent_id ? le_pstream : le_stream);          ret->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, ret, persistent_id ? le_pstream : le_stream);
         strlcpy(ret->mode, mode, sizeof(ret->mode));          strlcpy(ret->mode, mode, sizeof(ret->mode));
   
           ret->wrapper          = NULL;
           ret->wrapperthis      = NULL;
           ret->wrapperdata      = NULL;
           ret->stdiocast        = NULL;
           ret->orig_path        = NULL;
           ret->context          = NULL;
           ret->readbuf          = NULL;
           ret->enclosing_stream = NULL;
   
         return ret;          return ret;
 }  }
 /* }}} */  /* }}} */
   
   PHPAPI int _php_stream_free_enclosed(php_stream *stream_enclosed, int close_options TSRMLS_DC) /* {{{ */
   {
           return _php_stream_free(stream_enclosed,
                   close_options | PHP_STREAM_FREE_IGNORE_ENCLOSING TSRMLS_CC);
   }
   /* }}} */
   
   #if STREAM_DEBUG
   static const char *_php_stream_pretty_free_options(int close_options, char *out)
   {
           if (close_options & PHP_STREAM_FREE_CALL_DTOR)
                   strcat(out, "CALL_DTOR, ");
           if (close_options & PHP_STREAM_FREE_RELEASE_STREAM)
                   strcat(out, "RELEASE_STREAM, ");
           if (close_options & PHP_STREAM_FREE_PRESERVE_HANDLE)
                   strcat(out, "PREVERSE_HANDLE, ");
           if (close_options & PHP_STREAM_FREE_RSRC_DTOR)
                   strcat(out, "RSRC_DTOR, ");
           if (close_options & PHP_STREAM_FREE_PERSISTENT)
                   strcat(out, "PERSISTENT, ");
           if (close_options & PHP_STREAM_FREE_IGNORE_ENCLOSING)
                   strcat(out, "IGNORE_ENCLOSING, ");
           if (out[0] != '\0')
                   out[strlen(out) - 2] = '\0';
           return out;
   }
   #endif
   
 static int _php_stream_free_persistent(zend_rsrc_list_entry *le, void *pStream TSRMLS_DC)  static int _php_stream_free_persistent(zend_rsrc_list_entry *le, void *pStream TSRMLS_DC)
 {  {
         return le->ptr == pStream;          return le->ptr == pStream;
 }  }
   
   
 PHPAPI int _php_stream_free(php_stream *stream, int close_options TSRMLS_DC) /* {{{ */  PHPAPI int _php_stream_free(php_stream *stream, int close_options TSRMLS_DC) /* {{{ */
 {  {
         int ret = 1;          int ret = 1;
         int remove_rsrc = 1;  
         int preserve_handle = close_options & PHP_STREAM_FREE_PRESERVE_HANDLE ? 1 : 0;          int preserve_handle = close_options & PHP_STREAM_FREE_PRESERVE_HANDLE ? 1 : 0;
         int release_cast = 1;          int release_cast = 1;
        php_stream_context *context = stream->context;        php_stream_context *context = NULL;
   
           /* on an resource list destruction, the context, another resource, may have
            * already been freed (if it was created after the stream resource), so
            * don't reference it */
           if (EG(active)) {
                   context = stream->context;
           }
   
         if (stream->flags & PHP_STREAM_FLAG_NO_CLOSE) {          if (stream->flags & PHP_STREAM_FLAG_NO_CLOSE) {
                 preserve_handle = 1;                  preserve_handle = 1;
         }          }
   
 #if STREAM_DEBUG  #if STREAM_DEBUG
fprintf(stderr, "stream_free: %s:%p[%s] in_free=%d opts=%08x\n", stream->ops->label, stream, stream->orig_path, stream->in_free, close_options);        {
                 char out[200] = "";
                 fprintf(stderr, "stream_free: %s:%p[%s] in_free=%d opts=%s\n",
                         stream->ops->label, stream, stream->orig_path, stream->in_free, _php_stream_pretty_free_options(close_options, out));
         }
         
 #endif  #endif
   
         /* recursion protection */  
         if (stream->in_free) {          if (stream->in_free) {
                return 1;                /* hopefully called recursively from the enclosing stream; the pointer was NULLed below */
                 if ((stream->in_free == 1) && (close_options & PHP_STREAM_FREE_IGNORE_ENCLOSING) && (stream->enclosing_stream == NULL)) {
                         close_options |= PHP_STREAM_FREE_RSRC_DTOR; /* restore flag */
                 } else {
                         return 1; /* recursion protection */
                 }
         }          }
   
         stream->in_free++;          stream->in_free++;
   
           /* force correct order on enclosing/enclosed stream destruction (only from resource
            * destructor as in when reverse destroying the resource list) */
           if ((close_options & PHP_STREAM_FREE_RSRC_DTOR) &&
                           !(close_options & PHP_STREAM_FREE_IGNORE_ENCLOSING) &&
                           (close_options & (PHP_STREAM_FREE_CALL_DTOR | PHP_STREAM_FREE_RELEASE_STREAM)) && /* always? */
                           (stream->enclosing_stream != NULL)) {
                   php_stream *enclosing_stream = stream->enclosing_stream;
                   stream->enclosing_stream = NULL;
                   /* we force PHP_STREAM_CALL_DTOR because that's from where the
                    * enclosing stream can free this stream. We remove rsrc_dtor because
                    * we want the enclosing stream to be deleted from the resource list */
                   return _php_stream_free(enclosing_stream,
                           (close_options | PHP_STREAM_FREE_CALL_DTOR) & ~PHP_STREAM_FREE_RSRC_DTOR TSRMLS_CC);
           }
   
         /* if we are releasing the stream only (and preserving the underlying handle),          /* if we are releasing the stream only (and preserving the underlying handle),
          * we need to do things a little differently.           * we need to do things a little differently.
          * We are only ever called like this when the stream is cast to a FILE*           * We are only ever called like this when the stream is cast to a FILE*
Line 357  fprintf(stderr, "stream_free: %s:%p[%s] in_free=%d opt Line 453  fprintf(stderr, "stream_free: %s:%p[%s] in_free=%d opt
   
 #if STREAM_DEBUG  #if STREAM_DEBUG
 fprintf(stderr, "stream_free: %s:%p[%s] preserve_handle=%d release_cast=%d remove_rsrc=%d\n",  fprintf(stderr, "stream_free: %s:%p[%s] preserve_handle=%d release_cast=%d remove_rsrc=%d\n",
                stream->ops->label, stream, stream->orig_path, preserve_handle, release_cast, remove_rsrc);                stream->ops->label, stream, stream->orig_path, preserve_handle, release_cast,
                 (close_options & PHP_STREAM_FREE_RSRC_DTOR) == 0);
 #endif  #endif
   
         /* make sure everything is saved */          /* make sure everything is saved */
         _php_stream_flush(stream, 1 TSRMLS_CC);          _php_stream_flush(stream, 1 TSRMLS_CC);
   
         /* If not called from the resource dtor, remove the stream from the resource list. */          /* If not called from the resource dtor, remove the stream from the resource list. */
        if ((close_options & PHP_STREAM_FREE_RSRC_DTOR) == 0 && remove_rsrc) {        if ((close_options & PHP_STREAM_FREE_RSRC_DTOR) == 0) {
                 /* zend_list_delete actually only decreases the refcount; if we're                  /* zend_list_delete actually only decreases the refcount; if we're
                  * releasing the stream, we want to actually delete the resource from                   * releasing the stream, we want to actually delete the resource from
                  * the resource list, otherwise the resource will point to invalid memory.                   * the resource list, otherwise the resource will point to invalid memory.
Line 374  fprintf(stderr, "stream_free: %s:%p[%s] preserve_handl Line 471  fprintf(stderr, "stream_free: %s:%p[%s] preserve_handl
         }          }
   
         /* Remove stream from any context link list */          /* Remove stream from any context link list */
        if (stream->context && stream->context->links) {        if (context && context->links) {
                php_stream_context_del_link(stream->context, stream);                php_stream_context_del_link(context, stream);
         }          }
   
         if (close_options & PHP_STREAM_FREE_CALL_DTOR) {          if (close_options & PHP_STREAM_FREE_CALL_DTOR) {
Line 899  PHPAPI char *_php_stream_get_line(php_stream *stream,  Line 996  PHPAPI char *_php_stream_get_line(php_stream *stream, 
         return bufstart;          return bufstart;
 }  }
   
   #define STREAM_BUFFERED_AMOUNT(stream) \
           ((size_t)(((stream)->writepos) - (stream)->readpos))
   
   static char *_php_stream_search_delim(php_stream *stream,
                                                                             size_t maxlen,
                                                                             size_t skiplen,
                                                                             char *delim, /* non-empty! */
                                                                             size_t delim_len TSRMLS_DC)
   {
           size_t  seek_len;
   
           /* set the maximum number of bytes we're allowed to read from buffer */
           seek_len = MIN(STREAM_BUFFERED_AMOUNT(stream), maxlen);
           if (seek_len <= skiplen) {
                   return NULL;
           }
   
           if (delim_len == 1) {
                   return memchr(&stream->readbuf[stream->readpos + skiplen],
                           delim[0], seek_len - skiplen);
           } else {
                   return php_memnstr((char*)&stream->readbuf[stream->readpos + skiplen],
                                   delim, delim_len,
                                   (char*)&stream->readbuf[stream->readpos + seek_len]);
           }
   }
   
 PHPAPI char *php_stream_get_record(php_stream *stream, size_t maxlen, size_t *returned_len, char *delim, size_t delim_len TSRMLS_DC)  PHPAPI char *php_stream_get_record(php_stream *stream, size_t maxlen, size_t *returned_len, char *delim, size_t delim_len TSRMLS_DC)
 {  {
        char *e, *buf;        char    *ret_buf,                               /* returned buffer */
        size_t toread, len;                        *found_delim = NULL;
        int skip = 0;        size_t  buffered_len,
                         tent_ret_len;                    /* tentative returned length */
         int             has_delim        = delim_len > 0;
   
        len = stream->writepos - stream->readpos;        if (maxlen == 0) {
                 return NULL;
         }
   
        /* make sure the stream read buffer has maxlen bytes */        if (has_delim) {
        while (len < maxlen) {                found_delim = _php_stream_search_delim(
                         stream, maxlen, 0, delim, delim_len TSRMLS_CC);
         }
   
                size_t just_read;        buffered_len = STREAM_BUFFERED_AMOUNT(stream);
                toread = MIN(maxlen - len, stream->chunk_size);        /* try to read up to maxlen length bytes while we don't find the delim */
         while (!found_delim && buffered_len < maxlen) {
                 size_t  just_read,
                                 to_read_now;
   
                php_stream_fill_read_buffer(stream, len + toread TSRMLS_CC);                to_read_now = MIN(maxlen - buffered_len, stream->chunk_size);
   
                just_read = (stream->writepos - stream->readpos) - len;                php_stream_fill_read_buffer(stream, buffered_len + to_read_now TSRMLS_CC);
                len += just_read; 
   
                   just_read = STREAM_BUFFERED_AMOUNT(stream) - buffered_len;
   
                 /* Assume the stream is temporarily or permanently out of data */                  /* Assume the stream is temporarily or permanently out of data */
                 if (just_read == 0) {                  if (just_read == 0) {
                         break;                          break;
                 }                  }
         }  
   
        if (delim_len == 0 || !delim) {                if (has_delim) {
                toread = maxlen;                        /* search for delimiter, but skip buffered_len (the number of bytes
        } else {                         * buffered before this loop iteration), as they have already been
                size_t seek_len;                         * searched for the delimiter.
                         * The left part of the delimiter may still remain in the buffer,
                /* set the maximum number of bytes we're allowed to read from buffer */                         * so subtract up to <delim_len - 1> from buffered_len, which is
                seek_len = stream->writepos - stream->readpos;                         * the ammount of data we skip on this search  as an optimization
                if (seek_len > maxlen) {                         */
                        seek_len = maxlen;                        found_delim = _php_stream_search_delim(
                                 stream, maxlen,
                                 buffered_len >= (delim_len - 1)
                                                 ? buffered_len - (delim_len - 1)
                                                 : 0,
                                 delim, delim_len TSRMLS_CC);
                         if (found_delim) {
                                 break;
                         }
                 }                  }
                   buffered_len += just_read;
           }
   
                if (delim_len == 1) {        if (has_delim && found_delim) {
                        e = memchr(stream->readbuf + stream->readpos, *delim, seek_len);                tent_ret_len = found_delim - (char*)&stream->readbuf[stream->readpos];
         } else if (!has_delim && STREAM_BUFFERED_AMOUNT(stream) >= maxlen) {
                 tent_ret_len = maxlen;
         } else {
                 /* return with error if the delimiter string (if any) was not found, we
                  * could not completely fill the read buffer with maxlen bytes and we
                  * don't know we've reached end of file. Added with non-blocking streams
                  * in mind, where this situation is frequent */
                 if (STREAM_BUFFERED_AMOUNT(stream) < maxlen && !stream->eof) {
                         return NULL;
                 } else if (STREAM_BUFFERED_AMOUNT(stream) == 0 && stream->eof) {
                         /* refuse to return an empty string just because by accident
                          * we knew of EOF in a read that returned no data */
                         return NULL;
                 } else {                  } else {
                        e = php_memnstr(stream->readbuf + stream->readpos, delim, delim_len, (stream->readbuf + stream->readpos + seek_len));                        tent_ret_len = MIN(STREAM_BUFFERED_AMOUNT(stream), maxlen);
                 }                  }
   
                 if (!e) {  
                         /* return with error if the delimiter string was not found, we  
                          * could not completely fill the read buffer with maxlen bytes  
                          * and we don't know we've reached end of file. Added with  
                          * non-blocking streams in mind, where this situation is frequent */  
                         if (seek_len < maxlen && !stream->eof) {  
                                 return NULL;  
                         }  
                         toread = maxlen;  
                 } else {  
                         toread = e - (char *) stream->readbuf - stream->readpos;  
                         /* we found the delimiter, so advance the read pointer past it */  
                         skip = 1;  
                 }  
         }          }
   
        if (toread > maxlen && maxlen > 0) {        ret_buf = emalloc(tent_ret_len + 1);
                toread = maxlen;        /* php_stream_read will not call ops->read here because the necessary
        }         * data is guaranteedly buffered */
         *returned_len = php_stream_read(stream, ret_buf, tent_ret_len);
   
        buf = emalloc(toread + 1);        if (found_delim) {
        *returned_len = php_stream_read(stream, buf, toread); 
 
        if (skip) { 
                 stream->readpos += delim_len;                  stream->readpos += delim_len;
                 stream->position += delim_len;                  stream->position += delim_len;
         }          }
        buf[*returned_len] = '\0';        ret_buf[*returned_len] = '\0';
        return buf;        return ret_buf;
 }  }
   
 /* Writes a buffer directly to a stream, using multiple of the chunk size */  /* Writes a buffer directly to a stream, using multiple of the chunk size */
Line 1306  PHPAPI size_t _php_stream_copy_to_mem(php_stream *src, Line 1445  PHPAPI size_t _php_stream_copy_to_mem(php_stream *src,
                         len += ret;                          len += ret;
                         ptr += ret;                          ptr += ret;
                 }                  }
                *ptr = '\0';                if (len) {
                         *ptr = '\0';
                 } else {
                         pefree(*buf, persistent);
                         *buf = NULL;
                 }
                 return len;                  return len;
         }          }
   
Line 1345  PHPAPI size_t _php_stream_copy_to_mem(php_stream *src, Line 1489  PHPAPI size_t _php_stream_copy_to_mem(php_stream *src,
 }  }
   
 /* Returns SUCCESS/FAILURE and sets *len to the number of bytes moved */  /* Returns SUCCESS/FAILURE and sets *len to the number of bytes moved */
PHPAPI size_t _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size_t maxlen, size_t *len STREAMS_DC TSRMLS_DC)PHPAPI int _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size_t maxlen, size_t *len STREAMS_DC TSRMLS_DC)
 {  {
         char buf[CHUNK_SIZE];          char buf[CHUNK_SIZE];
         size_t readchunk;          size_t readchunk;
         size_t haveread = 0;          size_t haveread = 0;
        size_t didread;        size_t didread, didwrite, towrite;
         size_t dummy;          size_t dummy;
         php_stream_statbuf ssbuf;          php_stream_statbuf ssbuf;
   
Line 1385  PHPAPI size_t _php_stream_copy_to_stream_ex(php_stream Line 1529  PHPAPI size_t _php_stream_copy_to_stream_ex(php_stream
                 p = php_stream_mmap_range(src, php_stream_tell(src), maxlen, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped);                  p = php_stream_mmap_range(src, php_stream_tell(src), maxlen, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped);
   
                 if (p) {                  if (p) {
                        mapped = php_stream_write(dest, p, mapped);                        didwrite = php_stream_write(dest, p, mapped);
   
                         php_stream_mmap_unmap_ex(src, mapped);                          php_stream_mmap_unmap_ex(src, mapped);
   
                        *len = mapped;                        *len = didwrite;
   
                        /* we've got at least 1 byte to read.                        /* we've got at least 1 byte to read
                         * less than 1 is an error */                         * less than 1 is an error
                         * AND read bytes match written */
                        if (mapped > 0) {                        if (mapped > 0 && mapped == didwrite) {
                                 return SUCCESS;                                  return SUCCESS;
                         }                          }
                         return FAILURE;                          return FAILURE;
Line 1412  PHPAPI size_t _php_stream_copy_to_stream_ex(php_stream Line 1556  PHPAPI size_t _php_stream_copy_to_stream_ex(php_stream
   
                 if (didread) {                  if (didread) {
                         /* extra paranoid */                          /* extra paranoid */
                         size_t didwrite, towrite;  
                         char *writeptr;                          char *writeptr;
   
                         towrite = didread;                          towrite = didread;
Line 1492  void php_shutdown_stream_hashes(TSRMLS_D) Line 1635  void php_shutdown_stream_hashes(TSRMLS_D)
                 efree(FG(stream_filters));                  efree(FG(stream_filters));
                 FG(stream_filters) = NULL;                  FG(stream_filters) = NULL;
         }          }
       
       if (FG(wrapper_errors)) {
                   zend_hash_destroy(FG(wrapper_errors));
                   efree(FG(wrapper_errors));
                   FG(wrapper_errors) = NULL;
       }
 }  }
   
 int php_init_stream_wrappers(int module_number TSRMLS_DC)  int php_init_stream_wrappers(int module_number TSRMLS_DC)
Line 1740  PHPAPI int _php_stream_mkdir(char *path, int mode, int Line 1889  PHPAPI int _php_stream_mkdir(char *path, int mode, int
 {  {
         php_stream_wrapper *wrapper = NULL;          php_stream_wrapper *wrapper = NULL;
   
        wrapper = php_stream_locate_url_wrapper(path, NULL, ENFORCE_SAFE_MODE TSRMLS_CC);        wrapper = php_stream_locate_url_wrapper(path, NULL, 0 TSRMLS_CC);
         if (!wrapper || !wrapper->wops || !wrapper->wops->stream_mkdir) {          if (!wrapper || !wrapper->wops || !wrapper->wops->stream_mkdir) {
                 return 0;                  return 0;
         }          }
Line 1755  PHPAPI int _php_stream_rmdir(char *path, int options,  Line 1904  PHPAPI int _php_stream_rmdir(char *path, int options, 
 {  {
         php_stream_wrapper *wrapper = NULL;          php_stream_wrapper *wrapper = NULL;
   
        wrapper = php_stream_locate_url_wrapper(path, NULL, ENFORCE_SAFE_MODE TSRMLS_CC);        wrapper = php_stream_locate_url_wrapper(path, NULL, 0 TSRMLS_CC);
         if (!wrapper || !wrapper->wops || !wrapper->wops->stream_rmdir) {          if (!wrapper || !wrapper->wops || !wrapper->wops->stream_rmdir) {
                 return 0;                  return 0;
         }          }
Line 1784  PHPAPI int _php_stream_stat_path(char *path, int flags Line 1933  PHPAPI int _php_stream_stat_path(char *path, int flags
                 }                  }
         }          }
   
        wrapper = php_stream_locate_url_wrapper(path, &path_to_open, ENFORCE_SAFE_MODE TSRMLS_CC);        wrapper = php_stream_locate_url_wrapper(path, &path_to_open, 0 TSRMLS_CC);
         if (wrapper && wrapper->wops->url_stat) {          if (wrapper && wrapper->wops->url_stat) {
                 ret = wrapper->wops->url_stat(wrapper, path_to_open, flags, ssb, context TSRMLS_CC);                  ret = wrapper->wops->url_stat(wrapper, path_to_open, flags, ssb, context TSRMLS_CC);
                 if (ret == 0) {                  if (ret == 0) {
Line 1869  PHPAPI php_stream *_php_stream_open_wrapper_ex(char *p Line 2018  PHPAPI php_stream *_php_stream_open_wrapper_ex(char *p
         char *resolved_path = NULL;          char *resolved_path = NULL;
         char *copy_of_path = NULL;          char *copy_of_path = NULL;
   
   
         if (opened_path) {          if (opened_path) {
                 *opened_path = NULL;                  *opened_path = NULL;
         }          }
Line 2046  PHPAPI void php_stream_context_free(php_stream_context Line 2194  PHPAPI void php_stream_context_free(php_stream_context
         efree(context);          efree(context);
 }  }
   
PHPAPI php_stream_context *php_stream_context_alloc(void)PHPAPI php_stream_context *php_stream_context_alloc(TSRMLS_D)
 {  {
         php_stream_context *context;          php_stream_context *context;
   
Line 2055  PHPAPI php_stream_context *php_stream_context_alloc(vo Line 2203  PHPAPI php_stream_context *php_stream_context_alloc(vo
         MAKE_STD_ZVAL(context->options);          MAKE_STD_ZVAL(context->options);
         array_init(context->options);          array_init(context->options);
   
        context->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, context, php_le_stream_context());        context->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, context, php_le_stream_context(TSRMLS_C));
         return context;          return context;
 }  }
   
Line 2191  PHPAPI int _php_stream_scandir(char *dirname, char **n Line 2339  PHPAPI int _php_stream_scandir(char *dirname, char **n
         php_stream *stream;          php_stream *stream;
         php_stream_dirent sdp;          php_stream_dirent sdp;
         char **vector = NULL;          char **vector = NULL;
        int vector_size = 0;        unsigned int vector_size = 0;
        int nfiles = 0;        unsigned int nfiles = 0;
   
         if (!namelist) {          if (!namelist) {
                 return FAILURE;                  return FAILURE;
         }          }
   
        stream = php_stream_opendir(dirname, ENFORCE_SAFE_MODE | REPORT_ERRORS, context);        stream = php_stream_opendir(dirname, REPORT_ERRORS, context);
         if (!stream) {          if (!stream) {
                 return FAILURE;                  return FAILURE;
         }          }
Line 2208  PHPAPI int _php_stream_scandir(char *dirname, char **n Line 2356  PHPAPI int _php_stream_scandir(char *dirname, char **n
                         if (vector_size == 0) {                          if (vector_size == 0) {
                                 vector_size = 10;                                  vector_size = 10;
                         } else {                          } else {
                                   if(vector_size*2 < vector_size) {
                                           /* overflow */
                                           php_stream_closedir(stream);
                                           efree(vector);
                                           return FAILURE;
                                   }
                                 vector_size *= 2;                                  vector_size *= 2;
                         }                          }
                        vector = (char **) erealloc(vector, vector_size * sizeof(char *));                        vector = (char **) safe_erealloc(vector, vector_size, sizeof(char *), 0);
                 }                  }
   
                 vector[nfiles] = estrdup(sdp.d_name);                  vector[nfiles] = estrdup(sdp.d_name);
   
                 nfiles++;                  nfiles++;
                   if(vector_size < 10 || nfiles == 0) {
                           /* overflow */
                           php_stream_closedir(stream);
                           efree(vector);
                           return FAILURE;
                   }
         }          }
         php_stream_closedir(stream);          php_stream_closedir(stream);
   
         *namelist = vector;          *namelist = vector;
   
        if (compare) {        if (nfiles > 0 && compare) {
                 qsort(*namelist, nfiles, sizeof(char *), (int(*)(const void *, const void *))compare);                  qsort(*namelist, nfiles, sizeof(char *), (int(*)(const void *, const void *))compare);
         }          }
         return nfiles;          return nfiles;

Removed from v.1.1  
changed lines
  Added in v.1.1.1.4


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>