2001-04-18 01:03:18 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2001-12-11 23:32:16 +08:00
| PHP Version 4 |
2001-04-18 01:03:18 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2002-02-28 16:29:35 +08:00
| Copyright ( c ) 1997 - 2002 The PHP Group |
2001-04-18 01:03:18 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| This source file is subject to version 2.02 of the PHP license , |
| that is bundled with this package in the file LICENSE , and is |
| available at through the world - wide - web at |
| http : //www.php.net/license/2_02.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ php . net so we can mail you a copy immediately . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2002-03-16 05:03:08 +08:00
| Authors : |
| Wez Furlong ( wez @ thebrainroom . com ) |
| Borrowed code from : |
| Rasmus Lerdorf < rasmus @ lerdorf . on . ca > |
| Jim Winstead < jimw @ php . net > |
2001-04-18 01:03:18 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
2002-06-12 02:55:48 +08:00
/* $Id$ */
2001-04-18 01:03:18 +08:00
# define _GNU_SOURCE
# include "php.h"
2002-03-16 05:03:08 +08:00
# include "php_globals.h"
# include "php_network.h"
# include "php_open_temporary_file.h"
2002-03-20 22:21:30 +08:00
# include "ext/standard/file.h"
2002-03-21 09:11:52 +08:00
# include "ext/standard/basic_functions.h" /* for BG(mmap_file) (not strictly required) */
2002-03-16 05:03:08 +08:00
# ifdef HAVE_SYS_MMAN_H
# include <sys/mman.h>
# endif
2002-09-23 23:21:16 +08:00
# include <stddef.h>
2002-08-20 06:59:10 +08:00
# include <fcntl.h>
2002-03-16 05:03:08 +08:00
# ifndef MAP_FAILED
# define MAP_FAILED ((void *) -1)
# endif
2001-04-18 01:03:18 +08:00
2002-03-16 11:50:17 +08:00
# define CHUNK_SIZE 8192
2001-04-18 01:03:18 +08:00
2001-05-06 02:36:22 +08:00
# ifdef PHP_WIN32
# define EWOULDBLOCK WSAEWOULDBLOCK
# else
# include "build-defs.h"
# endif
2002-03-28 08:49:00 +08:00
# define STREAM_DEBUG 0
2002-04-17 06:14:27 +08:00
# define STREAM_WRAPPER_PLAIN_FILES ((php_stream_wrapper*)-1)
2002-03-20 07:29:37 +08:00
/* {{{ some macros to help track leaks */
2002-03-18 06:50:59 +08:00
# if ZEND_DEBUG
# define emalloc_rel_orig(size) \
( __php_stream_call_depth = = 0 \
2002-03-19 02:54:32 +08:00
? _emalloc ( ( size ) ZEND_FILE_LINE_CC ZEND_FILE_LINE_RELAY_CC ) \
2002-03-18 06:50:59 +08:00
: _emalloc ( ( size ) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC ) )
# define erealloc_rel_orig(ptr, size) \
( __php_stream_call_depth = = 0 \
2002-03-19 02:54:32 +08:00
? _erealloc ( ( ptr ) , ( size ) , 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_RELAY_CC ) \
2002-03-18 06:50:59 +08:00
: _erealloc ( ( ptr ) , ( size ) , 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC ) )
# define pemalloc_rel_orig(size, persistent) ((persistent) ? malloc((size)) : emalloc_rel_orig((size)))
# define perealloc_rel_orig(ptr, size, persistent) ((persistent) ? realloc((ptr), (size)) : erealloc_rel_orig((ptr), (size)))
# else
# define pemalloc_rel_orig(size, persistent) pemalloc((size), (persistent))
# define perealloc_rel_orig(ptr, size, persistent) perealloc((ptr), (size), (persistent))
# define emalloc_rel_orig(size) emalloc((size))
# endif
2002-03-20 07:29:37 +08:00
/* }}} */
2002-03-18 06:50:59 +08:00
2002-03-16 05:03:08 +08:00
static HashTable url_stream_wrappers_hash ;
2002-09-25 23:25:12 +08:00
static int le_stream = FAILURE ; /* true global */
static int le_pstream = FAILURE ; /* true global */
PHPAPI int php_file_le_stream ( void )
{
return le_stream ;
}
PHPAPI int php_file_le_pstream ( void )
{
return le_pstream ;
}
static int forget_persistent_resource_id_numbers ( zend_rsrc_list_entry * rsrc TSRMLS_DC )
{
php_stream * stream ;
if ( Z_TYPE_P ( rsrc ) ! = le_pstream )
return 0 ;
stream = ( php_stream * ) rsrc - > ptr ;
# if STREAM_DEBUG
fprintf ( stderr , " forget_persistent: %s:%p \n " , stream - > ops - > label , stream ) ;
# endif
stream - > rsrc_id = FAILURE ;
return 0 ;
}
PHP_RSHUTDOWN_FUNCTION ( streams )
{
zend_hash_apply ( & EG ( persistent_list ) , ( apply_func_t ) forget_persistent_resource_id_numbers TSRMLS_CC ) ;
return SUCCESS ;
}
PHPAPI int php_stream_from_persistent_id ( const char * persistent_id , php_stream * * stream TSRMLS_DC )
{
list_entry * le ;
if ( zend_hash_find ( & EG ( persistent_list ) , ( char * ) persistent_id , strlen ( persistent_id ) + 1 , ( void * ) & le ) = = SUCCESS ) {
if ( Z_TYPE_P ( le ) = = le_pstream ) {
if ( stream ) {
* stream = ( php_stream * ) le - > ptr ;
if ( ( * stream ) - > rsrc_id = = FAILURE ) {
/* first access this request; give it a valid id */
( * stream ) - > rsrc_id = ZEND_REGISTER_RESOURCE ( NULL , * stream , le_pstream ) ;
}
}
return PHP_STREAM_PERSISTENT_SUCCESS ;
}
return PHP_STREAM_PERSISTENT_FAILURE ;
}
return PHP_STREAM_PERSISTENT_NOT_EXIST ;
}
2001-04-18 01:03:18 +08:00
/* allocate a new stream for a particular ops */
2002-09-25 23:25:12 +08:00
PHPAPI php_stream * _php_stream_alloc ( php_stream_ops * ops , void * abstract , const char * persistent_id , const char * mode STREAMS_DC TSRMLS_DC ) /* { { { */
2001-04-18 01:03:18 +08:00
{
2002-03-16 08:05:47 +08:00
php_stream * ret ;
2002-03-18 06:50:59 +08:00
2002-09-25 23:25:12 +08:00
ret = ( php_stream * ) pemalloc_rel_orig ( sizeof ( php_stream ) , persistent_id ? 1 : 0 ) ;
2001-04-18 01:03:18 +08:00
memset ( ret , 0 , sizeof ( php_stream ) ) ;
2002-03-28 08:49:00 +08:00
# if STREAM_DEBUG
2002-09-25 23:25:12 +08:00
fprintf ( stderr , " stream_alloc: %s:%p persistent=%s \n " , ops - > label , ret , persistent_id ) ;
2002-03-28 08:49:00 +08:00
# endif
2001-04-18 01:03:18 +08:00
ret - > ops = ops ;
ret - > abstract = abstract ;
2002-09-25 23:25:12 +08:00
ret - > is_persistent = persistent_id ? 1 : 0 ;
2002-09-23 09:47:04 +08:00
ret - > chunk_size = FG ( def_chunk_size ) ;
2002-09-24 02:12:39 +08:00
if ( FG ( auto_detect_line_endings ) )
ret - > flags | = PHP_STREAM_FLAG_DETECT_EOL ;
2002-09-25 23:25:12 +08:00
if ( persistent_id ) {
list_entry le ;
Z_TYPE ( le ) = le_pstream ;
le . ptr = ret ;
if ( FAILURE = = zend_hash_update ( & EG ( persistent_list ) , ( char * ) persistent_id ,
strlen ( persistent_id ) + 1 ,
( void * ) & le , sizeof ( list_entry ) , NULL ) ) {
pefree ( ret , 1 ) ;
return NULL ;
}
}
2002-09-24 02:12:39 +08:00
2002-09-25 23:25:12 +08:00
ret - > rsrc_id = ZEND_REGISTER_RESOURCE ( NULL , ret , persistent_id ? le_pstream : le_stream ) ;
2002-03-16 08:05:47 +08:00
strlcpy ( ret - > mode , mode , sizeof ( ret - > mode ) ) ;
2002-09-25 23:25:12 +08:00
2001-04-18 01:03:18 +08:00
return ret ;
}
2002-03-16 05:03:08 +08:00
/* }}} */
2001-04-18 01:03:18 +08:00
2002-03-19 02:54:32 +08:00
PHPAPI int _php_stream_free ( php_stream * stream , int close_options TSRMLS_DC ) /* { { { */
2001-04-18 01:03:18 +08:00
{
int ret = 1 ;
2002-03-28 08:49:00 +08:00
# if STREAM_DEBUG
2002-09-25 23:25:12 +08:00
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 ) ;
2002-03-28 08:49:00 +08:00
# endif
2002-03-20 22:21:30 +08:00
if ( stream - > in_free )
return 1 ;
stream - > in_free + + ;
2002-08-25 18:26:58 +08:00
_php_stream_flush ( stream , 1 TSRMLS_CC ) ;
2002-08-21 04:47:47 +08:00
2002-03-20 22:21:30 +08:00
if ( ( close_options & PHP_STREAM_FREE_RSRC_DTOR ) = = 0 ) {
/* Remove entry from the resource list */
zend_list_delete ( stream - > rsrc_id ) ;
}
2002-03-19 02:54:32 +08:00
if ( close_options & PHP_STREAM_FREE_CALL_DTOR ) {
2002-03-16 08:05:47 +08:00
if ( stream - > fclose_stdiocast = = PHP_STREAM_FCLOSE_FOPENCOOKIE ) {
2001-05-06 02:36:22 +08:00
/* calling fclose on an fopencookied stream will ultimately
call this very same function . If we were called via fclose ,
the cookie_closer unsets the fclose_stdiocast flags , so
we can be sure that we only reach here when PHP code calls
php_stream_free .
Lets let the cookie code clean it all up .
*/
2002-03-20 22:21:30 +08:00
stream - > in_free = 0 ;
2001-05-06 02:36:22 +08:00
return fclose ( stream - > stdiocast ) ;
}
2002-03-17 04:05:08 +08:00
2002-03-19 02:54:32 +08:00
ret = stream - > ops - > close ( stream , close_options & PHP_STREAM_FREE_PRESERVE_HANDLE ? 0 : 1 TSRMLS_CC ) ;
stream - > abstract = NULL ;
2002-03-17 04:05:08 +08:00
2001-05-06 02:36:22 +08:00
/* tidy up any FILE* that might have been fdopened */
2002-03-16 08:05:47 +08:00
if ( stream - > fclose_stdiocast = = PHP_STREAM_FCLOSE_FDOPEN & & stream - > stdiocast ) {
2001-05-06 02:36:22 +08:00
fclose ( stream - > stdiocast ) ;
stream - > stdiocast = NULL ;
}
2001-04-18 01:03:18 +08:00
}
2002-03-16 05:03:08 +08:00
2002-03-19 02:54:32 +08:00
if ( close_options & PHP_STREAM_FREE_RELEASE_STREAM ) {
2002-08-21 04:47:47 +08:00
while ( stream - > filterhead ) {
php_stream_filter_remove_head ( stream , 1 ) ;
}
2002-03-19 02:54:32 +08:00
2002-04-17 06:14:27 +08:00
if ( stream - > wrapper & & stream - > wrapper - > wops & & stream - > wrapper - > wops - > stream_closer ) {
stream - > wrapper - > wops - > stream_closer ( stream - > wrapper , stream TSRMLS_CC ) ;
2002-03-19 02:54:32 +08:00
stream - > wrapper = NULL ;
}
if ( stream - > wrapperdata ) {
2002-03-19 21:42:25 +08:00
zval_ptr_dtor ( & stream - > wrapperdata ) ;
2002-03-19 02:54:32 +08:00
stream - > wrapperdata = NULL ;
}
2002-09-23 09:47:04 +08:00
if ( stream - > readbuf ) {
pefree ( stream - > readbuf , stream - > is_persistent ) ;
stream - > readbuf = NULL ;
}
2002-03-20 22:21:30 +08:00
# if ZEND_DEBUG
if ( ( close_options & PHP_STREAM_FREE_RSRC_DTOR ) & & ( stream - > __exposed = = 0 ) & & ( EG ( error_reporting ) & E_WARNING ) ) {
/* it leaked: Lets deliberately NOT pefree it so that the memory manager shows it
* as leaked ; it will log a warning , but lets help it out and display what kind
* of stream it was . */
char leakbuf [ 512 ] ;
2002-08-21 04:47:47 +08:00
snprintf ( leakbuf , sizeof ( leakbuf ) , __FILE__ " (%d) : Stream of type '%s' 0x%08X (path:%s) was not closed \n " , __LINE__ , stream - > ops - > label , ( unsigned int ) stream , stream - > __orig_path ) ;
2002-08-21 06:08:55 +08:00
STR_FREE ( stream - > __orig_path ) ;
2002-03-20 22:21:30 +08:00
# if defined(PHP_WIN32)
OutputDebugString ( leakbuf ) ;
# else
fprintf ( stderr , leakbuf ) ;
# endif
2002-08-21 06:08:55 +08:00
} else {
STR_FREE ( stream - > __orig_path ) ;
pefree ( stream , stream - > is_persistent ) ;
2002-03-20 22:21:30 +08:00
}
2002-08-21 06:08:55 +08:00
# else
2002-03-19 02:54:32 +08:00
pefree ( stream , stream - > is_persistent ) ;
2002-08-21 06:08:55 +08:00
# endif
2002-03-16 05:03:08 +08:00
}
2001-04-18 01:03:18 +08:00
return ret ;
}
2002-03-16 05:03:08 +08:00
/* }}} */
2001-04-18 01:03:18 +08:00
2002-09-23 09:47:04 +08:00
/* {{{ filter API */
2002-08-21 04:47:47 +08:00
static HashTable stream_filters_hash ;
PHPAPI int php_stream_filter_register_factory ( const char * filterpattern , php_stream_filter_factory * factory TSRMLS_DC )
{
return zend_hash_add ( & stream_filters_hash , ( char * ) filterpattern , strlen ( filterpattern ) , factory , sizeof ( * factory ) , NULL ) ;
}
PHPAPI int php_stream_filter_unregister_factory ( const char * filterpattern TSRMLS_DC )
{
return zend_hash_del ( & stream_filters_hash , ( char * ) filterpattern , strlen ( filterpattern ) ) ;
}
/* We allow very simple pattern matching for filter factories:
* if " charset.utf-8/sjis " is requested , we search first for an exact
* match . If that fails , we try " charset.* " .
* This means that we don ' t need to clog up the hashtable with a zillion
* charsets ( for example ) but still be able to provide them all as filters */
PHPAPI php_stream_filter * php_stream_filter_create ( const char * filtername , const char * filterparams , int filterparamslen , int persistent TSRMLS_DC )
{
php_stream_filter_factory * factory ;
php_stream_filter * filter = NULL ;
int n ;
char * period ;
n = strlen ( filtername ) ;
if ( SUCCESS = = zend_hash_find ( & stream_filters_hash , ( char * ) filtername , n , ( void * * ) & factory ) ) {
filter = factory - > create_filter ( filtername , filterparams , filterparamslen , persistent TSRMLS_CC ) ;
} else if ( ( period = strchr ( filtername , ' . ' ) ) ) {
/* try a wildcard */
char wildname [ 128 ] ;
PHP_STRLCPY ( wildname , filtername , sizeof ( wildname ) - 1 , period - filtername + 1 ) ;
strcat ( wildname , " * " ) ;
if ( SUCCESS = = zend_hash_find ( & stream_filters_hash , wildname , strlen ( wildname ) , ( void * * ) & factory ) ) {
filter = factory - > create_filter ( filtername , filterparams , filterparamslen , persistent TSRMLS_CC ) ;
}
}
if ( filter = = NULL ) {
/* TODO: these need correct docrefs */
if ( factory = = NULL )
2002-08-22 18:16:03 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " unable to locate filter \" %s \" " , filtername ) ;
2002-08-21 04:47:47 +08:00
else
2002-08-22 18:16:03 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " unable to create or locate filter \" %s \" " , filtername ) ;
2002-08-21 04:47:47 +08:00
}
return filter ;
}
PHPAPI php_stream_filter * _php_stream_filter_alloc ( php_stream_filter_ops * fops , void * abstract , int persistent STREAMS_DC TSRMLS_DC )
{
php_stream_filter * filter ;
filter = ( php_stream_filter * ) pemalloc_rel_orig ( sizeof ( php_stream_filter ) , persistent ) ;
memset ( filter , 0 , sizeof ( php_stream_filter ) ) ;
filter - > fops = fops ;
filter - > abstract = abstract ;
filter - > is_persistent = persistent ;
return filter ;
}
PHPAPI void php_stream_filter_free ( php_stream_filter * filter TSRMLS_DC )
{
if ( filter - > fops - > dtor )
filter - > fops - > dtor ( filter TSRMLS_CC ) ;
pefree ( filter , filter - > is_persistent ) ;
}
PHPAPI void php_stream_filter_prepend ( php_stream * stream , php_stream_filter * filter )
{
filter - > next = stream - > filterhead ;
filter - > prev = NULL ;
if ( stream - > filterhead ) {
stream - > filterhead - > prev = filter ;
} else {
stream - > filtertail = filter ;
}
stream - > filterhead = filter ;
filter - > stream = stream ;
}
PHPAPI void php_stream_filter_append ( php_stream * stream , php_stream_filter * filter )
{
filter - > prev = stream - > filtertail ;
filter - > next = NULL ;
if ( stream - > filtertail ) {
stream - > filtertail - > next = filter ;
} else {
stream - > filterhead = filter ;
}
stream - > filtertail = filter ;
filter - > stream = stream ;
}
PHPAPI php_stream_filter * php_stream_filter_remove ( php_stream * stream , php_stream_filter * filter , int call_dtor TSRMLS_DC )
{
assert ( stream = = filter - > stream ) ;
if ( filter - > prev ) {
filter - > prev - > next = filter - > next ;
} else {
stream - > filterhead = filter - > next ;
}
if ( filter - > next ) {
filter - > next - > prev = filter - > prev ;
} else {
stream - > filtertail = filter - > prev ;
}
if ( call_dtor ) {
php_stream_filter_free ( filter TSRMLS_CC ) ;
return NULL ;
}
return filter ;
}
2002-09-23 09:47:04 +08:00
/* }}} */
2002-08-21 04:47:47 +08:00
2002-03-16 05:03:08 +08:00
/* {{{ generic stream operations */
2002-09-23 09:47:04 +08:00
static void php_stream_fill_read_buffer ( php_stream * stream , size_t size TSRMLS_DC )
2001-04-18 01:03:18 +08:00
{
2002-09-23 09:47:04 +08:00
/* allocate/fill the buffer */
2002-08-21 04:47:47 +08:00
2002-09-23 09:47:04 +08:00
/* is there enough data in the buffer ? */
2002-09-23 23:21:16 +08:00
while ( stream - > writepos - stream - > readpos < ( off_t ) size ) {
2002-09-23 09:47:04 +08:00
size_t justread ;
/* no; so lets fetch more data */
/* reduce buffer memory consumption if possible, to avoid a realloc */
if ( stream - > readbuflen - stream - > writepos < stream - > chunk_size ) {
memmove ( stream - > readbuf , stream - > readbuf + stream - > readpos , stream - > readbuflen - stream - > readpos ) ;
stream - > writepos - = stream - > readpos ;
stream - > readpos = 0 ;
}
/* grow the buffer if required */
if ( stream - > readbuflen - stream - > writepos < stream - > chunk_size ) {
stream - > readbuflen + = stream - > chunk_size ;
stream - > readbuf = perealloc ( stream - > readbuf , stream - > readbuflen ,
stream - > is_persistent ) ;
}
if ( stream - > filterhead ) {
justread = stream - > filterhead - > fops - > read ( stream , stream - > filterhead ,
stream - > readbuf + stream - > writepos ,
stream - > readbuflen - stream - > writepos
TSRMLS_CC ) ;
} else {
justread = stream - > ops - > read ( stream , stream - > readbuf + stream - > writepos ,
stream - > readbuflen - stream - > writepos
TSRMLS_CC ) ;
}
2002-09-24 07:39:46 +08:00
if ( justread < = 0 )
2002-09-23 09:47:04 +08:00
break ;
stream - > writepos + = justread ;
}
}
PHPAPI size_t _php_stream_read ( php_stream * stream , char * buf , size_t size TSRMLS_DC )
{
2002-09-24 07:39:46 +08:00
size_t toread , didread = 0 ;
2002-09-23 21:22:10 +08:00
/* take from the read buffer first.
* It is possible that a buffered stream was switched to non - buffered , so we
* drain the remainder of the buffer before using the " raw " read mode for
* the excess */
2002-09-24 07:39:46 +08:00
if ( stream - > writepos > stream - > readpos ) {
toread = stream - > writepos - stream - > readpos ;
2002-09-23 21:22:10 +08:00
if ( toread > size )
toread = size ;
memcpy ( buf , stream - > readbuf + stream - > readpos , toread ) ;
stream - > readpos + = toread ;
size - = toread ;
buf + = toread ;
2002-09-24 07:39:46 +08:00
didread + = toread ;
2002-09-23 21:22:10 +08:00
}
if ( size = = 0 )
return didread ;
2002-09-23 09:47:04 +08:00
if ( stream - > flags & PHP_STREAM_FLAG_NO_BUFFER | | stream - > chunk_size = = 1 ) {
2002-09-23 21:22:10 +08:00
if ( stream - > filterhead ) {
didread + = stream - > filterhead - > fops - > read ( stream , stream - > filterhead ,
buf , size
TSRMLS_CC ) ;
} else {
didread + = stream - > ops - > read ( stream , buf , size TSRMLS_CC ) ;
}
2002-09-23 09:47:04 +08:00
} else {
php_stream_fill_read_buffer ( stream , size TSRMLS_CC ) ;
2002-09-23 23:21:16 +08:00
if ( ( off_t ) size > stream - > writepos - stream - > readpos )
2002-09-23 09:47:04 +08:00
size = stream - > writepos - stream - > readpos ;
2002-09-24 07:39:46 +08:00
if ( size ) {
memcpy ( buf , stream - > readbuf + stream - > readpos , size ) ;
stream - > readpos + = size ;
didread + = size ;
}
2002-09-23 09:47:04 +08:00
}
2002-09-23 21:22:10 +08:00
stream - > position + = size ;
return didread ;
2001-04-18 01:03:18 +08:00
}
2002-03-19 02:54:32 +08:00
PHPAPI int _php_stream_eof ( php_stream * stream TSRMLS_DC )
2001-04-18 01:03:18 +08:00
{
2002-09-23 09:47:04 +08:00
/* if there is data in the buffer, it's not EOF */
if ( stream - > writepos - stream - > readpos > 0 )
return 0 ;
2001-05-06 02:36:22 +08:00
/* we define our stream reading function so that it
must return EOF when an EOF condition occurs , when
working in unbuffered mode and called with these args */
2002-08-21 04:47:47 +08:00
if ( stream - > filterhead )
return stream - > filterhead - > fops - > eof ( stream , stream - > filterhead TSRMLS_CC ) ;
return stream - > ops - > read ( stream , NULL , 0 TSRMLS_CC ) = = EOF ? 1 : 0 ;
2001-04-18 01:03:18 +08:00
}
2002-03-19 02:54:32 +08:00
PHPAPI int _php_stream_putc ( php_stream * stream , int c TSRMLS_DC )
2002-03-16 05:03:08 +08:00
{
unsigned char buf = c ;
2002-03-16 08:05:47 +08:00
if ( php_stream_write ( stream , & buf , 1 ) > 0 ) {
2002-03-16 05:03:08 +08:00
return 1 ;
2002-03-16 08:05:47 +08:00
}
2002-03-16 05:03:08 +08:00
return EOF ;
}
2002-03-19 02:54:32 +08:00
PHPAPI int _php_stream_getc ( php_stream * stream TSRMLS_DC )
2001-04-18 01:03:18 +08:00
{
char buf ;
2002-03-16 08:05:47 +08:00
if ( php_stream_read ( stream , & buf , 1 ) > 0 ) {
2002-03-16 10:39:39 +08:00
return buf & 0xff ;
2002-03-16 08:05:47 +08:00
}
2001-04-18 01:03:18 +08:00
return EOF ;
}
2002-03-19 02:54:32 +08:00
PHPAPI int _php_stream_puts ( php_stream * stream , char * buf TSRMLS_DC )
2002-03-16 05:03:08 +08:00
{
int len ;
char newline [ 2 ] = " \n " ; /* is this OK for Win? */
len = strlen ( buf ) ;
2002-03-16 08:05:47 +08:00
if ( len > 0 & & php_stream_write ( stream , buf , len ) & & php_stream_write ( stream , newline , 1 ) ) {
2002-03-16 05:03:08 +08:00
return 1 ;
2002-03-16 08:05:47 +08:00
}
2002-03-16 05:03:08 +08:00
return 0 ;
}
2002-03-28 08:49:00 +08:00
PHPAPI int _php_stream_stat ( php_stream * stream , php_stream_statbuf * ssb TSRMLS_DC )
{
memset ( ssb , 0 , sizeof ( * ssb ) ) ;
/* if the stream was wrapped, allow the wrapper to stat it */
if ( stream - > wrapper & & stream - > wrapper - > wops - > stream_stat ! = NULL ) {
return stream - > wrapper - > wops - > stream_stat ( stream - > wrapper , stream , ssb TSRMLS_CC ) ;
}
/* if the stream doesn't directly support stat-ing, return with failure.
* We could try and emulate this by casting to a FD and fstat - ing it ,
* but since the fd might not represent the actual underlying content
* this would give bogus results . */
if ( stream - > ops - > stat = = NULL ) {
return - 1 ;
}
return stream - > ops - > stat ( stream , ssb TSRMLS_CC ) ;
}
2002-03-19 02:54:32 +08:00
PHPAPI char * _php_stream_gets ( php_stream * stream , char * buf , size_t maxlen TSRMLS_DC )
2001-04-18 01:03:18 +08:00
{
2002-09-23 09:47:04 +08:00
char * cr , * lf , * eol ;
size_t toread = 0 , didread = 0 , justread = 0 , avail = 0 ;
char * readptr ;
2002-08-21 04:47:47 +08:00
if ( maxlen = = 0 )
2002-04-17 06:14:27 +08:00
return NULL ;
2002-09-23 09:47:04 +08:00
while ( didread < maxlen - 1 ) {
toread = maxlen - 1 ;
if ( toread > stream - > chunk_size )
toread = stream - > chunk_size ;
2002-08-21 04:47:47 +08:00
2002-09-23 09:47:04 +08:00
php_stream_fill_read_buffer ( stream , toread TSRMLS_CC ) ;
2001-04-18 01:03:18 +08:00
2002-09-23 09:47:04 +08:00
readptr = stream - > readbuf + stream - > readpos ;
avail = stream - > writepos - stream - > readpos ;
2001-04-18 01:03:18 +08:00
2002-09-23 09:47:04 +08:00
if ( avail = = 0 )
break ;
/* Look for EOL */
if ( stream - > flags & PHP_STREAM_FLAG_DETECT_EOL ) {
cr = memchr ( readptr , ' \r ' , avail ) ;
lf = memchr ( readptr , ' \n ' , avail ) ;
if ( cr & & lf ! = cr + 1 ) {
/* mac */
stream - > flags ^ = PHP_STREAM_FLAG_DETECT_EOL ;
stream - > flags | = PHP_STREAM_FLAG_EOL_MAC ;
eol = cr ;
} else if ( ( cr & & lf & & cr = = lf - 1 ) | | ( lf ) ) {
/* dos or unix endings */
stream - > flags ^ = PHP_STREAM_FLAG_DETECT_EOL ;
eol = lf ;
}
} else if ( stream - > flags & PHP_STREAM_FLAG_EOL_MAC ) {
eol = memchr ( readptr , ' \r ' , avail ) ;
} else {
/* unix (and dos) line endings */
eol = memchr ( readptr , ' \n ' , avail ) ;
}
2002-08-21 04:47:47 +08:00
2002-09-24 02:12:39 +08:00
if ( eol & & ( size_t ) ( ( ptrdiff_t ) eol + 1 - ( ptrdiff_t ) readptr ) < = maxlen - 1 ) {
2002-09-23 09:47:04 +08:00
justread = eol + 1 - readptr ;
} else {
eol = NULL ;
justread = toread ;
if ( justread > avail )
justread = avail ;
}
memcpy ( buf , readptr , justread ) ;
didread + = justread ;
buf + = justread ;
stream - > readpos + = justread ;
2002-08-21 04:47:47 +08:00
2002-09-23 09:47:04 +08:00
if ( eol )
break ;
2001-04-18 01:03:18 +08:00
}
2002-09-23 09:47:04 +08:00
if ( didread = = 0 )
return NULL ;
/* terminate the buffer */
* buf = ' \0 ' ;
stream - > position + = didread ;
2002-09-25 23:25:12 +08:00
2002-09-23 09:47:04 +08:00
return buf ;
2001-04-18 01:03:18 +08:00
}
2002-08-25 18:26:58 +08:00
PHPAPI int _php_stream_flush ( php_stream * stream , int closing TSRMLS_DC )
2001-04-18 01:03:18 +08:00
{
2002-09-23 09:47:04 +08:00
int ret ;
2002-08-21 04:47:47 +08:00
if ( stream - > filterhead )
2002-08-25 18:26:58 +08:00
stream - > filterhead - > fops - > flush ( stream , stream - > filterhead , closing TSRMLS_CC ) ;
2002-09-23 09:47:04 +08:00
2002-03-16 08:05:47 +08:00
if ( stream - > ops - > flush ) {
2002-09-23 09:47:04 +08:00
ret = stream - > ops - > flush ( stream TSRMLS_CC ) ;
2002-03-16 08:05:47 +08:00
}
2002-09-23 09:47:04 +08:00
return ret ;
2001-04-18 01:03:18 +08:00
}
2002-03-19 02:54:32 +08:00
PHPAPI size_t _php_stream_write ( php_stream * stream , const char * buf , size_t count TSRMLS_DC )
2001-04-18 01:03:18 +08:00
{
2002-09-23 09:47:04 +08:00
size_t didwrite ;
2002-03-20 07:29:37 +08:00
assert ( stream ) ;
2002-04-17 06:14:27 +08:00
if ( buf = = NULL | | count = = 0 | | stream - > ops - > write = = NULL )
2002-03-20 07:29:37 +08:00
return 0 ;
2002-08-21 04:47:47 +08:00
if ( stream - > filterhead ) {
2002-09-23 09:47:04 +08:00
didwrite = stream - > filterhead - > fops - > write ( stream , stream - > filterhead , buf , count TSRMLS_CC ) ;
2002-08-21 04:47:47 +08:00
} else {
2002-09-23 09:47:04 +08:00
didwrite = stream - > ops - > write ( stream , buf , count TSRMLS_CC ) ;
2002-08-21 04:47:47 +08:00
}
2002-09-23 09:47:04 +08:00
stream - > position + = didwrite ;
return didwrite ;
2001-04-18 01:03:18 +08:00
}
2002-03-19 02:54:32 +08:00
PHPAPI off_t _php_stream_tell ( php_stream * stream TSRMLS_DC )
2001-04-18 01:03:18 +08:00
{
2002-09-23 09:47:04 +08:00
return stream - > position ;
2001-04-18 01:03:18 +08:00
}
2002-03-19 02:54:32 +08:00
PHPAPI int _php_stream_seek ( php_stream * stream , off_t offset , int whence TSRMLS_DC )
2001-04-18 01:03:18 +08:00
{
2002-09-23 09:47:04 +08:00
/* not moving anywhere */
2002-09-23 21:22:10 +08:00
if ( ( offset = = 0 & & whence = = SEEK_CUR ) | | ( offset = = stream - > position & & whence = = SEEK_SET ) )
2002-09-23 09:47:04 +08:00
return 0 ;
2002-08-21 04:47:47 +08:00
2002-09-23 09:47:04 +08:00
/* handle the case where we are in the buffer */
switch ( whence ) {
case SEEK_CUR :
if ( offset > 0 & & offset < stream - > writepos - stream - > readpos ) {
stream - > readpos + = offset ;
stream - > position + = offset ;
return 0 ;
}
break ;
case SEEK_SET :
if ( offset > stream - > position & &
offset < stream - > position + stream - > writepos - stream - > readpos ) {
stream - > readpos + = offset - stream - > position ;
stream - > position = offset ;
return 0 ;
}
break ;
}
/* invalidate the buffer contents */
stream - > readpos = stream - > writepos = 0 ;
if ( stream - > ops - > seek & & ( stream - > flags & PHP_STREAM_FLAG_NO_SEEK ) = = 0 ) {
2002-09-23 21:22:10 +08:00
int ret ;
2002-08-21 04:47:47 +08:00
if ( stream - > filterhead )
2002-08-25 18:26:58 +08:00
stream - > filterhead - > fops - > flush ( stream , stream - > filterhead , 0 TSRMLS_CC ) ;
2002-08-21 04:47:47 +08:00
2002-09-23 09:47:04 +08:00
switch ( whence ) {
case SEEK_CUR :
offset = stream - > position + offset ;
whence = SEEK_SET ;
break ;
}
2002-09-23 21:22:10 +08:00
ret = stream - > ops - > seek ( stream , offset , whence , & stream - > position TSRMLS_CC ) ;
if ( ( ( stream - > flags & PHP_STREAM_FLAG_NO_SEEK ) = = 0 ) | | ret = = 0 )
return ret ;
/* else the stream has decided that it can't support seeking after all;
* fall through to attempt emulation */
2002-03-16 08:05:47 +08:00
}
2001-04-18 01:03:18 +08:00
2002-03-16 05:03:08 +08:00
/* emulate forward moving seeks with reads */
2002-03-16 08:05:47 +08:00
if ( whence = = SEEK_CUR & & offset > 0 ) {
2002-03-16 10:39:39 +08:00
char tmp [ 1024 ] ;
while ( offset > = sizeof ( tmp ) ) {
if ( php_stream_read ( stream , tmp , sizeof ( tmp ) ) = = 0 )
return - 1 ;
offset - = sizeof ( tmp ) ;
}
if ( offset ) {
if ( php_stream_read ( stream , tmp , offset ) = = 0 )
2002-03-16 05:03:08 +08:00
return - 1 ;
2002-03-16 08:05:47 +08:00
}
2002-03-16 05:03:08 +08:00
return 0 ;
}
2002-03-17 04:05:08 +08:00
2002-09-23 21:22:10 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " stream does not support seeking " ) ;
2002-09-23 09:47:04 +08:00
2001-04-18 01:03:18 +08:00
return - 1 ;
}
2002-08-20 06:59:10 +08:00
PHPAPI int _php_stream_set_option ( php_stream * stream , int option , int value , void * ptrparam TSRMLS_DC )
{
2002-09-23 21:22:10 +08:00
int ret = PHP_STREAM_OPTION_RETURN_NOTIMPL ;
if ( stream - > ops - > set_option ) {
ret = stream - > ops - > set_option ( stream , option , value , ptrparam TSRMLS_CC ) ;
}
if ( ret = = PHP_STREAM_OPTION_RETURN_NOTIMPL ) {
switch ( option ) {
case PHP_STREAM_OPTION_BUFFER :
/* try to match the buffer mode as best we can */
if ( value = = PHP_STREAM_BUFFER_NONE ) {
stream - > flags | = PHP_STREAM_FLAG_NO_BUFFER ;
} else {
stream - > flags ^ = PHP_STREAM_FLAG_NO_BUFFER ;
}
ret = PHP_STREAM_OPTION_RETURN_OK ;
break ;
default :
ret = PHP_STREAM_OPTION_RETURN_ERR ;
}
}
return ret ;
2002-08-20 06:59:10 +08:00
}
2002-03-21 09:11:52 +08:00
PHPAPI size_t _php_stream_passthru ( php_stream * stream STREAMS_DC TSRMLS_DC )
{
size_t bcount = 0 ;
int ready = 0 ;
char buf [ 8192 ] ;
# ifdef HAVE_MMAP
int fd ;
# endif
# ifdef HAVE_MMAP
if ( ! php_stream_is ( stream , PHP_STREAM_IS_SOCKET )
2002-08-21 04:47:47 +08:00
& & stream - > filterhead = = NULL
2002-03-22 06:35:02 +08:00
& & SUCCESS = = php_stream_cast ( stream , PHP_STREAM_AS_FD , ( void * ) & fd , 0 ) )
2002-03-21 09:11:52 +08:00
{
struct stat sbuf ;
off_t off ;
void * p ;
size_t len ;
fstat ( fd , & sbuf ) ;
if ( sbuf . st_size > sizeof ( buf ) ) {
off = php_stream_tell ( stream ) ;
len = sbuf . st_size - off ;
p = mmap ( 0 , len , PROT_READ , MAP_SHARED , fd , off ) ;
if ( p ! = ( void * ) MAP_FAILED ) {
BG ( mmap_file ) = p ;
BG ( mmap_len ) = len ;
PHPWRITE ( p , len ) ;
BG ( mmap_file ) = NULL ;
munmap ( p , len ) ;
bcount + = len ;
ready = 1 ;
}
}
}
# endif
if ( ! ready ) {
int b ;
while ( ( b = php_stream_read ( stream , buf , sizeof ( buf ) ) ) > 0 ) {
PHPWRITE ( buf , b ) ;
bcount + = b ;
}
}
return bcount ;
}
2002-03-19 02:54:32 +08:00
PHPAPI size_t _php_stream_copy_to_mem ( php_stream * src , char * * buf , size_t maxlen , int persistent STREAMS_DC TSRMLS_DC )
2002-03-16 05:03:08 +08:00
{
size_t ret = 0 ;
2002-03-16 09:58:13 +08:00
char * ptr ;
2002-03-16 05:03:08 +08:00
size_t len = 0 , max_len ;
int step = CHUNK_SIZE ;
int min_room = CHUNK_SIZE / 4 ;
# if HAVE_MMAP
int srcfd ;
# endif
2002-03-16 21:48:57 +08:00
if ( buf )
* buf = NULL ;
2002-03-17 04:05:08 +08:00
2002-03-16 21:48:57 +08:00
if ( maxlen = = 0 )
return 0 ;
if ( maxlen = = PHP_STREAM_COPY_ALL )
maxlen = 0 ;
2002-03-16 05:03:08 +08:00
# if HAVE_MMAP
/* try and optimize the case where we are copying from the start of a plain file.
* We could probably make this work in more situations , but I don ' t trust the stdio
* buffering layer .
* */
if ( php_stream_is ( src , PHP_STREAM_IS_STDIO ) & &
2002-08-21 04:47:47 +08:00
src - > filterhead = = NULL & &
2002-03-17 04:05:08 +08:00
php_stream_tell ( src ) = = 0 & &
2002-03-16 05:03:08 +08:00
SUCCESS = = php_stream_cast ( src , PHP_STREAM_AS_FD , ( void * * ) & srcfd , 0 ) )
{
struct stat sbuf ;
2002-03-16 08:05:47 +08:00
if ( fstat ( srcfd , & sbuf ) = = 0 ) {
2002-03-16 09:58:13 +08:00
void * srcfile ;
2002-03-16 21:48:57 +08:00
2002-03-28 08:49:00 +08:00
# if STREAM_DEBUG
2002-09-25 23:25:12 +08:00
fprintf ( stderr , " mmap attempt: maxlen=%d filesize=%ld \n " , maxlen , sbuf . st_size ) ;
2002-03-28 08:49:00 +08:00
# endif
2002-03-16 21:48:57 +08:00
if ( maxlen > sbuf . st_size | | maxlen = = 0 )
maxlen = sbuf . st_size ;
2002-03-28 08:49:00 +08:00
# if STREAM_DEBUG
fprintf ( stderr , " mmap attempt: will map maxlen=%d \n " , maxlen ) ;
# endif
2002-03-16 21:48:57 +08:00
srcfile = mmap ( NULL , maxlen , PROT_READ , MAP_SHARED , srcfd , 0 ) ;
2002-03-16 08:05:47 +08:00
if ( srcfile ! = ( void * ) MAP_FAILED ) {
2002-03-16 05:03:08 +08:00
2002-03-28 08:49:00 +08:00
* buf = pemalloc_rel_orig ( maxlen + 1 , persistent ) ;
2002-03-16 05:03:08 +08:00
if ( * buf ) {
2002-03-16 21:48:57 +08:00
memcpy ( * buf , srcfile , maxlen ) ;
2002-03-28 08:49:00 +08:00
( * buf ) [ maxlen ] = ' \0 ' ;
2002-03-16 21:48:57 +08:00
ret = maxlen ;
2002-03-16 05:03:08 +08:00
}
2002-03-17 04:05:08 +08:00
2002-03-16 21:48:57 +08:00
munmap ( srcfile , maxlen ) ;
2002-03-28 08:49:00 +08:00
2002-03-16 05:03:08 +08:00
return ret ;
}
}
/* fall through - we might be able to copy in smaller chunks */
}
# endif
2002-03-17 04:05:08 +08:00
2002-03-28 08:49:00 +08:00
ptr = * buf = pemalloc_rel_orig ( step , persistent ) ;
2002-03-16 05:03:08 +08:00
max_len = step ;
while ( ( ret = php_stream_read ( src , ptr , max_len - len ) ) ) {
len + = ret ;
2002-03-16 08:05:47 +08:00
if ( len + min_room > = max_len ) {
2002-03-18 06:50:59 +08:00
* buf = perealloc_rel_orig ( * buf , max_len + step , persistent ) ;
2002-03-16 05:03:08 +08:00
max_len + = step ;
ptr = * buf + len ;
}
}
2002-03-16 08:05:47 +08:00
if ( len ) {
2002-06-12 02:54:57 +08:00
* buf = perealloc_rel_orig ( * buf , len + 1 , persistent ) ;
( * buf ) [ len ] = ' \0 ' ;
2002-03-16 08:05:47 +08:00
} else {
2002-03-16 05:03:08 +08:00
pefree ( * buf , persistent ) ;
* buf = NULL ;
}
return len ;
}
2002-03-19 02:54:32 +08:00
PHPAPI size_t _php_stream_copy_to_stream ( php_stream * src , php_stream * dest , size_t maxlen STREAMS_DC TSRMLS_DC )
2002-03-16 05:03:08 +08:00
{
char buf [ CHUNK_SIZE ] ;
size_t readchunk ;
size_t haveread = 0 ;
size_t didread ;
# if HAVE_MMAP
int srcfd ;
# endif
2002-03-16 10:48:35 +08:00
if ( maxlen = = 0 )
return 0 ;
if ( maxlen = = PHP_STREAM_COPY_ALL )
maxlen = 0 ;
2002-03-17 04:05:08 +08:00
2002-03-16 05:03:08 +08:00
# if HAVE_MMAP
/* try and optimize the case where we are copying from the start of a plain file.
* We could probably make this work in more situations , but I don ' t trust the stdio
* buffering layer .
* */
if ( php_stream_is ( src , PHP_STREAM_IS_STDIO ) & &
2002-08-21 04:47:47 +08:00
src - > filterhead = = NULL & &
2002-03-17 04:05:08 +08:00
php_stream_tell ( src ) = = 0 & &
2002-03-16 05:03:08 +08:00
SUCCESS = = php_stream_cast ( src , PHP_STREAM_AS_FD , ( void * * ) & srcfd , 0 ) )
{
struct stat sbuf ;
2002-03-16 08:05:47 +08:00
if ( fstat ( srcfd , & sbuf ) = = 0 ) {
2002-03-16 09:58:13 +08:00
void * srcfile ;
2002-03-17 04:05:08 +08:00
2002-08-09 08:33:06 +08:00
/* in the event that the source file is 0 bytes, return 1 to indicate success
* because opening the file to write had already created a copy */
if ( sbuf . st_size = = 0 )
return 1 ;
2002-03-16 10:48:35 +08:00
if ( maxlen > sbuf . st_size | | maxlen = = 0 )
maxlen = sbuf . st_size ;
2002-03-17 04:05:08 +08:00
2002-03-16 10:48:35 +08:00
srcfile = mmap ( NULL , maxlen , PROT_READ , MAP_SHARED , srcfd , 0 ) ;
2002-03-16 08:05:47 +08:00
if ( srcfile ! = ( void * ) MAP_FAILED ) {
2002-03-16 10:48:35 +08:00
haveread = php_stream_write ( dest , srcfile , maxlen ) ;
munmap ( srcfile , maxlen ) ;
2002-03-16 05:03:08 +08:00
return haveread ;
}
}
/* fall through - we might be able to copy in smaller chunks */
}
# endif
2002-03-17 04:05:08 +08:00
2002-03-16 08:05:47 +08:00
while ( 1 ) {
2002-03-16 05:03:08 +08:00
readchunk = sizeof ( buf ) ;
if ( maxlen & & ( maxlen - haveread ) < readchunk )
readchunk = maxlen - haveread ;
didread = php_stream_read ( src , buf , readchunk ) ;
2002-03-20 07:29:37 +08:00
2002-03-16 08:05:47 +08:00
if ( didread ) {
2002-03-16 05:03:08 +08:00
/* extra paranoid */
size_t didwrite , towrite ;
2002-03-16 08:05:47 +08:00
char * writeptr ;
2002-03-16 05:03:08 +08:00
towrite = didread ;
writeptr = buf ;
haveread + = didread ;
2002-03-17 04:05:08 +08:00
2002-03-16 08:05:47 +08:00
while ( towrite ) {
2002-03-16 05:03:08 +08:00
didwrite = php_stream_write ( dest , writeptr , towrite ) ;
if ( didwrite = = 0 )
return 0 ; /* error */
2002-03-17 04:05:08 +08:00
2002-03-16 05:03:08 +08:00
towrite - = didwrite ;
writeptr + = didwrite ;
}
2002-03-16 08:05:47 +08:00
} else {
2002-03-20 07:29:37 +08:00
if ( maxlen = = 0 ) {
2002-03-17 04:05:08 +08:00
return haveread ;
} else {
return 0 ; /* error */
}
2002-03-16 08:05:47 +08:00
}
2002-03-16 05:03:08 +08:00
2002-03-16 08:05:47 +08:00
if ( maxlen - haveread = = 0 ) {
2002-03-16 05:03:08 +08:00
break ;
2002-03-16 08:05:47 +08:00
}
2002-03-16 05:03:08 +08:00
}
return haveread ;
2002-03-17 04:05:08 +08:00
2002-03-16 05:03:08 +08:00
}
/* }}} */
/* {{{ ------- STDIO stream implementation -------*/
typedef struct {
2002-03-16 09:58:13 +08:00
FILE * file ;
2002-08-25 19:23:19 +08:00
int is_process_pipe ; /* use pclose instead of fclose */
int is_pipe ; /* don't try and seek */
2002-03-16 05:03:08 +08:00
# if HAVE_FLUSHIO
char last_op ;
# endif
} php_stdio_stream_data ;
2002-03-19 02:54:32 +08:00
PHPAPI php_stream * _php_stream_fopen_temporary_file ( const char * dir , const char * pfx , char * * opened_path STREAMS_DC TSRMLS_DC )
2002-03-16 05:03:08 +08:00
{
2002-03-16 11:30:19 +08:00
FILE * fp = php_open_temporary_file ( dir , pfx , opened_path TSRMLS_CC ) ;
2002-03-16 05:03:08 +08:00
if ( fp ) {
2002-03-18 06:50:59 +08:00
php_stream * stream = php_stream_fopen_from_file_rel ( fp , " wb " ) ;
2002-03-16 08:05:47 +08:00
if ( stream ) {
2002-03-16 05:03:08 +08:00
return stream ;
2002-03-16 08:05:47 +08:00
}
2002-03-16 05:03:08 +08:00
fclose ( fp ) ;
2002-08-25 18:36:08 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " unable to allocate stream " ) ;
2002-03-17 04:05:08 +08:00
2002-03-16 05:03:08 +08:00
return NULL ;
}
return NULL ;
}
2002-03-19 03:47:50 +08:00
PHPAPI php_stream * _php_stream_fopen_tmpfile ( int dummy STREAMS_DC TSRMLS_DC )
2002-03-16 05:03:08 +08:00
{
2002-03-16 08:05:47 +08:00
FILE * fp ;
php_stream * stream ;
2002-03-17 04:05:08 +08:00
2002-03-16 05:03:08 +08:00
fp = tmpfile ( ) ;
if ( fp = = NULL ) {
2002-08-25 18:36:08 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " tmpfile(): %s " , strerror ( errno ) ) ;
2002-03-16 05:03:08 +08:00
return NULL ;
}
2002-03-18 06:50:59 +08:00
stream = php_stream_fopen_from_file_rel ( fp , " r+ " ) ;
2002-03-16 05:03:08 +08:00
if ( stream = = NULL ) {
2002-08-25 18:36:08 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " tmpfile(): %s " , strerror ( errno ) ) ;
2002-03-16 05:03:08 +08:00
fclose ( fp ) ;
return NULL ;
}
return stream ;
}
2001-04-18 01:03:18 +08:00
2002-03-16 05:03:08 +08:00
2002-03-19 02:54:32 +08:00
PHPAPI php_stream * _php_stream_fopen_from_file ( FILE * file , const char * mode STREAMS_DC TSRMLS_DC )
2002-03-16 05:03:08 +08:00
{
2002-03-16 08:05:47 +08:00
php_stdio_stream_data * self ;
2002-08-25 19:23:19 +08:00
# ifdef S_ISFIFO
int fd ;
# endif
2002-03-18 06:50:59 +08:00
self = emalloc_rel_orig ( sizeof ( * self ) ) ;
2002-03-16 05:03:08 +08:00
self - > file = file ;
self - > is_pipe = 0 ;
2002-08-25 19:23:19 +08:00
self - > is_process_pipe = 0 ;
# ifdef S_ISFIFO
/* detect if this is a pipe */
fd = fileno ( file ) ;
if ( fd > = 0 ) {
struct stat sb ;
self - > is_pipe = ( fstat ( fd , & sb ) = = 0 & & S_ISFIFO ( sb . st_mode ) ) ? 1 : 0 ;
}
# endif
2002-03-18 06:50:59 +08:00
return php_stream_alloc_rel ( & php_stream_stdio_ops , self , 0 , mode ) ;
2002-03-16 05:03:08 +08:00
}
2002-03-19 02:54:32 +08:00
PHPAPI php_stream * _php_stream_fopen_from_pipe ( FILE * file , const char * mode STREAMS_DC TSRMLS_DC )
2002-03-16 05:03:08 +08:00
{
2002-03-16 08:05:47 +08:00
php_stdio_stream_data * self ;
2002-03-16 05:03:08 +08:00
2002-03-18 06:50:59 +08:00
self = emalloc_rel_orig ( sizeof ( * self ) ) ;
2002-03-16 05:03:08 +08:00
self - > file = file ;
self - > is_pipe = 1 ;
2002-08-25 19:23:19 +08:00
self - > is_process_pipe = 1 ;
2002-03-18 06:50:59 +08:00
return php_stream_alloc_rel ( & php_stream_stdio_ops , self , 0 , mode ) ;
2002-03-16 05:03:08 +08:00
}
2002-08-25 19:23:19 +08:00
2002-03-19 02:54:32 +08:00
static size_t php_stdiop_write ( php_stream * stream , const char * buf , size_t count TSRMLS_DC )
2001-04-18 01:03:18 +08:00
{
2002-03-16 09:58:13 +08:00
php_stdio_stream_data * data = ( php_stdio_stream_data * ) stream - > abstract ;
2002-03-16 05:03:08 +08:00
2002-03-16 19:24:12 +08:00
assert ( data ! = NULL ) ;
2002-03-17 04:05:08 +08:00
2002-03-16 05:03:08 +08:00
# if HAVE_FLUSHIO
2002-08-25 19:02:05 +08:00
if ( ! data - > is_pipe & & data - > last_op = = ' r ' ) {
2002-03-16 05:03:08 +08:00
fseek ( data - > file , 0 , SEEK_CUR ) ;
2002-03-16 08:05:47 +08:00
}
2002-03-16 05:03:08 +08:00
data - > last_op = ' w ' ;
# endif
return fwrite ( buf , 1 , count , data - > file ) ;
2001-04-18 01:03:18 +08:00
}
2002-03-19 02:54:32 +08:00
static size_t php_stdiop_read ( php_stream * stream , char * buf , size_t count TSRMLS_DC )
2001-04-18 01:03:18 +08:00
{
2002-03-16 09:58:13 +08:00
php_stdio_stream_data * data = ( php_stdio_stream_data * ) stream - > abstract ;
2002-03-16 05:03:08 +08:00
2002-03-16 19:24:12 +08:00
assert ( data ! = NULL ) ;
2002-03-17 04:05:08 +08:00
2001-04-18 01:03:18 +08:00
if ( buf = = NULL & & count = = 0 ) {
/* check for EOF condition */
2002-03-16 05:03:08 +08:00
if ( feof ( data - > file ) ) {
2001-04-18 01:03:18 +08:00
return EOF ;
}
return 0 ;
}
2002-03-16 05:03:08 +08:00
# if HAVE_FLUSHIO
2002-08-25 19:02:05 +08:00
if ( ! data - > is_pipe & & data - > last_op = = ' w ' )
2002-03-16 05:03:08 +08:00
fseek ( data - > file , 0 , SEEK_CUR ) ;
data - > last_op = ' r ' ;
# endif
2002-03-17 04:05:08 +08:00
2002-03-16 05:03:08 +08:00
return fread ( buf , 1 , count , data - > file ) ;
2001-04-18 01:03:18 +08:00
}
2002-03-19 02:54:32 +08:00
static int php_stdiop_close ( php_stream * stream , int close_handle TSRMLS_DC )
2001-04-18 01:03:18 +08:00
{
2002-03-16 05:03:08 +08:00
int ret ;
2002-03-16 08:05:47 +08:00
php_stdio_stream_data * data = ( php_stdio_stream_data * ) stream - > abstract ;
2002-03-16 05:03:08 +08:00
2002-03-16 19:24:12 +08:00
assert ( data ! = NULL ) ;
2002-03-16 22:39:51 +08:00
if ( close_handle ) {
2002-08-25 19:23:19 +08:00
if ( data - > is_process_pipe ) {
2002-03-16 22:39:51 +08:00
ret = pclose ( data - > file ) ;
} else {
ret = fclose ( data - > file ) ;
}
2002-03-17 02:16:55 +08:00
} else {
2002-03-16 22:39:51 +08:00
ret = 0 ;
2002-03-17 02:16:55 +08:00
}
2002-03-16 05:03:08 +08:00
2002-03-19 02:54:32 +08:00
/* STDIO streams are never persistent! */
2002-03-16 05:03:08 +08:00
efree ( data ) ;
2002-03-17 04:05:08 +08:00
2002-03-16 05:03:08 +08:00
return ret ;
2001-04-18 01:03:18 +08:00
}
2002-03-19 02:54:32 +08:00
static int php_stdiop_flush ( php_stream * stream TSRMLS_DC )
2001-04-18 01:03:18 +08:00
{
2002-03-16 19:24:12 +08:00
php_stdio_stream_data * data = ( php_stdio_stream_data * ) stream - > abstract ;
assert ( data ! = NULL ) ;
2002-03-17 04:05:08 +08:00
2002-03-16 19:24:12 +08:00
return fflush ( data - > file ) ;
2001-04-18 01:03:18 +08:00
}
2002-09-23 09:47:04 +08:00
static int php_stdiop_seek ( php_stream * stream , off_t offset , int whence , off_t * newoffset TSRMLS_DC )
2001-04-18 01:03:18 +08:00
{
2002-03-16 19:24:12 +08:00
php_stdio_stream_data * data = ( php_stdio_stream_data * ) stream - > abstract ;
2002-09-23 09:47:04 +08:00
int ret ;
2002-03-16 19:24:12 +08:00
assert ( data ! = NULL ) ;
2002-08-25 19:23:19 +08:00
if ( data - > is_pipe ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " cannot seek on a pipe " ) ;
return - 1 ;
}
2002-09-23 09:47:04 +08:00
ret = fseek ( data - > file , offset , whence ) ;
* newoffset = ftell ( data - > file ) ;
return ret ;
2001-04-18 01:03:18 +08:00
}
2002-03-19 02:54:32 +08:00
static int php_stdiop_cast ( php_stream * stream , int castas , void * * ret TSRMLS_DC )
2001-04-18 01:03:18 +08:00
{
int fd ;
2002-03-16 08:05:47 +08:00
php_stdio_stream_data * data = ( php_stdio_stream_data * ) stream - > abstract ;
2002-03-17 04:05:08 +08:00
2002-03-16 19:24:12 +08:00
assert ( data ! = NULL ) ;
2001-04-18 01:03:18 +08:00
switch ( castas ) {
case PHP_STREAM_AS_STDIO :
2002-03-16 08:05:47 +08:00
if ( ret ) {
2002-03-16 05:03:08 +08:00
* ret = data - > file ;
2002-03-16 08:05:47 +08:00
}
2001-04-18 01:03:18 +08:00
return SUCCESS ;
case PHP_STREAM_AS_FD :
2002-03-16 05:03:08 +08:00
fd = fileno ( data - > file ) ;
2002-03-16 08:05:47 +08:00
if ( fd < 0 ) {
2001-04-18 01:03:18 +08:00
return FAILURE ;
2002-03-16 08:05:47 +08:00
}
if ( ret ) {
2002-04-03 00:46:33 +08:00
fflush ( data - > file ) ;
2001-04-18 01:03:18 +08:00
* ret = ( void * ) fd ;
2002-03-16 08:05:47 +08:00
}
2001-04-18 01:03:18 +08:00
return SUCCESS ;
default :
return FAILURE ;
}
}
2002-03-28 08:49:00 +08:00
static int php_stdiop_stat ( php_stream * stream , php_stream_statbuf * ssb TSRMLS_DC )
{
int fd ;
php_stdio_stream_data * data = ( php_stdio_stream_data * ) stream - > abstract ;
assert ( data ! = NULL ) ;
fd = fileno ( data - > file ) ;
return fstat ( fd , & ssb - > sb ) ;
}
2002-08-20 06:59:10 +08:00
static int php_stdiop_set_option ( php_stream * stream , int option , int value , void * ptrparam TSRMLS_DC )
{
php_stdio_stream_data * data = ( php_stdio_stream_data * ) stream - > abstract ;
size_t size ;
int fd ;
2002-08-23 01:42:18 +08:00
# ifdef O_NONBLOCK
/* FIXME: make this work for win32 */
2002-08-20 06:59:10 +08:00
int flags ;
int oldval ;
2002-08-23 01:42:18 +08:00
# endif
2002-08-20 06:59:10 +08:00
switch ( option ) {
case PHP_STREAM_OPTION_BLOCKING :
fd = fileno ( data - > file ) ;
if ( fd = = - 1 )
return - 1 ;
# ifdef O_NONBLOCK
flags = fcntl ( fd , F_GETFL , 0 ) ;
oldval = ( flags & O_NONBLOCK ) ? 0 : 1 ;
if ( value )
flags ^ = O_NONBLOCK ;
else
flags | = O_NONBLOCK ;
if ( - 1 = = fcntl ( fd , F_SETFL , flags ) )
return - 1 ;
return oldval ;
# else
return - 1 ; /* not yet implemented */
# endif
case PHP_STREAM_OPTION_BUFFER :
if ( ptrparam )
size = * ( size_t * ) ptrparam ;
else
size = BUFSIZ ;
switch ( value ) {
case PHP_STREAM_BUFFER_NONE :
2002-09-23 21:22:10 +08:00
stream - > flags | = PHP_STREAM_FLAG_NO_BUFFER ;
2002-08-20 06:59:10 +08:00
return setvbuf ( data - > file , NULL , _IONBF , 0 ) ;
case PHP_STREAM_BUFFER_LINE :
2002-09-23 21:22:10 +08:00
stream - > flags ^ = PHP_STREAM_FLAG_NO_BUFFER ;
2002-08-20 06:59:10 +08:00
return setvbuf ( data - > file , NULL , _IOLBF , size ) ;
case PHP_STREAM_BUFFER_FULL :
2002-09-23 21:22:10 +08:00
stream - > flags ^ = PHP_STREAM_FLAG_NO_BUFFER ;
2002-08-20 06:59:10 +08:00
return setvbuf ( data - > file , NULL , _IOFBF , size ) ;
default :
return - 1 ;
}
break ;
default :
return - 1 ;
}
}
2002-04-16 06:22:53 +08:00
PHPAPI php_stream_ops php_stream_stdio_ops = {
2001-04-18 01:03:18 +08:00
php_stdiop_write , php_stdiop_read ,
2002-03-28 08:49:00 +08:00
php_stdiop_close , php_stdiop_flush ,
" STDIO " ,
php_stdiop_seek ,
2002-09-23 09:47:04 +08:00
php_stdiop_cast ,
2002-08-20 06:59:10 +08:00
php_stdiop_stat ,
php_stdiop_set_option
2001-04-18 01:03:18 +08:00
} ;
2002-03-20 22:21:30 +08:00
/* }}} */
2001-04-18 01:03:18 +08:00
2002-03-20 22:21:30 +08:00
/* {{{ php_stream_fopen_with_path */
PHPAPI php_stream * _php_stream_fopen_with_path ( char * filename , char * mode , char * path , char * * opened_path STREAMS_DC TSRMLS_DC )
2002-03-16 05:03:08 +08:00
{
/* code ripped off from fopen_wrappers.c */
char * pathbuf , * ptr , * end ;
char * exec_fname ;
char trypath [ MAXPATHLEN ] ;
struct stat sb ;
php_stream * stream ;
int path_length ;
int filename_length ;
int exec_fname_length ;
if ( opened_path ) {
* opened_path = NULL ;
}
if ( ! filename ) {
return NULL ;
}
filename_length = strlen ( filename ) ;
/* Relative path open */
if ( * filename = = ' . ' ) {
2002-08-25 20:10:17 +08:00
if ( php_check_open_basedir ( filename TSRMLS_CC ) ) {
return NULL ;
}
2002-03-16 05:03:08 +08:00
if ( PG ( safe_mode ) & & ( ! php_checkuid ( filename , mode , CHECKUID_CHECK_MODE_PARAM ) ) ) {
return NULL ;
}
2002-03-18 17:12:31 +08:00
return php_stream_fopen_rel ( filename , mode , opened_path ) ;
2002-03-16 05:03:08 +08:00
}
/*
* files in safe_mode_include_dir ( or subdir ) are excluded from
* safe mode GID / UID checks
*/
/* Absolute path open */
if ( IS_ABSOLUTE_PATH ( filename , filename_length ) ) {
2002-08-25 20:10:17 +08:00
if ( php_check_open_basedir ( filename TSRMLS_CC ) ) {
return NULL ;
}
2002-03-16 05:03:08 +08:00
if ( ( php_check_safe_mode_include_dir ( filename TSRMLS_CC ) ) = = 0 )
/* filename is in safe_mode_include_dir (or subdir) */
2002-03-18 06:50:59 +08:00
return php_stream_fopen_rel ( filename , mode , opened_path ) ;
2002-03-16 05:03:08 +08:00
if ( PG ( safe_mode ) & & ( ! php_checkuid ( filename , mode , CHECKUID_CHECK_MODE_PARAM ) ) )
return NULL ;
2002-03-18 06:50:59 +08:00
return php_stream_fopen_rel ( filename , mode , opened_path ) ;
2002-03-16 05:03:08 +08:00
}
if ( ! path | | ( path & & ! * path ) ) {
2002-08-25 20:10:17 +08:00
if ( php_check_open_basedir ( path TSRMLS_CC ) ) {
return NULL ;
}
2002-03-16 05:03:08 +08:00
if ( PG ( safe_mode ) & & ( ! php_checkuid ( filename , mode , CHECKUID_CHECK_MODE_PARAM ) ) ) {
return NULL ;
}
2002-03-18 06:50:59 +08:00
return php_stream_fopen_rel ( filename , mode , opened_path ) ;
2002-03-16 05:03:08 +08:00
}
/* check in provided path */
/* append the calling scripts' current working directory
* as a fall back case
*/
if ( zend_is_executing ( TSRMLS_C ) ) {
exec_fname = zend_get_executed_filename ( TSRMLS_C ) ;
exec_fname_length = strlen ( exec_fname ) ;
path_length = strlen ( path ) ;
while ( ( - - exec_fname_length > = 0 ) & & ! IS_SLASH ( exec_fname [ exec_fname_length ] ) ) ;
if ( ( exec_fname & & exec_fname [ 0 ] = = ' [ ' )
| | exec_fname_length < = 0 ) {
/* [no active file] or no path */
pathbuf = estrdup ( path ) ;
2002-03-17 04:05:08 +08:00
} else {
2002-03-16 05:03:08 +08:00
pathbuf = ( char * ) emalloc ( exec_fname_length + path_length + 1 + 1 ) ;
memcpy ( pathbuf , path , path_length ) ;
pathbuf [ path_length ] = DEFAULT_DIR_SEPARATOR ;
memcpy ( pathbuf + path_length + 1 , exec_fname , exec_fname_length ) ;
pathbuf [ path_length + exec_fname_length + 1 ] = ' \0 ' ;
}
} else {
pathbuf = estrdup ( path ) ;
}
ptr = pathbuf ;
while ( ptr & & * ptr ) {
end = strchr ( ptr , DEFAULT_DIR_SEPARATOR ) ;
if ( end ! = NULL ) {
* end = ' \0 ' ;
end + + ;
}
snprintf ( trypath , MAXPATHLEN , " %s/%s " , ptr , filename ) ;
if ( PG ( safe_mode ) ) {
if ( VCWD_STAT ( trypath , & sb ) = = 0 ) {
/* file exists ... check permission */
2002-08-25 20:10:17 +08:00
if ( php_check_open_basedir ( trypath TSRMLS_CC ) ) {
stream = NULL ;
} else if ( ( php_check_safe_mode_include_dir ( trypath TSRMLS_CC ) = = 0 ) | |
2002-03-17 02:16:55 +08:00
php_checkuid ( trypath , mode , CHECKUID_CHECK_MODE_PARAM ) ) {
2002-03-16 05:03:08 +08:00
/* UID ok, or trypath is in safe_mode_include_dir */
2002-03-18 06:50:59 +08:00
stream = php_stream_fopen_rel ( trypath , mode , opened_path ) ;
2002-03-17 02:16:55 +08:00
} else {
2002-03-16 05:03:08 +08:00
stream = NULL ;
2002-03-17 02:16:55 +08:00
}
2002-03-16 05:03:08 +08:00
efree ( pathbuf ) ;
return stream ;
}
}
2002-03-18 06:50:59 +08:00
stream = php_stream_fopen_rel ( trypath , mode , opened_path ) ;
2002-03-16 05:03:08 +08:00
if ( stream ) {
efree ( pathbuf ) ;
return stream ;
}
ptr = end ;
} /* end provided path */
efree ( pathbuf ) ;
return NULL ;
}
/* }}} */
2002-03-20 22:21:30 +08:00
/* {{{ php_stream_fopen */
2002-03-19 02:54:32 +08:00
PHPAPI php_stream * _php_stream_fopen ( const char * filename , const char * mode , char * * opened_path STREAMS_DC TSRMLS_DC )
2001-04-18 01:03:18 +08:00
{
2002-03-16 08:05:47 +08:00
FILE * fp ;
2002-03-16 11:30:19 +08:00
char * realpath = NULL ;
2002-03-16 08:05:47 +08:00
2002-03-16 11:30:19 +08:00
realpath = expand_filepath ( filename , NULL TSRMLS_CC ) ;
2002-03-17 04:05:08 +08:00
2002-03-16 05:03:08 +08:00
fp = fopen ( realpath , mode ) ;
2001-04-18 01:03:18 +08:00
if ( fp ) {
2002-03-18 06:50:59 +08:00
php_stream * ret = php_stream_fopen_from_file_rel ( fp , mode ) ;
2002-03-16 05:03:08 +08:00
if ( ret ) {
if ( opened_path ) {
* opened_path = realpath ;
realpath = NULL ;
}
if ( realpath )
efree ( realpath ) ;
2001-04-18 01:03:18 +08:00
return ret ;
2002-03-16 05:03:08 +08:00
}
2001-04-18 01:03:18 +08:00
fclose ( fp ) ;
}
2002-03-16 05:03:08 +08:00
efree ( realpath ) ;
2001-04-18 01:03:18 +08:00
return NULL ;
}
2002-03-16 05:03:08 +08:00
/* }}} */
2001-04-18 01:03:18 +08:00
2002-03-16 05:03:08 +08:00
/* {{{ STDIO with fopencookie */
2001-04-18 01:03:18 +08:00
# if HAVE_FOPENCOOKIE
static ssize_t stream_cookie_reader ( void * cookie , char * buffer , size_t size )
{
2002-03-20 07:29:37 +08:00
ssize_t ret ;
2002-03-19 02:54:32 +08:00
TSRMLS_FETCH ( ) ;
2002-03-20 07:29:37 +08:00
ret = php_stream_read ( ( ( php_stream * ) cookie ) , buffer , size ) ;
return ret ;
2001-04-18 01:03:18 +08:00
}
2002-03-20 07:29:37 +08:00
static ssize_t stream_cookie_writer ( void * cookie , const char * buffer , size_t size )
{
2002-03-19 02:54:32 +08:00
TSRMLS_FETCH ( ) ;
return php_stream_write ( ( ( php_stream * ) cookie ) , ( char * ) buffer , size ) ;
2001-04-18 01:03:18 +08:00
}
2002-08-23 06:28:19 +08:00
# ifdef COOKIE_SEEKER_USES_FPOS_T
static int stream_cookie_seeker ( void * cookie , fpos_t * position , int whence )
{
TSRMLS_FETCH ( ) ;
* position = php_stream_seek ( ( php_stream * ) cookie , * position , whence ) ;
if ( * position = = - 1 )
return - 1 ;
return 0 ;
}
# else
2002-03-20 07:29:37 +08:00
static int stream_cookie_seeker ( void * cookie , off_t position , int whence )
{
2002-03-19 02:54:32 +08:00
TSRMLS_FETCH ( ) ;
2002-03-20 07:29:37 +08:00
return php_stream_seek ( ( php_stream * ) cookie , position , whence ) ;
2001-04-18 01:03:18 +08:00
}
2002-08-23 06:28:19 +08:00
# endif
2001-04-18 01:03:18 +08:00
2002-03-20 07:29:37 +08:00
static int stream_cookie_closer ( void * cookie )
{
2002-03-16 09:58:13 +08:00
php_stream * stream = ( php_stream * ) cookie ;
2002-03-19 03:13:11 +08:00
TSRMLS_FETCH ( ) ;
2002-03-20 07:29:37 +08:00
2001-05-06 02:36:22 +08:00
/* prevent recursion */
stream - > fclose_stdiocast = PHP_STREAM_FCLOSE_NONE ;
return php_stream_close ( stream ) ;
2001-04-18 01:03:18 +08:00
}
static COOKIE_IO_FUNCTIONS_T stream_cookie_functions =
{
stream_cookie_reader , stream_cookie_writer ,
stream_cookie_seeker , stream_cookie_closer
} ;
2001-05-06 02:36:22 +08:00
# else
2001-08-25 17:20:18 +08:00
/* TODO: use socketpair() to emulate fopencookie, as suggested by Hartmut ? */
2001-04-18 01:03:18 +08:00
# endif
2002-03-16 05:03:08 +08:00
/* }}} */
2001-04-18 01:03:18 +08:00
2002-03-20 22:21:30 +08:00
/* {{{ php_stream_cast */
PHPAPI int _php_stream_cast ( php_stream * stream , int castas , void * * ret , int show_err TSRMLS_DC )
2001-04-18 01:03:18 +08:00
{
2002-03-16 22:39:51 +08:00
int flags = castas & PHP_STREAM_CAST_MASK ;
castas & = ~ PHP_STREAM_CAST_MASK ;
2002-03-17 04:05:08 +08:00
2002-09-23 09:47:04 +08:00
/* synchronize our buffer (if possible) */
if ( ret ) {
php_stream_flush ( stream ) ;
if ( stream - > ops - > seek & & ( stream - > flags & PHP_STREAM_FLAG_NO_SEEK ) = = 0 ) {
off_t dummy ;
stream - > ops - > seek ( stream , stream - > position , SEEK_SET , & dummy TSRMLS_CC ) ;
stream - > readpos = stream - > writepos = 0 ;
}
}
2002-08-21 04:47:47 +08:00
/* filtered streams can only be cast as stdio, and only when fopencookie is present */
2002-03-16 22:39:51 +08:00
if ( castas = = PHP_STREAM_AS_STDIO ) {
if ( stream - > stdiocast ) {
2002-03-16 08:05:47 +08:00
if ( ret ) {
2001-04-18 01:03:18 +08:00
* ret = stream - > stdiocast ;
2002-03-16 08:05:47 +08:00
}
2002-03-16 22:39:51 +08:00
goto exit_success ;
2001-04-18 01:03:18 +08:00
}
2002-03-20 07:29:37 +08:00
/* if the stream is a stdio stream let's give it a chance to respond
* first , to avoid doubling up the layers of stdio with an fopencookie */
if ( php_stream_is ( stream , PHP_STREAM_IS_STDIO ) & &
stream - > ops - > cast & &
2002-08-21 04:47:47 +08:00
stream - > filterhead = = NULL & &
2002-03-20 07:29:37 +08:00
stream - > ops - > cast ( stream , castas , ret TSRMLS_CC ) = = SUCCESS )
{
2001-04-18 01:03:18 +08:00
goto exit_success ;
2002-03-20 07:29:37 +08:00
}
2001-04-18 01:03:18 +08:00
# if HAVE_FOPENCOOKIE
/* if just checking, say yes we can be a FILE*, but don't actually create it yet */
if ( ret = = NULL )
goto exit_success ;
* ret = fopencookie ( stream , stream - > mode , stream_cookie_functions ) ;
2002-03-16 22:39:51 +08:00
if ( * ret ! = NULL ) {
2002-03-20 07:29:37 +08:00
off_t pos ;
2002-03-16 22:39:51 +08:00
stream - > fclose_stdiocast = PHP_STREAM_FCLOSE_FOPENCOOKIE ;
2002-03-20 07:29:37 +08:00
/* If the stream position is not at the start, we need to force
* the stdio layer to believe it ' s real location . */
pos = php_stream_tell ( stream ) ;
if ( pos > 0 )
fseek ( * ret , pos , SEEK_SET ) ;
2001-04-18 01:03:18 +08:00
goto exit_success ;
2001-05-06 02:36:22 +08:00
}
2001-04-18 01:03:18 +08:00
2002-03-20 01:49:02 +08:00
/* must be either:
a ) programmer error
b ) no memory
- > lets bail
*/
2002-08-25 18:36:08 +08:00
php_error_docref ( NULL TSRMLS_CC , E_ERROR , " fopencookie failed " ) ;
2002-03-20 01:49:02 +08:00
return FAILURE ;
2001-04-18 01:03:18 +08:00
# endif
}
2002-08-21 04:47:47 +08:00
if ( stream - > filterhead ) {
2002-08-22 18:16:03 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " cannot cast a filtered stream on this system " ) ;
2002-08-21 04:47:47 +08:00
return FAILURE ;
}
2002-03-19 02:54:32 +08:00
if ( stream - > ops - > cast & & stream - > ops - > cast ( stream , castas , ret TSRMLS_CC ) = = SUCCESS )
2001-04-18 01:03:18 +08:00
goto exit_success ;
2002-03-16 22:39:51 +08:00
if ( show_err ) {
2001-05-06 02:36:22 +08:00
/* these names depend on the values of the PHP_STREAM_AS_XXX defines in php_streams.h */
2002-03-16 09:58:13 +08:00
static const char * cast_names [ 3 ] = {
2001-05-06 02:36:22 +08:00
" STDIO FILE* " , " File Descriptor " , " Socket Descriptor "
} ;
2001-08-25 17:20:18 +08:00
2002-08-25 18:36:08 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " cannot represent a stream of type %s as a %s " ,
2001-04-18 01:03:18 +08:00
stream - > ops - > label ,
cast_names [ castas ]
) ;
}
return FAILURE ;
exit_success :
2002-09-23 09:47:04 +08:00
2002-09-27 00:22:28 +08:00
if ( ( stream - > writepos - stream - > readpos ) > 0 & & stream - > fclose_stdiocast ! = PHP_STREAM_FCLOSE_FOPENCOOKIE ) {
2002-09-23 09:47:04 +08:00
/* the data we have buffered will be lost to the third party library that
* will be accessing the stream . Emit a warning so that the end - user will
* know that they should try something else */
php_error_docref ( NULL TSRMLS_CC , E_WARNING ,
" %d bytes of buffered data lost during conversion to FILE*! " ,
stream - > writepos - stream - > readpos ) ;
}
2001-04-18 01:03:18 +08:00
if ( castas = = PHP_STREAM_AS_STDIO & & ret )
stream - > stdiocast = * ret ;
2002-03-20 07:29:37 +08:00
2002-03-16 22:39:51 +08:00
if ( flags & PHP_STREAM_CAST_RELEASE ) {
/* Something other than php_stream_close will be closing
* the underlying handle , so we should free the stream handle / data
* here now . The stream may not be freed immediately ( in the case
* of fopencookie ) , but the caller should still not touch their
* original stream pointer in any case . */
if ( stream - > fclose_stdiocast ! = PHP_STREAM_FCLOSE_FOPENCOOKIE ) {
/* ask the implementation to release resources other than
* the underlying handle */
2002-03-19 02:54:32 +08:00
php_stream_free ( stream , PHP_STREAM_FREE_PRESERVE_HANDLE | PHP_STREAM_FREE_CLOSE ) ;
2002-03-16 22:39:51 +08:00
}
}
2002-03-17 04:05:08 +08:00
2001-04-18 01:03:18 +08:00
return SUCCESS ;
2002-03-20 22:21:30 +08:00
}
/* }}} */
2002-03-16 05:03:08 +08:00
2002-03-20 22:21:30 +08:00
/* {{{ wrapper init and registration */
2002-09-25 23:25:12 +08:00
static void stream_resource_regular_dtor ( zend_rsrc_list_entry * rsrc TSRMLS_DC )
{
php_stream * stream = ( php_stream * ) rsrc - > ptr ;
/* set the return value for pclose */
FG ( pclose_ret ) = php_stream_free ( stream , PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR ) ;
}
static void stream_resource_persistent_dtor ( zend_rsrc_list_entry * rsrc TSRMLS_DC )
{
php_stream * stream = ( php_stream * ) rsrc - > ptr ;
FG ( pclose_ret ) = php_stream_free ( stream , PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR ) ;
}
int php_init_stream_wrappers ( int module_number TSRMLS_DC )
2002-03-16 05:03:08 +08:00
{
2002-09-25 23:25:12 +08:00
le_stream = zend_register_list_destructors_ex ( stream_resource_regular_dtor , NULL , " stream " , module_number ) ;
le_pstream = zend_register_list_destructors_ex ( NULL , stream_resource_persistent_dtor , " persistent stream " , module_number ) ;
return (
zend_hash_init ( & url_stream_wrappers_hash , 0 , NULL , NULL , 1 ) = = SUCCESS
& &
zend_hash_init ( & stream_filters_hash , 0 , NULL , NULL , 1 ) = = SUCCESS
) ? SUCCESS : FAILURE ;
2002-03-16 05:03:08 +08:00
}
2002-09-25 23:25:12 +08:00
int php_shutdown_stream_wrappers ( int module_number TSRMLS_DC )
2002-03-16 05:03:08 +08:00
{
2002-04-17 06:14:27 +08:00
zend_hash_destroy ( & url_stream_wrappers_hash ) ;
2002-08-21 04:47:47 +08:00
zend_hash_destroy ( & stream_filters_hash ) ;
2002-03-16 05:03:08 +08:00
return SUCCESS ;
2001-04-18 01:03:18 +08:00
}
2002-03-18 16:05:28 +08:00
PHPAPI int php_register_url_stream_wrapper ( char * protocol , php_stream_wrapper * wrapper TSRMLS_DC )
2002-03-16 05:03:08 +08:00
{
2002-04-17 06:14:27 +08:00
return zend_hash_add ( & url_stream_wrappers_hash , protocol , strlen ( protocol ) , wrapper , sizeof ( * wrapper ) , NULL ) ;
2002-03-16 05:03:08 +08:00
}
2002-03-18 16:05:28 +08:00
PHPAPI int php_unregister_url_stream_wrapper ( char * protocol TSRMLS_DC )
2002-03-16 05:03:08 +08:00
{
2002-04-17 06:14:27 +08:00
return zend_hash_del ( & url_stream_wrappers_hash , protocol , strlen ( protocol ) ) ;
2002-03-16 05:03:08 +08:00
}
2002-03-20 22:21:30 +08:00
/* }}} */
2002-03-16 05:03:08 +08:00
2002-04-17 06:14:27 +08:00
static size_t php_plain_files_dirstream_read ( php_stream * stream , char * buf , size_t count TSRMLS_DC )
2002-03-16 05:03:08 +08:00
{
2002-04-17 06:14:27 +08:00
DIR * dir = ( DIR * ) stream - > abstract ;
/* avoid libc5 readdir problems */
char entry [ sizeof ( struct dirent ) + MAXPATHLEN ] ;
struct dirent * result = ( struct dirent * ) & entry ;
php_stream_dirent * ent = ( php_stream_dirent * ) buf ;
/* avoid problems if someone mis-uses the stream */
if ( count ! = sizeof ( php_stream_dirent ) )
return 0 ;
if ( php_readdir_r ( dir , ( struct dirent * ) entry , & result ) = = 0 & & result ) {
PHP_STRLCPY ( ent - > d_name , result - > d_name , sizeof ( ent - > d_name ) , strlen ( result - > d_name ) ) ;
return sizeof ( php_stream_dirent ) ;
}
return 0 ;
}
static int php_plain_files_dirstream_close ( php_stream * stream , int close_handle TSRMLS_DC )
{
return closedir ( ( DIR * ) stream - > abstract ) ;
}
2002-09-23 09:47:04 +08:00
static int php_plain_files_dirstream_rewind ( php_stream * stream , off_t offset , int whence , off_t * newoffs TSRMLS_DC )
2002-04-17 06:14:27 +08:00
{
rewinddir ( ( DIR * ) stream - > abstract ) ;
return 0 ;
}
static php_stream_ops php_plain_files_dirstream_ops = {
NULL , php_plain_files_dirstream_read ,
php_plain_files_dirstream_close , NULL ,
" dir " ,
php_plain_files_dirstream_rewind ,
2002-09-23 09:47:04 +08:00
NULL , /* cast */
NULL , /* stat */
NULL /* set_option */
2002-04-17 06:14:27 +08:00
} ;
static php_stream * php_plain_files_dir_opener ( php_stream_wrapper * wrapper , char * path , char * mode ,
int options , char * * opened_path , php_stream_context * context STREAMS_DC TSRMLS_DC )
{
DIR * dir = NULL ;
php_stream * stream = NULL ;
if ( php_check_open_basedir ( path TSRMLS_CC ) ) {
return NULL ;
}
if ( PG ( safe_mode ) & & ( ! php_checkuid ( path , NULL , CHECKUID_ALLOW_ONLY_FILE ) ) ) {
return NULL ;
}
dir = VCWD_OPENDIR ( path ) ;
# ifdef PHP_WIN32
if ( dir & & dir - > finished ) {
closedir ( dir ) ;
dir = NULL ;
}
# endif
if ( dir ) {
stream = php_stream_alloc ( & php_plain_files_dirstream_ops , dir , 0 , mode ) ;
if ( stream = = NULL )
closedir ( dir ) ;
}
return stream ;
}
static php_stream * php_plain_files_stream_opener ( php_stream_wrapper * wrapper , char * path , char * mode ,
int options , char * * opened_path , php_stream_context * context STREAMS_DC TSRMLS_DC )
{
if ( ( options & USE_PATH ) & & PG ( include_path ) ! = NULL ) {
return php_stream_fopen_with_path_rel ( path , mode , PG ( include_path ) , opened_path ) ;
}
2002-08-25 20:10:17 +08:00
if ( php_check_open_basedir ( path TSRMLS_CC ) ) {
return NULL ;
}
2002-04-17 06:14:27 +08:00
if ( ( options & ENFORCE_SAFE_MODE ) & & PG ( safe_mode ) & & ( ! php_checkuid ( path , mode , CHECKUID_CHECK_MODE_PARAM ) ) )
return NULL ;
return php_stream_fopen_rel ( path , mode , opened_path ) ;
}
static int php_plain_files_url_stater ( php_stream_wrapper * wrapper , char * url , php_stream_statbuf * ssb TSRMLS_DC )
{
return VCWD_STAT ( url , & ssb - > sb ) ;
}
static php_stream_wrapper_ops php_plain_files_wrapper_ops = {
php_plain_files_stream_opener ,
NULL ,
NULL ,
php_plain_files_url_stater ,
php_plain_files_dir_opener
} ;
static php_stream_wrapper php_plain_files_wrapper = {
& php_plain_files_wrapper_ops ,
NULL ,
0
} ;
2002-08-16 17:50:24 +08:00
PHPAPI php_stream_wrapper * php_stream_locate_url_wrapper ( const char * path , char * * path_for_open , int options TSRMLS_DC )
2002-04-17 06:14:27 +08:00
{
php_stream_wrapper * wrapper = NULL ;
2002-03-16 08:05:47 +08:00
const char * p , * protocol = NULL ;
2002-03-16 05:03:08 +08:00
int n = 0 ;
2002-08-16 17:50:24 +08:00
if ( path_for_open )
* path_for_open = ( char * ) path ;
2002-04-17 06:14:27 +08:00
if ( options & IGNORE_URL )
2002-08-16 17:50:24 +08:00
return ( options & STREAM_LOCATE_WRAPPERS_ONLY ) ? NULL : & php_plain_files_wrapper ;
2002-04-17 06:14:27 +08:00
2002-04-19 18:06:41 +08:00
for ( p = path ; isalnum ( ( int ) * p ) | | * p = = ' + ' | | * p = = ' - ' | | * p = = ' . ' ; p + + ) {
2002-03-16 05:03:08 +08:00
n + + ;
2002-03-16 08:05:47 +08:00
}
2002-03-16 05:03:08 +08:00
2002-03-22 01:02:50 +08:00
if ( ( * p = = ' : ' ) & & ( n > 1 ) & & ! strncmp ( " :// " , p , 3 ) ) {
2002-03-16 05:03:08 +08:00
protocol = path ;
2002-04-07 01:29:39 +08:00
} else if ( strncasecmp ( path , " zlib: " , 5 ) = = 0 ) {
/* BC with older php scripts and zlib wrapper */
2002-04-19 18:06:41 +08:00
protocol = " compress.zlib " ;
n = 13 ;
2002-08-25 18:36:08 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Use of \" zlib: \" wrapper is deprecated; please use \" compress.zlib:// \" instead. " ) ;
2002-03-16 08:05:47 +08:00
}
2002-03-16 05:03:08 +08:00
if ( protocol ) {
if ( FAILURE = = zend_hash_find ( & url_stream_wrappers_hash , ( char * ) protocol , n , ( void * * ) & wrapper ) ) {
2002-04-07 01:29:39 +08:00
char wrapper_name [ 32 ] ;
if ( n > = sizeof ( wrapper_name ) )
n = sizeof ( wrapper_name ) - 1 ;
PHP_STRLCPY ( wrapper_name , protocol , sizeof ( wrapper_name ) , n ) ;
2002-08-25 18:36:08 +08:00
php_error_docref ( NULL TSRMLS_CC , E_NOTICE , " Unable to find the wrapper \" %s \" - did you forget to enable it when you configured PHP? " ,
2002-04-07 01:29:39 +08:00
wrapper_name ) ;
2002-03-16 05:03:08 +08:00
wrapper = NULL ;
protocol = NULL ;
}
}
2002-08-16 17:50:24 +08:00
/* TODO: curl based streams probably support file:// properly */
2002-03-16 05:03:08 +08:00
if ( ! protocol | | ! strncasecmp ( protocol , " file " , n ) ) {
if ( protocol & & path [ n + 1 ] = = ' / ' & & path [ n + 2 ] = = ' / ' ) {
2002-08-16 17:50:24 +08:00
if ( options & REPORT_ERRORS )
2002-08-25 18:36:08 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " remote host file access not supported, %s " , path ) ;
2002-03-16 05:03:08 +08:00
return NULL ;
}
2002-08-16 17:50:24 +08:00
if ( protocol & & path_for_open )
* path_for_open = ( char * ) path + n + 1 ;
2002-04-17 06:14:27 +08:00
2002-03-16 05:03:08 +08:00
/* fall back on regular file access */
2002-08-16 17:50:24 +08:00
return ( options & STREAM_LOCATE_WRAPPERS_ONLY ) ? NULL : & php_plain_files_wrapper ;
2002-03-16 05:03:08 +08:00
}
2002-04-17 06:14:27 +08:00
if ( wrapper & & wrapper - > is_url & & ! PG ( allow_url_fopen ) ) {
2002-08-16 17:50:24 +08:00
if ( options & REPORT_ERRORS )
2002-08-25 18:36:08 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " URL file-access is disabled in the server configuration " ) ;
2002-04-17 06:14:27 +08:00
return NULL ;
}
return wrapper ;
}
PHPAPI int _php_stream_stat_path ( char * path , php_stream_statbuf * ssb TSRMLS_DC )
{
php_stream_wrapper * wrapper = NULL ;
char * path_to_open = path ;
2002-08-16 17:50:24 +08:00
wrapper = php_stream_locate_url_wrapper ( path , & path_to_open , ENFORCE_SAFE_MODE TSRMLS_CC ) ;
2002-04-17 06:14:27 +08:00
if ( wrapper & & wrapper - > wops - > url_stat ) {
return wrapper - > wops - > url_stat ( wrapper , path_to_open , ssb TSRMLS_CC ) ;
}
return - 1 ;
}
/* {{{ php_stream_opendir */
PHPAPI php_stream * _php_stream_opendir ( char * path , int options ,
php_stream_context * context STREAMS_DC TSRMLS_DC )
{
php_stream * stream = NULL ;
php_stream_wrapper * wrapper = NULL ;
char * path_to_open ;
if ( ! path | | ! * path )
return NULL ;
path_to_open = path ;
2002-08-16 17:50:24 +08:00
wrapper = php_stream_locate_url_wrapper ( path , & path_to_open , options TSRMLS_CC ) ;
2002-04-17 06:14:27 +08:00
if ( wrapper & & wrapper - > wops - > dir_opener ) {
stream = wrapper - > wops - > dir_opener ( wrapper ,
path_to_open , " r " , options , NULL ,
context STREAMS_REL_CC TSRMLS_CC ) ;
2002-09-23 09:47:04 +08:00
if ( stream ) {
2002-04-17 06:14:27 +08:00
stream - > wrapper = wrapper ;
2002-09-23 09:47:04 +08:00
stream - > flags | = PHP_STREAM_FLAG_NO_BUFFER ;
}
2002-04-17 06:14:27 +08:00
}
if ( stream = = NULL & & ( options & REPORT_ERRORS ) ) {
char * tmp = estrdup ( path ) ;
char * msg ;
if ( wrapper )
msg = strerror ( errno ) ;
else
msg = " no suitable wrapper could be found " ;
php_strip_url_passwd ( tmp ) ;
2002-08-25 18:36:08 +08:00
php_error_docref1 ( NULL TSRMLS_CC , tmp , E_WARNING , " %s " , msg ) ;
2002-04-17 06:14:27 +08:00
efree ( tmp ) ;
}
return stream ;
2002-03-16 05:03:08 +08:00
}
2002-03-20 22:21:30 +08:00
/* }}} */
2002-03-16 05:03:08 +08:00
2002-04-17 06:14:27 +08:00
PHPAPI php_stream_dirent * _php_stream_readdir ( php_stream * dirstream , php_stream_dirent * ent TSRMLS_DC )
{
2002-09-23 09:47:04 +08:00
2002-04-17 06:14:27 +08:00
if ( sizeof ( php_stream_dirent ) = = php_stream_read ( dirstream , ( char * ) ent , sizeof ( php_stream_dirent ) ) )
return ent ;
return NULL ;
}
2002-08-11 18:53:10 +08:00
PHPAPI void php_stream_wrapper_log_error ( php_stream_wrapper * wrapper , int options TSRMLS_DC , const char * fmt , . . . )
{
va_list args ;
char * buffer = NULL ;
va_start ( args , fmt ) ;
vspprintf ( & buffer , 0 , fmt , args ) ;
va_end ( args ) ;
if ( options & REPORT_ERRORS | | wrapper = = NULL ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , buffer ) ;
efree ( buffer ) ;
} else {
/* append to stack */
wrapper - > err_stack = erealloc ( wrapper - > err_stack , ( wrapper - > err_count + 1 ) * sizeof ( char * ) ) ;
if ( wrapper - > err_stack )
wrapper - > err_stack [ wrapper - > err_count + + ] = buffer ;
}
}
2002-04-11 06:42:32 +08:00
/* {{{ php_stream_open_wrapper_ex */
PHPAPI php_stream * _php_stream_open_wrapper_ex ( char * path , char * mode , int options ,
char * * opened_path , php_stream_context * context STREAMS_DC TSRMLS_DC )
2002-03-16 05:03:08 +08:00
{
2002-03-16 08:05:47 +08:00
php_stream * stream = NULL ;
2002-04-17 06:14:27 +08:00
php_stream_wrapper * wrapper = NULL ;
char * path_to_open ;
2002-08-21 04:47:47 +08:00
# if ZEND_DEBUG
char * copy_of_path = NULL ;
# endif
2002-04-17 06:14:27 +08:00
2002-03-16 05:03:08 +08:00
if ( opened_path )
* opened_path = NULL ;
2002-03-17 04:05:08 +08:00
2002-03-16 05:03:08 +08:00
if ( ! path | | ! * path )
return NULL ;
2002-04-17 06:14:27 +08:00
path_to_open = path ;
2002-03-17 04:05:08 +08:00
2002-08-16 17:50:24 +08:00
wrapper = php_stream_locate_url_wrapper ( path , & path_to_open , options TSRMLS_CC ) ;
2002-03-16 05:03:08 +08:00
2002-04-17 06:14:27 +08:00
if ( wrapper ) {
2002-08-11 18:53:10 +08:00
/* prepare error stack */
wrapper - > err_count = 0 ;
wrapper - > err_stack = NULL ;
2002-04-17 06:14:27 +08:00
stream = wrapper - > wops - > stream_opener ( wrapper ,
2002-08-11 18:53:10 +08:00
path_to_open , mode , options ^ REPORT_ERRORS ,
2002-04-17 06:14:27 +08:00
opened_path , context STREAMS_REL_CC TSRMLS_CC ) ;
if ( stream )
stream - > wrapper = wrapper ;
}
2002-03-20 07:29:37 +08:00
2002-08-21 04:47:47 +08:00
# if ZEND_DEBUG
if ( stream ) {
copy_of_path = estrdup ( path ) ;
stream - > __orig_path = copy_of_path ;
}
# endif
2002-03-17 22:21:01 +08:00
if ( stream ! = NULL & & ( options & STREAM_MUST_SEEK ) ) {
php_stream * newstream ;
2002-09-24 03:10:33 +08:00
switch ( php_stream_make_seekable_rel ( stream , & newstream ,
( options & STREAM_WILL_CAST )
? PHP_STREAM_PREFER_STDIO : PHP_STREAM_NO_PREFERENCE ) ) {
2002-03-17 22:21:01 +08:00
case PHP_STREAM_UNCHANGED :
return stream ;
case PHP_STREAM_RELEASED :
2002-08-21 04:47:47 +08:00
# if ZEND_DEBUG
newstream - > __orig_path = copy_of_path ;
# endif
2002-03-17 22:21:01 +08:00
return newstream ;
default :
php_stream_close ( stream ) ;
stream = NULL ;
if ( options & REPORT_ERRORS ) {
char * tmp = estrdup ( path ) ;
php_strip_url_passwd ( tmp ) ;
2002-08-11 18:53:10 +08:00
php_error_docref1 ( NULL TSRMLS_CC , tmp , E_WARNING , " could not make seekable - %s " ,
tmp , strerror ( errno ) ) ;
2002-03-17 22:21:01 +08:00
efree ( tmp ) ;
options ^ = REPORT_ERRORS ;
}
}
}
if ( stream = = NULL & & ( options & REPORT_ERRORS ) ) {
2002-03-16 09:58:13 +08:00
char * tmp = estrdup ( path ) ;
2002-04-17 06:14:27 +08:00
char * msg ;
2002-08-16 20:02:42 +08:00
int free_msg = 0 ;
2002-04-17 06:14:27 +08:00
2002-08-11 18:53:10 +08:00
if ( wrapper ) {
2002-09-26 20:12:27 +08:00
if ( wrapper - > err_count > 0 ) {
2002-08-11 18:53:10 +08:00
int i ;
size_t l ;
int brlen ;
char * br ;
if ( PG ( html_errors ) ) {
brlen = 7 ;
br = " <br /> \n " ;
} else {
brlen = 1 ;
br = " \n " ;
}
for ( i = 0 , l = 0 ; i < wrapper - > err_count ; i + + ) {
l + = strlen ( wrapper - > err_stack [ i ] ) ;
if ( i < wrapper - > err_count - 1 )
l + = brlen ;
}
msg = emalloc ( l + 1 ) ;
msg [ 0 ] = ' \0 ' ;
for ( i = 0 ; i < wrapper - > err_count ; i + + ) {
strcat ( msg , wrapper - > err_stack [ i ] ) ;
if ( i < wrapper - > err_count - 1 )
strcat ( msg , br ) ;
}
2002-08-16 20:02:42 +08:00
free_msg = 1 ;
2002-08-11 18:53:10 +08:00
} else {
msg = strerror ( errno ) ;
}
} else {
2002-04-17 06:14:27 +08:00
msg = " no suitable wrapper could be found " ;
2002-08-11 18:53:10 +08:00
}
2002-04-17 06:14:27 +08:00
2002-03-16 05:03:08 +08:00
php_strip_url_passwd ( tmp ) ;
2002-08-11 18:53:10 +08:00
php_error_docref1 ( NULL TSRMLS_CC , tmp , E_WARNING , " failed to create stream: %s " , msg ) ;
2002-03-16 05:03:08 +08:00
efree ( tmp ) ;
2002-08-16 20:02:42 +08:00
if ( free_msg )
efree ( msg ) ;
2002-03-16 05:03:08 +08:00
}
2002-08-11 18:53:10 +08:00
if ( wrapper ) {
/* tidy up the error stack */
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 ;
2002-09-26 20:12:27 +08:00
wrapper - > err_count = 0 ;
2002-08-11 18:53:10 +08:00
}
2002-08-21 04:47:47 +08:00
# if ZEND_DEBUG
if ( stream = = NULL & & copy_of_path ! = NULL )
efree ( copy_of_path ) ;
# endif
2002-03-16 05:03:08 +08:00
return stream ;
}
2002-03-20 22:21:30 +08:00
/* }}} */
2002-03-16 05:03:08 +08:00
2002-03-20 22:21:30 +08:00
/* {{{ php_stream_open_wrapper_as_file */
2002-03-20 07:29:37 +08:00
PHPAPI FILE * _php_stream_open_wrapper_as_file ( char * path , char * mode , int options , char * * opened_path STREAMS_DC TSRMLS_DC )
{
FILE * fp = NULL ;
php_stream * stream = NULL ;
2002-04-30 08:16:00 +08:00
stream = php_stream_open_wrapper_rel ( path , mode , options | STREAM_WILL_CAST , opened_path ) ;
2002-03-20 07:29:37 +08:00
if ( stream = = NULL )
return NULL ;
2002-08-21 04:47:47 +08:00
2002-03-20 07:29:37 +08:00
if ( php_stream_cast ( stream , PHP_STREAM_AS_STDIO | PHP_STREAM_CAST_TRY_HARD | PHP_STREAM_CAST_RELEASE ,
( void * * ) & fp , REPORT_ERRORS ) = = FAILURE )
{
php_stream_close ( stream ) ;
if ( opened_path & & * opened_path )
efree ( * opened_path ) ;
return NULL ;
}
return fp ;
}
2002-03-20 22:21:30 +08:00
/* }}} */
2002-03-20 07:29:37 +08:00
2002-03-20 22:21:30 +08:00
/* {{{ php_stream_make_seekable */
2002-03-20 01:49:02 +08:00
PHPAPI int _php_stream_make_seekable ( php_stream * origstream , php_stream * * newstream , int flags STREAMS_DC TSRMLS_DC )
2002-03-17 22:21:01 +08:00
{
assert ( newstream ! = NULL ) ;
* newstream = NULL ;
if ( origstream - > ops - > seek ! = NULL ) {
* newstream = origstream ;
return PHP_STREAM_UNCHANGED ;
}
/* Use a tmpfile and copy the old streams contents into it */
2002-03-20 01:49:02 +08:00
if ( flags & PHP_STREAM_PREFER_STDIO )
* newstream = php_stream_fopen_tmpfile ( ) ;
else
2002-03-24 01:51:20 +08:00
* newstream = php_stream_temp_new ( ) ;
2002-03-17 22:21:01 +08:00
if ( * newstream = = NULL )
return PHP_STREAM_FAILED ;
if ( php_stream_copy_to_stream ( origstream , * newstream , PHP_STREAM_COPY_ALL ) = = 0 ) {
php_stream_close ( * newstream ) ;
* newstream = NULL ;
return PHP_STREAM_CRITICAL ;
}
php_stream_close ( origstream ) ;
2002-03-20 07:29:37 +08:00
php_stream_seek ( * newstream , 0 , SEEK_SET ) ;
2002-03-17 22:21:01 +08:00
return PHP_STREAM_RELEASED ;
}
2002-03-20 22:21:30 +08:00
/* }}} */
2002-03-16 05:03:08 +08:00
2002-04-11 06:42:32 +08:00
PHPAPI php_stream_context * php_stream_context_set ( php_stream * stream , php_stream_context * context )
{
php_stream_context * oldcontext = stream - > context ;
stream - > context = context ;
return oldcontext ;
}
PHPAPI void php_stream_notification_notify ( php_stream_context * context , int notifycode , int severity ,
char * xmsg , int xcode , size_t bytes_sofar , size_t bytes_max , void * ptr TSRMLS_DC )
{
if ( context & & context - > notifier )
context - > notifier - > func ( context , notifycode , severity , xmsg , xcode , bytes_sofar , bytes_max , ptr TSRMLS_CC ) ;
}
PHPAPI void php_stream_context_free ( php_stream_context * context )
{
2002-04-30 08:16:00 +08:00
zval_ptr_dtor ( & context - > options ) ;
2002-04-11 06:42:32 +08:00
efree ( context ) ;
}
PHPAPI php_stream_context * php_stream_context_alloc ( void )
{
2002-04-30 08:16:00 +08:00
php_stream_context * context ;
context = ecalloc ( 1 , sizeof ( php_stream_context ) ) ;
MAKE_STD_ZVAL ( context - > options ) ;
array_init ( context - > options ) ;
return context ;
2002-04-11 06:42:32 +08:00
}
PHPAPI php_stream_notifier * php_stream_notification_alloc ( void )
{
return ecalloc ( 1 , sizeof ( php_stream_notifier ) ) ;
}
PHPAPI void php_stream_notification_free ( php_stream_notifier * notifier )
{
efree ( notifier ) ;
}
2002-04-30 08:16:00 +08:00
PHPAPI int php_stream_context_get_option ( php_stream_context * context ,
2002-09-08 04:58:30 +08:00
const char * wrappername , const char * optionname , zval * * * optionvalue )
2002-04-30 08:16:00 +08:00
{
zval * * wrapperhash ;
if ( FAILURE = = zend_hash_find ( Z_ARRVAL_P ( context - > options ) , ( char * ) wrappername , strlen ( wrappername ) + 1 , ( void * * ) & wrapperhash ) )
return FAILURE ;
2002-09-08 04:58:30 +08:00
return zend_hash_find ( Z_ARRVAL_PP ( wrapperhash ) , ( char * ) optionname , strlen ( optionname ) + 1 , ( void * * ) optionvalue ) ;
2002-04-30 08:16:00 +08:00
}
PHPAPI int php_stream_context_set_option ( php_stream_context * context ,
const char * wrappername , const char * optionname , zval * optionvalue )
{
zval * * wrapperhash ;
2002-09-08 04:58:30 +08:00
zval * category ;
2002-04-30 08:16:00 +08:00
if ( FAILURE = = zend_hash_find ( Z_ARRVAL_P ( context - > options ) , ( char * ) wrappername , strlen ( wrappername ) + 1 , ( void * * ) & wrapperhash ) ) {
2002-09-08 04:58:30 +08:00
MAKE_STD_ZVAL ( category ) ;
array_init ( category ) ;
if ( FAILURE = = zend_hash_update ( Z_ARRVAL_P ( context - > options ) , ( char * ) wrappername , strlen ( wrappername ) + 1 , ( void * * ) & category , sizeof ( zval * ) , NULL ) )
2002-04-30 08:16:00 +08:00
return FAILURE ;
ZVAL_ADDREF ( optionvalue ) ;
2002-09-08 04:58:30 +08:00
wrapperhash = & category ;
2002-04-30 08:16:00 +08:00
}
return zend_hash_update ( Z_ARRVAL_PP ( wrapperhash ) , ( char * ) optionname , strlen ( optionname ) + 1 , ( void * * ) & optionvalue , sizeof ( zval * ) , NULL ) ;
}
2002-06-08 18:25:44 +08:00
PHPAPI HashTable * php_stream_get_url_stream_wrappers_hash ( )
{
return & url_stream_wrappers_hash ;
}
2002-04-11 06:42:32 +08:00
2001-05-06 02:36:22 +08:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* End :
2001-09-09 21:29:31 +08:00
* vim600 : noet sw = 4 ts = 4 fdm = marker
* vim < 600 : noet sw = 4 ts = 4
2001-05-06 02:36:22 +08:00
*/