2008-05-12 21:03:49 +00:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| phar : // stream wrapper support |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Copyright ( c ) 2005 - 2008 The PHP Group |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| 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 |
| available through the world - wide - web at the following url : |
| http : //www.php.net/license/3_01.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 . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Authors : Gregory Beaver < cellog @ php . net > |
| Marcus Boerger < helly @ php . net > |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
# define PHAR_STREAM 1
# include "phar_internal.h"
# include "stream.h"
# include "dirstream.h"
php_stream_ops phar_ops = {
phar_stream_write , /* write */
phar_stream_read , /* read */
phar_stream_close , /* close */
phar_stream_flush , /* flush */
" phar stream " ,
phar_stream_seek , /* seek */
NULL , /* cast */
phar_stream_stat , /* stat */
NULL , /* set option */
} ;
php_stream_wrapper_ops phar_stream_wops = {
2008-08-01 13:48:45 +00:00
phar_wrapper_open_url ,
NULL , /* phar_wrapper_close */
NULL , /* phar_wrapper_stat, */
phar_wrapper_stat , /* stat_url */
phar_wrapper_open_dir , /* opendir */
" phar " ,
phar_wrapper_unlink , /* unlink */
phar_wrapper_rename , /* rename */
phar_wrapper_mkdir , /* create directory */
phar_wrapper_rmdir , /* remove directory */
2008-05-12 21:03:49 +00:00
} ;
2008-08-01 13:48:45 +00:00
php_stream_wrapper php_stream_phar_wrapper = {
& phar_stream_wops ,
NULL ,
0 /* is_url */
2008-05-12 21:03:49 +00:00
} ;
/**
* Open a phar file for streams API
*/
2008-05-30 22:38:46 +00:00
php_url * phar_parse_url ( php_stream_wrapper * wrapper , char * filename , char * mode , int options TSRMLS_DC ) /* { { { */
2008-05-12 21:03:49 +00:00
{
php_url * resource ;
char * arch = NULL , * entry = NULL , * error ;
int arch_len , entry_len ;
if ( strlen ( filename ) < 7 | | strncasecmp ( filename , " phar:// " , 7 ) ) {
return NULL ;
}
if ( mode [ 0 ] = = ' a ' ) {
if ( ! ( options & PHP_STREAM_URL_STAT_QUIET ) ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: open mode append not supported " ) ;
}
2008-08-01 13:48:45 +00:00
return NULL ;
}
2008-05-12 21:03:49 +00:00
if ( phar_split_fname ( filename , strlen ( filename ) , & arch , & arch_len , & entry , & entry_len , 2 , ( mode [ 0 ] = = ' w ' ? 2 : 0 ) TSRMLS_CC ) = = FAILURE ) {
if ( ! ( options & PHP_STREAM_URL_STAT_QUIET ) ) {
if ( arch & & ! entry ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: no directory in \" %s \" , must have at least phar://%s/ for root directory (always use full path to a new phar) " , filename , arch ) ;
arch = NULL ;
} else {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: invalid url or non-existent phar \" %s \" " , filename ) ;
}
}
return NULL ;
}
resource = ecalloc ( 1 , sizeof ( php_url ) ) ;
resource - > scheme = estrndup ( " phar " , 4 ) ;
resource - > host = arch ;
resource - > path = entry ;
# if MBO_0
if ( resource ) {
fprintf ( stderr , " Alias: %s \n " , alias ) ;
fprintf ( stderr , " Scheme: %s \n " , resource - > scheme ) ;
/* fprintf(stderr, "User: %s\n", resource->user);*/
/* fprintf(stderr, "Pass: %s\n", resource->pass ? "***" : NULL);*/
fprintf ( stderr , " Host: %s \n " , resource - > host ) ;
/* fprintf(stderr, "Port: %d\n", resource->port);*/
fprintf ( stderr , " Path: %s \n " , resource - > path ) ;
/* fprintf(stderr, "Query: %s\n", resource->query);*/
/* fprintf(stderr, "Fragment: %s\n", resource->fragment);*/
}
# endif
if ( mode [ 0 ] = = ' w ' | | ( mode [ 0 ] = = ' r ' & & mode [ 1 ] = = ' + ' ) ) {
2008-06-18 06:38:47 +00:00
phar_archive_data * * pphar = NULL , * phar ;
2008-05-12 21:03:49 +00:00
if ( PHAR_GLOBALS - > request_init & & PHAR_GLOBALS - > phar_fname_map . arBuckets & & FAILURE = = zend_hash_find ( & ( PHAR_GLOBALS - > phar_fname_map ) , arch , arch_len , ( void * * ) & pphar ) ) {
pphar = NULL ;
}
if ( PHAR_G ( readonly ) & & ( ! pphar | | ! ( * pphar ) - > is_data ) ) {
if ( ! ( options & PHP_STREAM_URL_STAT_QUIET ) ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: write operations disabled by INI setting " ) ;
}
php_url_free ( resource ) ;
return NULL ;
}
2008-06-18 06:38:47 +00:00
if ( phar_open_or_create_filename ( resource - > host , arch_len , NULL , 0 , 0 , options , & phar , & error TSRMLS_CC ) = = FAILURE )
2008-05-12 21:03:49 +00:00
{
if ( error ) {
if ( ! ( options & PHP_STREAM_URL_STAT_QUIET ) ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , error ) ;
}
efree ( error ) ;
}
php_url_free ( resource ) ;
return NULL ;
}
2008-06-18 06:38:47 +00:00
if ( phar - > is_persistent & & FAILURE = = phar_copy_on_write ( & phar TSRMLS_CC ) ) {
if ( error ) {
spprintf ( & error , 0 , " Cannot open cached phar '%s' as writeable, copy on write failed " , resource - > host ) ;
if ( ! ( options & PHP_STREAM_URL_STAT_QUIET ) ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , error ) ;
}
efree ( error ) ;
}
php_url_free ( resource ) ;
return NULL ;
}
2008-05-12 21:03:49 +00:00
} else {
2008-05-30 22:38:46 +00:00
if ( phar_open_from_filename ( resource - > host , arch_len , NULL , 0 , options , NULL , & error TSRMLS_CC ) = = FAILURE )
2008-05-12 21:03:49 +00:00
{
if ( error ) {
if ( ! ( options & PHP_STREAM_URL_STAT_QUIET ) ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , error ) ;
}
efree ( error ) ;
}
php_url_free ( resource ) ;
return NULL ;
}
2008-08-01 13:48:45 +00:00
}
2008-05-12 21:03:49 +00:00
return resource ;
}
/* }}} */
/**
* used for fopen ( ' phar : //...') and company
*/
static php_stream * phar_wrapper_open_url ( php_stream_wrapper * wrapper , char * path , char * mode , int options , char * * opened_path , php_stream_context * context STREAMS_DC TSRMLS_DC ) /* { { { */
{
2008-06-27 01:21:12 +00:00
phar_archive_data * phar ;
2008-05-12 21:03:49 +00:00
phar_entry_data * idata ;
char * internal_file ;
char * error ;
HashTable * pharcontext ;
php_url * resource = NULL ;
php_stream * fpf ;
zval * * pzoption , * metadata ;
uint host_len ;
2008-05-30 22:38:46 +00:00
if ( ( resource = phar_parse_url ( wrapper , path , mode , options TSRMLS_CC ) ) = = NULL ) {
2008-05-12 21:03:49 +00:00
return NULL ;
}
/* we must have at the very least phar://alias.phar/internalfile.php */
if ( ! resource - > scheme | | ! resource - > host | | ! resource - > path ) {
php_url_free ( resource ) ;
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: invalid url \" %s \" " , path ) ;
return NULL ;
}
if ( strcasecmp ( " phar " , resource - > scheme ) ) {
php_url_free ( resource ) ;
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: not a phar stream url \" %s \" " , path ) ;
return NULL ;
}
host_len = strlen ( resource - > host ) ;
phar_request_initialize ( TSRMLS_C ) ;
/* strip leading "/" */
internal_file = estrdup ( resource - > path + 1 ) ;
if ( mode [ 0 ] = = ' w ' | | ( mode [ 0 ] = = ' r ' & & mode [ 1 ] = = ' + ' ) ) {
2008-05-15 16:09:01 +00:00
if ( NULL = = ( idata = phar_get_or_create_entry_data ( resource - > host , host_len , internal_file , strlen ( internal_file ) , mode , 0 , & error , 1 TSRMLS_CC ) ) ) {
2008-05-12 21:03:49 +00:00
if ( error ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , error ) ;
efree ( error ) ;
} else {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: file \" %s \" could not be created in phar \" %s \" " , internal_file , resource - > host ) ;
}
efree ( internal_file ) ;
php_url_free ( resource ) ;
return NULL ;
}
if ( error ) {
efree ( error ) ;
}
fpf = php_stream_alloc ( & phar_ops , idata , NULL , mode ) ;
php_url_free ( resource ) ;
efree ( internal_file ) ;
if ( context & & context - > options & & zend_hash_find ( HASH_OF ( context - > options ) , " phar " , sizeof ( " phar " ) , ( void * * ) & pzoption ) = = SUCCESS ) {
pharcontext = HASH_OF ( * pzoption ) ;
if ( idata - > internal_file - > uncompressed_filesize = = 0
& & idata - > internal_file - > compressed_filesize = = 0
& & zend_hash_find ( pharcontext , " compress " , sizeof ( " compress " ) , ( void * * ) & pzoption ) = = SUCCESS
& & Z_TYPE_PP ( pzoption ) = = IS_LONG
& & ( Z_LVAL_PP ( pzoption ) & ~ PHAR_ENT_COMPRESSION_MASK ) = = 0
) {
idata - > internal_file - > flags & = ~ PHAR_ENT_COMPRESSION_MASK ;
idata - > internal_file - > flags | = Z_LVAL_PP ( pzoption ) ;
}
if ( zend_hash_find ( pharcontext , " metadata " , sizeof ( " metadata " ) , ( void * * ) & pzoption ) = = SUCCESS ) {
if ( idata - > internal_file - > metadata ) {
zval_ptr_dtor ( & idata - > internal_file - > metadata ) ;
idata - > internal_file - > metadata = NULL ;
}
MAKE_STD_ZVAL ( idata - > internal_file - > metadata ) ;
metadata = * pzoption ;
ZVAL_ZVAL ( idata - > internal_file - > metadata , metadata , 1 , 0 ) ;
idata - > phar - > is_modified = 1 ;
}
}
if ( opened_path ) {
spprintf ( opened_path , MAXPATHLEN , " phar://%s/%s " , idata - > phar - > fname , idata - > internal_file - > filename ) ;
}
return fpf ;
} else {
2008-06-27 01:21:12 +00:00
if ( ! * internal_file & & ( options & STREAM_OPEN_FOR_INCLUDE ) ) {
/* retrieve the stub */
if ( FAILURE = = phar_get_archive ( & phar , resource - > host , host_len , NULL , 0 , NULL TSRMLS_CC ) ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " file %s is not a valid phar archive " ) ;
efree ( internal_file ) ;
php_url_free ( resource ) ;
return NULL ;
}
if ( phar - > is_tar | | phar - > is_zip ) {
if ( ( FAILURE = = phar_get_entry_data ( & idata , resource - > host , host_len , " .phar/stub.php " , sizeof ( " .phar/stub.php " ) - 1 , " r " , 0 , & error , 0 TSRMLS_CC ) ) | | ! idata ) {
goto idata_error ;
}
efree ( internal_file ) ;
if ( opened_path ) {
spprintf ( opened_path , MAXPATHLEN , " %s " , phar - > fname ) ;
}
php_url_free ( resource ) ;
goto phar_stub ;
} else {
phar_entry_info * entry ;
entry = ( phar_entry_info * ) ecalloc ( 1 , sizeof ( phar_entry_info ) ) ;
entry - > is_temp_dir = 1 ;
2008-09-26 23:34:57 +00:00
entry - > filename = estrndup ( " " , 0 ) ;
2008-06-27 01:21:12 +00:00
entry - > filename_len = 0 ;
entry - > phar = phar ;
entry - > offset = entry - > offset_abs = 0 ;
entry - > compressed_filesize = entry - > uncompressed_filesize = phar - > halt_offset ;
entry - > is_crc_checked = 1 ;
idata = ( phar_entry_data * ) ecalloc ( 1 , sizeof ( phar_entry_data ) ) ;
idata - > fp = phar_get_pharfp ( phar TSRMLS_CC ) ;
idata - > phar = phar ;
idata - > internal_file = entry ;
if ( ! phar - > is_persistent ) {
+ + ( entry - > phar - > refcount ) ;
}
+ + ( entry - > fp_refcount ) ;
php_url_free ( resource ) ;
if ( opened_path ) {
spprintf ( opened_path , MAXPATHLEN , " %s " , phar - > fname ) ;
}
efree ( internal_file ) ;
goto phar_stub ;
}
}
2008-05-15 16:09:01 +00:00
/* read-only access is allowed to magic files in .phar directory */
if ( ( FAILURE = = phar_get_entry_data ( & idata , resource - > host , host_len , internal_file , strlen ( internal_file ) , " r " , 0 , & error , 0 TSRMLS_CC ) ) | | ! idata ) {
2008-06-27 01:21:12 +00:00
idata_error :
2008-05-12 21:03:49 +00:00
if ( error ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , error ) ;
efree ( error ) ;
} else {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: \" %s \" is not a file in phar \" %s \" " , internal_file , resource - > host ) ;
}
efree ( internal_file ) ;
php_url_free ( resource ) ;
return NULL ;
}
}
php_url_free ( resource ) ;
# if MBO_0
fprintf ( stderr , " Pharname: %s \n " , idata - > phar - > filename ) ;
fprintf ( stderr , " Filename: %s \n " , internal_file ) ;
fprintf ( stderr , " Entry: %s \n " , idata - > internal_file - > filename ) ;
fprintf ( stderr , " Size: %u \n " , idata - > internal_file - > uncompressed_filesize ) ;
fprintf ( stderr , " Compressed: %u \n " , idata - > internal_file - > flags ) ;
fprintf ( stderr , " Offset: %u \n " , idata - > internal_file - > offset_within_phar ) ;
fprintf ( stderr , " Cached: %s \n " , idata - > internal_file - > filedata ? " yes " : " no " ) ;
# endif
/* check length, crc32 */
2008-08-21 05:17:28 +00:00
if ( ! idata - > internal_file - > is_crc_checked & & phar_postprocess_file ( idata , idata - > internal_file - > crc32 , & error , 2 TSRMLS_CC ) ! = SUCCESS ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , error ) ;
efree ( error ) ;
2008-05-12 21:03:49 +00:00
phar_entry_delref ( idata TSRMLS_CC ) ;
efree ( internal_file ) ;
return NULL ;
}
if ( ! PHAR_G ( cwd_init ) & & options & STREAM_OPEN_FOR_INCLUDE ) {
char * entry = idata - > internal_file - > filename , * cwd ;
PHAR_G ( cwd_init ) = 1 ;
if ( ( idata - > phar - > is_tar | | idata - > phar - > is_zip ) & & idata - > internal_file - > filename_len = = sizeof ( " .phar/stub.php " ) - 1 & & ! strncmp ( idata - > internal_file - > filename , " .phar/stub.php " , sizeof ( " .phar/stub.php " ) - 1 ) ) {
/* we're executing the stub, which doesn't count as a file */
PHAR_G ( cwd_init ) = 0 ;
} else if ( ( cwd = strrchr ( entry , ' / ' ) ) ) {
PHAR_G ( cwd_len ) = cwd - entry ;
PHAR_G ( cwd ) = estrndup ( entry , PHAR_G ( cwd_len ) ) ;
} else {
/* root directory */
PHAR_G ( cwd_len ) = 0 ;
PHAR_G ( cwd ) = NULL ;
}
}
if ( opened_path ) {
spprintf ( opened_path , MAXPATHLEN , " phar://%s/%s " , idata - > phar - > fname , idata - > internal_file - > filename ) ;
}
efree ( internal_file ) ;
2008-06-27 01:21:12 +00:00
phar_stub :
fpf = php_stream_alloc ( & phar_ops , idata , NULL , mode ) ;
2008-05-12 21:03:49 +00:00
return fpf ;
}
/* }}} */
/**
* Used for fclose ( $ fp ) where $ fp is a phar archive
*/
static int phar_stream_close ( php_stream * stream , int close_handle TSRMLS_DC ) /* { { { */
{
phar_entry_delref ( ( phar_entry_data * ) stream - > abstract TSRMLS_CC ) ;
return 0 ;
}
/* }}} */
/**
* used for fread ( $ fp ) and company on a fopen ( ) ed phar file handle
*/
static size_t phar_stream_read ( php_stream * stream , char * buf , size_t count TSRMLS_DC ) /* { { { */
{
phar_entry_data * data = ( phar_entry_data * ) stream - > abstract ;
size_t got ;
2008-10-11 22:12:07 +00:00
phar_entry_info * entry ;
2008-08-01 13:48:45 +00:00
2008-10-11 22:12:07 +00:00
if ( data - > internal_file - > link ) {
entry = phar_get_link_source ( data - > internal_file TSRMLS_CC ) ;
} else {
entry = data - > internal_file ;
}
if ( entry - > is_deleted ) {
2008-05-12 21:03:49 +00:00
stream - > eof = 1 ;
return 0 ;
}
/* use our proxy position */
php_stream_seek ( data - > fp , data - > position + data - > zero , SEEK_SET ) ;
2008-10-11 22:12:07 +00:00
got = php_stream_read ( data - > fp , buf , MIN ( count , entry - > uncompressed_filesize - data - > position ) ) ;
2008-05-12 21:03:49 +00:00
data - > position = php_stream_tell ( data - > fp ) - data - > zero ;
2008-10-11 22:12:07 +00:00
stream - > eof = ( data - > position = = ( off_t ) entry - > uncompressed_filesize ) ;
2008-05-12 21:03:49 +00:00
return got ;
}
/* }}} */
/**
* Used for fseek ( $ fp ) on a phar file handle
*/
static int phar_stream_seek ( php_stream * stream , off_t offset , int whence , off_t * newoffset TSRMLS_DC ) /* { { { */
{
phar_entry_data * data = ( phar_entry_data * ) stream - > abstract ;
2008-10-11 22:20:57 +00:00
phar_entry_info * entry ;
2008-05-12 21:03:49 +00:00
int res ;
off_t temp ;
2008-10-11 22:20:57 +00:00
if ( data - > internal_file - > link ) {
entry = phar_get_link_source ( data - > internal_file TSRMLS_CC ) ;
} else {
entry = data - > internal_file ;
}
2008-05-12 21:03:49 +00:00
switch ( whence ) {
case SEEK_END :
2008-10-11 22:20:57 +00:00
temp = data - > zero + entry - > uncompressed_filesize + offset ;
2008-05-12 21:03:49 +00:00
break ;
case SEEK_CUR :
temp = data - > zero + data - > position + offset ;
break ;
case SEEK_SET :
temp = data - > zero + offset ;
break ;
}
2008-10-11 22:20:57 +00:00
if ( temp > data - > zero + ( off_t ) entry - > uncompressed_filesize ) {
2008-05-12 21:03:49 +00:00
* newoffset = - 1 ;
return - 1 ;
}
if ( temp < data - > zero ) {
* newoffset = - 1 ;
return - 1 ;
}
res = php_stream_seek ( data - > fp , temp , SEEK_SET ) ;
* newoffset = php_stream_tell ( data - > fp ) - data - > zero ;
data - > position = * newoffset ;
return res ;
}
/* }}} */
/**
* Used for writing to a phar file
*/
static size_t phar_stream_write ( php_stream * stream , const char * buf , size_t count TSRMLS_DC ) /* { { { */
{
phar_entry_data * data = ( phar_entry_data * ) stream - > abstract ;
php_stream_seek ( data - > fp , data - > position , SEEK_SET ) ;
if ( count ! = php_stream_write ( data - > fp , buf , count ) ) {
php_stream_wrapper_log_error ( stream - > wrapper , stream - > flags TSRMLS_CC , " phar error: Could not write %d characters to \" %s \" in phar \" %s \" " , ( int ) count , data - > internal_file - > filename , data - > phar - > fname ) ;
return - 1 ;
}
data - > position = php_stream_tell ( data - > fp ) ;
if ( data - > position > ( off_t ) data - > internal_file - > uncompressed_filesize ) {
data - > internal_file - > uncompressed_filesize = data - > position ;
}
data - > internal_file - > compressed_filesize = data - > internal_file - > uncompressed_filesize ;
data - > internal_file - > old_flags = data - > internal_file - > flags ;
data - > internal_file - > is_modified = 1 ;
return count ;
}
/* }}} */
/**
* Used to save work done on a writeable phar
*/
static int phar_stream_flush ( php_stream * stream TSRMLS_DC ) /* { { { */
{
char * error ;
int ret ;
if ( stream - > mode [ 0 ] = = ' w ' | | ( stream - > mode [ 0 ] = = ' r ' & & stream - > mode [ 1 ] = = ' + ' ) ) {
ret = phar_flush ( ( ( phar_entry_data * ) stream - > abstract ) - > phar , 0 , 0 , 0 , & error TSRMLS_CC ) ;
if ( error ) {
php_stream_wrapper_log_error ( stream - > wrapper , REPORT_ERRORS TSRMLS_CC , error ) ;
efree ( error ) ;
}
return ret ;
} else {
return EOF ;
}
}
/* }}} */
/* {{{ phar_dostat */
/**
* stat an opened phar file handle stream , used by phar_stat ( )
*/
2008-09-13 22:30:55 +00:00
void phar_dostat ( phar_archive_data * phar , phar_entry_info * data , php_stream_statbuf * ssb , zend_bool is_temp_dir TSRMLS_DC )
2008-05-12 21:03:49 +00:00
{
memset ( ssb , 0 , sizeof ( php_stream_statbuf ) ) ;
if ( ! is_temp_dir & & ! data - > is_dir ) {
ssb - > sb . st_size = data - > uncompressed_filesize ;
ssb - > sb . st_mode = data - > flags & PHAR_ENT_PERM_MASK ;
ssb - > sb . st_mode | = S_IFREG ; /* regular file */
/* timestamp is just the timestamp when this was added to the phar */
# ifdef NETWARE
ssb - > sb . st_mtime . tv_sec = data - > timestamp ;
ssb - > sb . st_atime . tv_sec = data - > timestamp ;
ssb - > sb . st_ctime . tv_sec = data - > timestamp ;
# else
ssb - > sb . st_mtime = data - > timestamp ;
ssb - > sb . st_atime = data - > timestamp ;
ssb - > sb . st_ctime = data - > timestamp ;
# endif
} else if ( ! is_temp_dir & & data - > is_dir ) {
ssb - > sb . st_size = 0 ;
ssb - > sb . st_mode = data - > flags & PHAR_ENT_PERM_MASK ;
ssb - > sb . st_mode | = S_IFDIR ; /* regular directory */
/* timestamp is just the timestamp when this was added to the phar */
# ifdef NETWARE
ssb - > sb . st_mtime . tv_sec = data - > timestamp ;
ssb - > sb . st_atime . tv_sec = data - > timestamp ;
ssb - > sb . st_ctime . tv_sec = data - > timestamp ;
# else
ssb - > sb . st_mtime = data - > timestamp ;
ssb - > sb . st_atime = data - > timestamp ;
ssb - > sb . st_ctime = data - > timestamp ;
# endif
} else {
ssb - > sb . st_size = 0 ;
ssb - > sb . st_mode = 0777 ;
ssb - > sb . st_mode | = S_IFDIR ; /* regular directory */
# ifdef NETWARE
ssb - > sb . st_mtime . tv_sec = phar - > max_timestamp ;
ssb - > sb . st_atime . tv_sec = phar - > max_timestamp ;
ssb - > sb . st_ctime . tv_sec = phar - > max_timestamp ;
# else
ssb - > sb . st_mtime = phar - > max_timestamp ;
ssb - > sb . st_atime = phar - > max_timestamp ;
ssb - > sb . st_ctime = phar - > max_timestamp ;
# endif
}
if ( ! phar - > is_writeable ) {
ssb - > sb . st_mode = ( ssb - > sb . st_mode & 0555 ) | ( ssb - > sb . st_mode & ~ 0777 ) ;
}
ssb - > sb . st_nlink = 1 ;
ssb - > sb . st_rdev = - 1 ;
/* this is only for APC, so use /dev/null device - no chance of conflict there! */
ssb - > sb . st_dev = 0xc ;
/* generate unique inode number for alias/filename, so no phars will conflict */
2008-06-15 21:42:20 +00:00
if ( ! is_temp_dir ) {
ssb - > sb . st_ino = data - > inode ;
}
2008-05-12 21:03:49 +00:00
# ifndef PHP_WIN32
ssb - > sb . st_blksize = - 1 ;
ssb - > sb . st_blocks = - 1 ;
# endif
}
/* }}}*/
/**
* Stat an opened phar file handle
*/
static int phar_stream_stat ( php_stream * stream , php_stream_statbuf * ssb TSRMLS_DC ) /* { { { */
{
phar_entry_data * data = ( phar_entry_data * ) stream - > abstract ;
/* If ssb is NULL then someone is misbehaving */
if ( ! ssb ) {
return - 1 ;
}
2008-09-13 22:30:55 +00:00
phar_dostat ( data - > phar , data - > internal_file , ssb , 0 TSRMLS_CC ) ;
2008-05-12 21:03:49 +00:00
return 0 ;
}
/* }}} */
/**
* Stream wrapper stat implementation of stat ( )
*/
static int phar_wrapper_stat ( php_stream_wrapper * wrapper , char * url , int flags ,
php_stream_statbuf * ssb , php_stream_context * context TSRMLS_DC ) /* {{{ */
{
php_url * resource = NULL ;
2008-06-18 06:38:47 +00:00
char * internal_file , * error ;
2008-05-12 21:03:49 +00:00
phar_archive_data * phar ;
phar_entry_info * entry ;
uint host_len ;
int internal_file_len ;
2008-05-30 22:38:46 +00:00
if ( ( resource = phar_parse_url ( wrapper , url , " r " , flags | PHP_STREAM_URL_STAT_QUIET TSRMLS_CC ) ) = = NULL ) {
2008-05-12 21:03:49 +00:00
return FAILURE ;
}
/* we must have at the very least phar://alias.phar/internalfile.php */
if ( ! resource - > scheme | | ! resource - > host | | ! resource - > path ) {
php_url_free ( resource ) ;
return FAILURE ;
}
if ( strcasecmp ( " phar " , resource - > scheme ) ) {
php_url_free ( resource ) ;
return FAILURE ;
}
host_len = strlen ( resource - > host ) ;
phar_request_initialize ( TSRMLS_C ) ;
internal_file = resource - > path + 1 ; /* strip leading "/" */
/* find the phar in our trusty global hash indexed by alias (host of phar://blah.phar/file.whatever) */
2008-09-13 22:30:55 +00:00
if ( FAILURE = = phar_get_archive ( & phar , resource - > host , host_len , NULL , 0 , & error TSRMLS_CC ) ) {
2008-05-12 21:03:49 +00:00
php_url_free ( resource ) ;
if ( error ) {
efree ( error ) ;
}
return FAILURE ;
}
if ( error ) {
efree ( error ) ;
}
if ( * internal_file = = ' \0 ' ) {
/* root directory requested */
2008-09-13 22:30:55 +00:00
phar_dostat ( phar , NULL , ssb , 1 TSRMLS_CC ) ;
2008-05-12 21:03:49 +00:00
php_url_free ( resource ) ;
return SUCCESS ;
}
if ( ! phar - > manifest . arBuckets ) {
php_url_free ( resource ) ;
return FAILURE ;
}
internal_file_len = strlen ( internal_file ) ;
/* search through the manifest of files, and if we have an exact match, it's a file */
if ( SUCCESS = = zend_hash_find ( & phar - > manifest , internal_file , internal_file_len , ( void * * ) & entry ) ) {
2008-09-13 22:30:55 +00:00
phar_dostat ( phar , entry , ssb , 0 TSRMLS_CC ) ;
2008-05-12 21:03:49 +00:00
php_url_free ( resource ) ;
return SUCCESS ;
2008-06-18 06:38:47 +00:00
}
2008-07-10 16:16:15 +00:00
if ( zend_hash_exists ( & ( phar - > virtual_dirs ) , internal_file , internal_file_len ) ) {
2008-09-13 22:30:55 +00:00
phar_dostat ( phar , NULL , ssb , 1 TSRMLS_CC ) ;
2008-06-18 06:38:47 +00:00
php_url_free ( resource ) ;
return SUCCESS ;
}
/* check for mounted directories */
if ( phar - > mounted_dirs . arBuckets & & zend_hash_num_elements ( & phar - > mounted_dirs ) ) {
phar_zstr key ;
char * str_key ;
ulong unused ;
uint keylen ;
2008-07-20 14:42:34 +00:00
HashPosition pos ;
2008-06-18 06:38:47 +00:00
2008-07-20 14:42:34 +00:00
zend_hash_internal_pointer_reset_ex ( & phar - > mounted_dirs , & pos ) ;
while ( FAILURE ! = zend_hash_has_more_elements_ex ( & phar - > mounted_dirs , & pos ) ) {
if ( HASH_KEY_NON_EXISTANT = = zend_hash_get_current_key_ex ( & phar - > mounted_dirs , & key , & keylen , & unused , 0 , & pos ) ) {
2008-05-12 21:03:49 +00:00
break ;
}
2008-06-18 06:38:47 +00:00
PHAR_STR ( key , str_key ) ;
if ( ( int ) keylen > = internal_file_len | | strncmp ( str_key , internal_file , keylen ) ) {
2008-08-01 13:48:45 +00:00
zend_hash_move_forward_ex ( & phar - > mounted_dirs , & pos ) ;
2008-06-18 06:38:47 +00:00
continue ;
} else {
char * test ;
int test_len ;
php_stream_statbuf ssbi ;
if ( SUCCESS ! = zend_hash_find ( & phar - > manifest , str_key , keylen , ( void * * ) & entry ) ) {
goto free_resource ;
}
if ( ! entry - > tmp | | ! entry - > is_mounted ) {
goto free_resource ;
2008-05-12 21:03:49 +00:00
}
2008-06-18 06:38:47 +00:00
test_len = spprintf ( & test , MAXPATHLEN , " %s%s " , entry - > tmp , internal_file + keylen ) ;
if ( SUCCESS ! = php_stream_stat_path ( test , & ssbi ) ) {
efree ( test ) ;
2008-08-01 13:48:45 +00:00
zend_hash_move_forward_ex ( & phar - > mounted_dirs , & pos ) ;
2008-05-12 21:03:49 +00:00
continue ;
2008-06-18 06:38:47 +00:00
}
/* mount the file/directory just in time */
if ( SUCCESS ! = phar_mount_entry ( phar , test , test_len , internal_file , internal_file_len TSRMLS_CC ) ) {
2008-05-12 21:03:49 +00:00
efree ( test ) ;
2008-06-18 06:38:47 +00:00
goto free_resource ;
}
efree ( test ) ;
if ( SUCCESS ! = zend_hash_find ( & phar - > manifest , internal_file , internal_file_len , ( void * * ) & entry ) ) {
goto free_resource ;
2008-05-12 21:03:49 +00:00
}
2008-09-13 22:30:55 +00:00
phar_dostat ( phar , entry , ssb , 0 TSRMLS_CC ) ;
2008-06-18 06:38:47 +00:00
php_url_free ( resource ) ;
return SUCCESS ;
2008-05-12 21:03:49 +00:00
}
}
}
free_resource :
php_url_free ( resource ) ;
return FAILURE ;
}
/* }}} */
/**
* Unlink a file within a phar archive
*/
static int phar_wrapper_unlink ( php_stream_wrapper * wrapper , char * url , int options , php_stream_context * context TSRMLS_DC ) /* { { { */
{
php_url * resource ;
char * internal_file , * error ;
2008-08-31 06:47:38 +00:00
int internal_file_len ;
2008-05-12 21:03:49 +00:00
phar_entry_data * idata ;
phar_archive_data * * pphar ;
uint host_len ;
2008-05-30 22:38:46 +00:00
if ( ( resource = phar_parse_url ( wrapper , url , " rb " , options TSRMLS_CC ) ) = = NULL ) {
2008-05-12 21:03:49 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: unlink failed " ) ;
return 0 ;
}
/* we must have at the very least phar://alias.phar/internalfile.php */
if ( ! resource - > scheme | | ! resource - > host | | ! resource - > path ) {
php_url_free ( resource ) ;
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: invalid url \" %s \" " , url ) ;
return 0 ;
}
if ( strcasecmp ( " phar " , resource - > scheme ) ) {
php_url_free ( resource ) ;
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: not a phar stream url \" %s \" " , url ) ;
return 0 ;
}
host_len = strlen ( resource - > host ) ;
phar_request_initialize ( TSRMLS_C ) ;
2008-08-31 06:47:38 +00:00
if ( FAILURE = = zend_hash_find ( & ( PHAR_GLOBALS - > phar_fname_map ) , resource - > host , host_len , ( void * * ) & pphar ) ) {
2008-05-12 21:03:49 +00:00
pphar = NULL ;
}
if ( PHAR_G ( readonly ) & & ( ! pphar | | ! ( * pphar ) - > is_data ) ) {
php_url_free ( resource ) ;
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: write operations disabled by INI setting " ) ;
return 0 ;
}
/* need to copy to strip leading "/", will get touched again */
internal_file = estrdup ( resource - > path + 1 ) ;
2008-08-31 06:47:38 +00:00
internal_file_len = strlen ( internal_file ) ;
if ( FAILURE = = phar_get_entry_data ( & idata , resource - > host , host_len , internal_file , internal_file_len , " r " , 0 , & error , 1 TSRMLS_CC ) ) {
2008-05-12 21:03:49 +00:00
/* constraints of fp refcount were not met */
if ( error ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " unlink of \" %s \" failed: %s " , url , error ) ;
efree ( error ) ;
} else {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " unlink of \" %s \" failed, file does not exist " , url ) ;
}
efree ( internal_file ) ;
php_url_free ( resource ) ;
return 0 ;
}
if ( error ) {
efree ( error ) ;
}
if ( idata - > internal_file - > fp_refcount > 1 ) {
2008-08-01 13:48:45 +00:00
/* more than just our fp resource is open for this file */
2008-05-12 21:03:49 +00:00
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , " phar error: \" %s \" in phar \" %s \" , has open file pointers, cannot unlink " , internal_file , resource - > host ) ;
efree ( internal_file ) ;
php_url_free ( resource ) ;
phar_entry_delref ( idata TSRMLS_CC ) ;
return 0 ;
}
php_url_free ( resource ) ;
efree ( internal_file ) ;
phar_entry_remove ( idata , & error TSRMLS_CC ) ;
if ( error ) {
php_stream_wrapper_log_error ( wrapper , options TSRMLS_CC , error ) ;
efree ( error ) ;
}
return 1 ;
}
/* }}} */
static int phar_wrapper_rename ( php_stream_wrapper * wrapper , char * url_from , char * url_to , int options , php_stream_context * context TSRMLS_DC ) /* { { { */
{
php_url * resource_from , * resource_to ;
char * error ;
phar_archive_data * phar , * pfrom , * pto ;
phar_entry_info * entry ;
uint host_len ;
2008-07-20 14:42:34 +00:00
int is_dir = 0 ;
int is_modified = 0 ;
2008-05-12 21:03:49 +00:00
error = NULL ;
2008-05-30 22:38:46 +00:00
if ( ( resource_from = phar_parse_url ( wrapper , url_from , " wb " , options | PHP_STREAM_URL_STAT_QUIET TSRMLS_CC ) ) = = NULL ) {
2008-05-12 21:03:49 +00:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " phar error: cannot rename \" %s \" to \" %s \" : invalid or non-writable url \" %s \" " , url_from , url_to , url_from ) ;
return 0 ;
}
if ( SUCCESS ! = phar_get_archive ( & pfrom , resource_from - > host , strlen ( resource_from - > host ) , NULL , 0 , & error TSRMLS_CC ) ) {
pfrom = NULL ;
if ( error ) {
efree ( error ) ;
}
}
if ( PHAR_G ( readonly ) & & ( ! pfrom | | ! pfrom - > is_data ) ) {
php_url_free ( resource_from ) ;
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " phar error: write operations disabled by phar.readonly INI setting " ) ;
return 0 ;
}
2008-05-30 22:38:46 +00:00
if ( ( resource_to = phar_parse_url ( wrapper , url_to , " wb " , options | PHP_STREAM_URL_STAT_QUIET TSRMLS_CC ) ) = = NULL ) {
2008-05-12 21:03:49 +00:00
php_url_free ( resource_from ) ;
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " phar error: cannot rename \" %s \" to \" %s \" : invalid or non-writable url \" %s \" " , url_from , url_to , url_to ) ;
return 0 ;
}
if ( SUCCESS ! = phar_get_archive ( & pto , resource_to - > host , strlen ( resource_to - > host ) , NULL , 0 , & error TSRMLS_CC ) ) {
if ( error ) {
efree ( error ) ;
}
pto = NULL ;
}
if ( PHAR_G ( readonly ) & & ( ! pto | | ! pto - > is_data ) ) {
php_url_free ( resource_from ) ;
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " phar error: write operations disabled by phar.readonly INI setting " ) ;
return 0 ;
}
if ( strcmp ( resource_from - > host , resource_to - > host ) ) {
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " phar error: cannot rename \" %s \" to \" %s \" , not within the same phar archive " , url_from , url_to ) ;
return 0 ;
}
/* we must have at the very least phar://alias.phar/internalfile.php */
if ( ! resource_from - > scheme | | ! resource_from - > host | | ! resource_from - > path ) {
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " phar error: cannot rename \" %s \" to \" %s \" : invalid url \" %s \" " , url_from , url_to , url_from ) ;
return 0 ;
}
2008-08-01 13:48:45 +00:00
2008-05-12 21:03:49 +00:00
if ( ! resource_to - > scheme | | ! resource_to - > host | | ! resource_to - > path ) {
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " phar error: cannot rename \" %s \" to \" %s \" : invalid url \" %s \" " , url_from , url_to , url_to ) ;
return 0 ;
}
if ( strcasecmp ( " phar " , resource_from - > scheme ) ) {
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " phar error: cannot rename \" %s \" to \" %s \" : not a phar stream url \" %s \" " , url_from , url_to , url_from ) ;
return 0 ;
}
if ( strcasecmp ( " phar " , resource_to - > scheme ) ) {
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " phar error: cannot rename \" %s \" to \" %s \" : not a phar stream url \" %s \" " , url_from , url_to , url_to ) ;
return 0 ;
}
host_len = strlen ( resource_from - > host ) ;
2008-08-31 06:47:38 +00:00
if ( SUCCESS ! = phar_get_archive ( & phar , resource_from - > host , host_len , NULL , 0 , & error TSRMLS_CC ) ) {
2008-05-12 21:03:49 +00:00
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " phar error: cannot rename \" %s \" to \" %s \" : %s " , url_from , url_to , error ) ;
efree ( error ) ;
return 0 ;
}
2008-06-18 06:38:47 +00:00
if ( phar - > is_persistent & & FAILURE = = phar_copy_on_write ( & phar TSRMLS_CC ) ) {
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " phar error: cannot rename \" %s \" to \" %s \" : could not make cached phar writeable " , url_from , url_to ) ;
return 0 ;
}
2008-05-12 21:03:49 +00:00
if ( SUCCESS = = zend_hash_find ( & ( phar - > manifest ) , resource_from - > path + 1 , strlen ( resource_from - > path ) - 1 , ( void * * ) & entry ) ) {
phar_entry_info new , * source ;
/* perform rename magic */
if ( entry - > is_deleted ) {
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " phar error: cannot rename \" %s \" to \" %s \" from extracted phar archive, source has been deleted " , url_from , url_to ) ;
return 0 ;
}
/* transfer all data over to the new entry */
memcpy ( ( void * ) & new , ( void * ) entry , sizeof ( phar_entry_info ) ) ;
/* mark the old one for deletion */
entry - > is_deleted = 1 ;
entry - > fp = NULL ;
entry - > metadata = 0 ;
entry - > link = entry - > tmp = NULL ;
source = entry ;
/* add to the manifest, and then store the pointer to the new guy in entry */
zend_hash_add ( & ( phar - > manifest ) , resource_to - > path + 1 , strlen ( resource_to - > path ) - 1 , ( void * * ) & new , sizeof ( phar_entry_info ) , ( void * * ) & entry ) ;
entry - > filename = estrdup ( resource_to - > path + 1 ) ;
if ( FAILURE = = phar_copy_entry_fp ( source , entry , & error TSRMLS_CC ) ) {
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " phar error: cannot rename \" %s \" to \" %s \" : %s " , url_from , url_to , error ) ;
efree ( error ) ;
zend_hash_del ( & ( phar - > manifest ) , entry - > filename , strlen ( entry - > filename ) ) ;
return 0 ;
}
2008-07-20 14:42:34 +00:00
is_modified = 1 ;
2008-05-12 21:03:49 +00:00
entry - > is_modified = 1 ;
entry - > filename_len = strlen ( entry - > filename ) ;
2008-07-20 14:42:34 +00:00
is_dir = entry - > is_dir ;
} else {
is_dir = zend_hash_exists ( & ( phar - > virtual_dirs ) , resource_from - > path + 1 , strlen ( resource_from - > path ) - 1 ) ;
}
/* Rename directory. Update all nested paths */
if ( is_dir ) {
int key_type ;
2008-08-30 23:47:55 +00:00
phar_zstr key , new_key ;
char * str_key , * new_str_key ;
2008-07-20 14:42:34 +00:00
uint key_len , new_key_len ;
ulong unused ;
uint from_len = strlen ( resource_from - > path + 1 ) ;
uint to_len = strlen ( resource_to - > path + 1 ) ;
for ( zend_hash_internal_pointer_reset ( & phar - > manifest ) ;
2008-08-01 13:48:45 +00:00
HASH_KEY_NON_EXISTANT ! = ( key_type = zend_hash_get_current_key_ex ( & phar - > manifest , & key , & key_len , & unused , 0 , NULL ) ) & &
SUCCESS = = zend_hash_get_current_data ( & phar - > manifest , ( void * * ) & entry ) ;
zend_hash_move_forward ( & phar - > manifest ) ) {
2008-07-20 14:42:34 +00:00
2008-08-30 23:47:55 +00:00
PHAR_STR ( key , str_key ) ;
2008-07-20 14:42:34 +00:00
if ( ! entry - > is_deleted & &
2008-08-01 13:48:45 +00:00
key_len > from_len & &
2008-08-30 23:47:55 +00:00
memcmp ( str_key , resource_from - > path + 1 , from_len ) = = 0 & &
IS_SLASH ( str_key [ from_len ] ) ) {
2008-07-20 14:42:34 +00:00
new_key_len = key_len + to_len - from_len ;
2008-08-30 23:47:55 +00:00
new_str_key = emalloc ( new_key_len + 1 ) ;
memcpy ( new_str_key , resource_to - > path + 1 , to_len ) ;
memcpy ( new_str_key + to_len , str_key + from_len , key_len - from_len ) ;
new_str_key [ new_key_len ] = 0 ;
2008-08-31 02:14:03 +00:00
2008-07-20 14:42:34 +00:00
is_modified = 1 ;
entry - > is_modified = 1 ;
efree ( entry - > filename ) ;
2008-08-30 23:47:55 +00:00
entry - > filename = new_str_key ;
2008-07-20 14:42:34 +00:00
entry - > filename_len = new_key_len ;
2008-08-30 23:47:55 +00:00
PHAR_ZSTR ( new_str_key , new_key ) ;
# if PHP_VERSION_ID < 50300
zend_hash_update_current_key_ex ( & phar - > manifest , key_type , new_key , new_key_len , 0 , NULL ) ;
# else
2008-08-01 14:22:48 +00:00
zend_hash_update_current_key_ex ( & phar - > manifest , key_type , new_key , new_key_len , 0 , HASH_UPDATE_KEY_ANYWAY , NULL ) ;
2008-08-30 23:47:55 +00:00
# endif
2008-07-20 14:42:34 +00:00
}
2008-08-01 13:48:45 +00:00
}
2008-07-20 14:42:34 +00:00
for ( zend_hash_internal_pointer_reset ( & phar - > virtual_dirs ) ;
2008-08-01 13:48:45 +00:00
HASH_KEY_NON_EXISTANT ! = ( key_type = zend_hash_get_current_key_ex ( & phar - > virtual_dirs , & key , & key_len , & unused , 0 , NULL ) ) ;
zend_hash_move_forward ( & phar - > virtual_dirs ) ) {
2008-07-20 14:42:34 +00:00
2008-08-30 23:47:55 +00:00
PHAR_STR ( key , str_key ) ;
2008-07-20 14:42:34 +00:00
if ( key_len > = from_len & &
2008-08-30 23:47:55 +00:00
memcmp ( str_key , resource_from - > path + 1 , from_len ) = = 0 & &
( key_len = = from_len | | IS_SLASH ( str_key [ from_len ] ) ) ) {
2008-07-20 14:42:34 +00:00
new_key_len = key_len + to_len - from_len ;
2008-08-30 23:47:55 +00:00
new_str_key = emalloc ( new_key_len + 1 ) ;
memcpy ( new_str_key , resource_to - > path + 1 , to_len ) ;
memcpy ( new_str_key + to_len , str_key + from_len , key_len - from_len ) ;
new_str_key [ new_key_len ] = 0 ;
PHAR_ZSTR ( new_str_key , new_key ) ;
# if PHP_VERSION_ID < 50300
zend_hash_update_current_key_ex ( & phar - > virtual_dirs , key_type , new_key , new_key_len , 0 , NULL ) ;
# else
2008-08-01 14:22:48 +00:00
zend_hash_update_current_key_ex ( & phar - > virtual_dirs , key_type , new_key , new_key_len , 0 , HASH_UPDATE_KEY_ANYWAY , NULL ) ;
2008-08-30 23:47:55 +00:00
# endif
efree ( new_str_key ) ;
2008-07-20 14:42:34 +00:00
}
}
for ( zend_hash_internal_pointer_reset ( & phar - > mounted_dirs ) ;
2008-08-01 13:48:45 +00:00
HASH_KEY_NON_EXISTANT ! = ( key_type = zend_hash_get_current_key_ex ( & phar - > mounted_dirs , & key , & key_len , & unused , 0 , NULL ) ) & &
SUCCESS = = zend_hash_get_current_data ( & phar - > mounted_dirs , ( void * * ) & entry ) ;
zend_hash_move_forward ( & phar - > mounted_dirs ) ) {
2008-07-20 14:42:34 +00:00
2008-08-30 23:47:55 +00:00
PHAR_STR ( key , str_key ) ;
2008-07-20 14:42:34 +00:00
if ( key_len > = from_len & &
2008-08-30 23:47:55 +00:00
memcmp ( str_key , resource_from - > path + 1 , from_len ) = = 0 & &
( key_len = = from_len | | IS_SLASH ( str_key [ from_len ] ) ) ) {
2008-07-20 14:42:34 +00:00
new_key_len = key_len + to_len - from_len ;
2008-08-30 23:47:55 +00:00
new_str_key = emalloc ( new_key_len + 1 ) ;
memcpy ( new_str_key , resource_to - > path + 1 , to_len ) ;
memcpy ( new_str_key + to_len , str_key + from_len , key_len - from_len ) ;
new_str_key [ new_key_len ] = 0 ;
PHAR_ZSTR ( new_str_key , new_key ) ;
# if PHP_VERSION_ID < 50300
zend_hash_update_current_key_ex ( & phar - > mounted_dirs , key_type , new_key , new_key_len , 0 , NULL ) ;
# else
2008-08-01 14:22:48 +00:00
zend_hash_update_current_key_ex ( & phar - > mounted_dirs , key_type , new_key , new_key_len , 0 , HASH_UPDATE_KEY_ANYWAY , NULL ) ;
2008-08-30 23:47:55 +00:00
# endif
efree ( new_str_key ) ;
2008-07-20 14:42:34 +00:00
}
}
}
if ( is_modified ) {
2008-05-12 21:03:49 +00:00
phar_flush ( phar , 0 , 0 , 0 , & error TSRMLS_CC ) ;
if ( error ) {
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " phar error: cannot rename \" %s \" to \" %s \" : %s " , url_from , url_to , error ) ;
efree ( error ) ;
return 0 ;
}
}
2008-07-20 14:42:34 +00:00
2008-05-12 21:03:49 +00:00
php_url_free ( resource_from ) ;
php_url_free ( resource_to ) ;
2008-08-01 13:48:45 +00:00
2008-05-12 21:03:49 +00:00
return 1 ;
}
/* }}} */
2008-07-29 10:52:08 +00:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* End :
* vim600 : noet sw = 4 ts = 4 fdm = marker
* vim < 600 : noet sw = 4 ts = 4
*/