]> granicus.if.org Git - php/commitdiff
fix stat of directory in tar/zip
authorGreg Beaver <cellog@php.net>
Mon, 7 Jan 2008 05:41:09 +0000 (05:41 +0000)
committerGreg Beaver <cellog@php.net>
Mon, 7 Jan 2008 05:41:09 +0000 (05:41 +0000)
improve phar recognition of tar/zip-based phars in phar_compile_file
fix segfault in Phar::webPhar() with invalid redirect
add Phar->isTar()/isZip()/isPhar() to determine internal file format
fix creation of tar-based phars from filename in some circumstances
fix read of corrupted file contents from a tar if the tar had been opened readonly and then modified
ensure directories are marked with is_dir in tar file format entries
copy fp_refcount logic into phar_tar_flush() from phar_flush()
fix segfault when flushing a tar with a new stub/alias

ext/phar/phar.c
ext/phar/phar_object.c
ext/phar/tar.c

index 735198d85e6a07e88707d9d392e59aa037aae3c7..aa566b39420b7f07128f0b5b53b671101de78ee0 100644 (file)
@@ -4027,6 +4027,20 @@ static void phar_dostat(phar_archive_data *phar, phar_entry_info *data, php_stre
                ssb->sb.st_mtime = data->timestamp;
                ssb->sb.st_atime = data->timestamp;
                ssb->sb.st_ctime = data->timestamp;
+#endif
+       } else if (!is_dir && data->is_dir && (data->is_tar || data->is_zip)) {
+               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;
@@ -4719,34 +4733,26 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type
        char *fname = NULL;
        int fname_len, failed;
        zend_op_array *(*save)(zend_file_handle *file_handle, int type TSRMLS_DC);
+       phar_archive_data *phar;
 
        save = zend_compile_file; /* restore current handler or we cause trouble */
        zend_compile_file = phar_orig_compile_file;
 
        fname = zend_get_executed_filename(TSRMLS_C);
        fname_len = strlen(fname);
-       if (fname_len == sizeof("[no active file]")-1 && !strncmp(fname, "[no active file]", fname_len)) {
-               if (strstr(file_handle->filename, ".phar.zip") && !strstr(file_handle->filename, ":\\")) {
-                       /* zip-based phar */
-                       spprintf(&name, 4096, "phar://%s/%s", file_handle->filename, ".phar/stub.php");
-                       file_handle->type = ZEND_HANDLE_FILENAME;
-                       file_handle->free_filename = 1;
-                       file_handle->filename = name;
-                       if (file_handle->opened_path) {
-                               efree(file_handle->opened_path);
-                       }
-                       goto skip_phar;
-               }
-               if (strstr(file_handle->filename, ".phar.tar") && !strstr(file_handle->filename, ":\\")) {
-                       /* tar-based phar */
-                       spprintf(&name, 4096, "phar://%s/%s", file_handle->filename, ".phar/stub.php");
-                       file_handle->type = ZEND_HANDLE_FILENAME;
-                       file_handle->free_filename = 1;
-                       file_handle->filename = name;
-                       if (file_handle->opened_path) {
-                               efree(file_handle->opened_path);
+       if (strstr(file_handle->filename, ".phar") && !strstr(file_handle->filename, ":\\")) {
+               if (SUCCESS == phar_open_filename(file_handle->filename, strlen(file_handle->filename), NULL, 0, 0, &phar, NULL TSRMLS_CC)) {
+                       if (phar->is_zip || phar->is_tar) {
+                               /* zip-based phar */
+                               spprintf(&name, 4096, "phar://%s/%s", file_handle->filename, ".phar/stub.php");
+                               file_handle->type = ZEND_HANDLE_FILENAME;
+                               file_handle->free_filename = 1;
+                               file_handle->filename = name;
+                               if (file_handle->opened_path) {
+                                       efree(file_handle->opened_path);
+                               }
+                               goto skip_phar;
                        }
-                       goto skip_phar;
                }
        }
        if (zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) {
index 883c61affa09fea40f5227283e609b8e86af9a1f..28534bcd6cc60435dfcaef3c804030e6278825ee 100755 (executable)
@@ -382,7 +382,7 @@ PHP_METHOD(Phar, webPhar)
        if (strstr(fname, "://")) {
                char *arch, *entry;
                int arch_len, entry_len;
-               phar_archive_data *phar;
+               phar_archive_data *mphar;
 
                /* running within a zip-based phar, acquire the actual name */
                if (SUCCESS != phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len TSRMLS_CC)) {
@@ -395,10 +395,10 @@ PHP_METHOD(Phar, webPhar)
                entry = fname;
                fname = arch;
                fname_len = arch_len;
-               if (SUCCESS == phar_open_loaded(fname, fname_len, alias, alias_len, 0, &phar, 0 TSRMLS_CC) && phar && (phar->is_zip || phar->is_tar)) {
+               if (SUCCESS == phar_open_loaded(fname, fname_len, alias, alias_len, 0, &mphar, 0 TSRMLS_CC) && mphar && (phar->is_zip || phar->is_tar)) {
                        efree(arch);
-                       fname = phar->fname;
-                       fname_len = phar->fname_len;
+                       fname = mphar->fname;
+                       fname_len = mphar->fname_len;
                } else {
                        efree(arch);
                        fname = entry;
@@ -476,7 +476,6 @@ PHP_METHOD(Phar, webPhar)
                /* check for "rewrite" urls */
                if (SUCCESS == zend_hash_find(Z_ARRVAL_P(rewrites), entry, entry_len+1, (void **) &fd_ptr)) {
                        if (IS_STRING != Z_TYPE_PP(fd_ptr)) {
-                               phar_entry_delref(phar TSRMLS_CC);
 #ifdef PHP_WIN32
                                efree(fname);
 #endif
@@ -1218,6 +1217,39 @@ PHP_METHOD(Phar, count)
 }
 /* }}} */
 
+/* {{{ proto bool Phar::isTar()
+ * Returns true if the phar archive is based on the tar file format
+ */
+PHP_METHOD(Phar, isTar)
+{
+       PHAR_ARCHIVE_OBJECT();
+       
+       RETURN_BOOL(phar_obj->arc.archive->is_tar);
+}
+/* }}} */
+
+/* {{{ proto bool Phar::isZip()
+ * Returns true if the phar archive is based on the Zip file format
+ */
+PHP_METHOD(Phar, isZip)
+{
+       PHAR_ARCHIVE_OBJECT();
+       
+       RETURN_BOOL(phar_obj->arc.archive->is_zip);
+}
+/* }}} */
+
+/* {{{ proto bool Phar::isPhar()
+ * Returns true if the phar archive is based on the phar file format
+ */
+PHP_METHOD(Phar, isPhar)
+{
+       PHAR_ARCHIVE_OBJECT();
+       
+       RETURN_BOOL(!phar_obj->arc.archive->is_tar && !phar_obj->arc.archive->is_zip);
+}
+/* }}} */
+
 /* {{{ proto bool Phar::delete(string file)
  * Delete a file from within the Phar
  */
@@ -2217,8 +2249,8 @@ PHP_METHOD(PharFileInfo, __destruct)
 {
        PHAR_ENTRY_OBJECT();
 
-       if (entry_obj->ent.entry->is_dir) {
-               if (!entry_obj->ent.entry->is_zip && !entry_obj->ent.entry->is_tar && entry_obj->ent.entry->filename) {
+       if (entry_obj->ent.entry->is_dir&& !entry_obj->ent.entry->is_zip && !entry_obj->ent.entry->is_tar) {
+               if (entry_obj->ent.entry->filename) {
                        efree(entry_obj->ent.entry->filename);
                        entry_obj->ent.entry->filename = NULL;
                }
@@ -2323,7 +2355,7 @@ PHP_METHOD(PharFileInfo, chmod)
        long perms;
        PHAR_ENTRY_OBJECT();
 
-       if (entry_obj->ent.entry->is_dir) {
+       if (entry_obj->ent.entry->is_dir && (!entry_obj->ent.entry->is_tar && !entry_obj->ent.entry->is_zip)) {
                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
                        "Phar entry is a directory, cannot chmod"); \
        }
@@ -2728,6 +2760,9 @@ zend_function_entry php_archive_methods[] = {
        PHP_ME(Phar, offsetUnset,           arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
        PHP_ME(Phar, uncompressAllFiles,    NULL,                      ZEND_ACC_PUBLIC)
        PHP_ME(Phar, buildFromIterator,     arginfo_phar_build,        ZEND_ACC_PUBLIC)
+       PHP_ME(Phar, isTar,                 NULL,                      ZEND_ACC_PUBLIC)
+       PHP_ME(Phar, isZip,                 NULL,                      ZEND_ACC_PUBLIC)
+       PHP_ME(Phar, isPhar,                NULL,                      ZEND_ACC_PUBLIC)
 #endif
        /* static member functions */
        PHP_ME(Phar, apiVersion,            NULL,                      ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
index 795afd3a1db7d8b092a9ac70c9cdff179b5784d1..5ce834dcd94ebddd6eeeffdb36c14e0253eab50c 100644 (file)
@@ -125,18 +125,20 @@ int phar_is_tar(char *buf)
 int phar_open_or_create_tar(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC) /* {{{ */
 {
        phar_archive_data *phar;
-       int ret = phar_create_or_parse_filename(fname, fname_len, alias, alias_len, options, pphar, error TSRMLS_CC);
+       int ret = phar_create_or_parse_filename(fname, fname_len, alias, alias_len, options, &phar, error TSRMLS_CC);
 
+       if (pphar) {
+               *pphar = phar;
+       }
        if (FAILURE == ret) {
                return FAILURE;
        }
-       if ((*pphar)->is_tar) {
+       if (phar->is_tar) {
                return ret;
        }
-
-       phar = *pphar;
        if (phar->is_brandnew) {
                phar->is_tar = 1;
+               phar->internal_file_start = 0;
                return SUCCESS;
        }
 
@@ -231,6 +233,9 @@ int phar_open_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, i
                if (old && entry.tar_type == TAR_FILE && S_ISDIR(entry.flags)) {
                        entry.tar_type = TAR_DIR;
                }
+               if (entry.tar_type == TAR_DIR) {
+                       entry.is_dir = 1;
+               }
 
                entry.link = NULL;
                if (entry.tar_type == TAR_LINK) {
@@ -366,7 +371,11 @@ int phar_tar_writeheaders(void *pDest, void *argument TSRMLS_DC)
        if (entry->fp) {
                /* new file */
                file = entry->fp;
-               php_stream_seek(file, 0, SEEK_SET);
+               if (file == entry->phar->fp) {
+                       php_stream_seek(file, entry->offset_within_phar, SEEK_SET);
+               } else {
+                       php_stream_seek(file, 0, SEEK_SET);
+               }
        } else {
                file = fp->old;
                php_stream_seek(file, entry->offset_within_phar, SEEK_SET);
@@ -381,9 +390,12 @@ int phar_tar_writeheaders(void *pDest, void *argument TSRMLS_DC)
        memset(padding, 0, 512);
        php_stream_write(fp->new, padding, ((entry->uncompressed_filesize +511)&~511) - entry->uncompressed_filesize);
 
-       if (entry->fp) {
-               php_stream_close(entry->fp);
-               entry->fp = NULL;
+       entry->is_modified = 0;
+       if (entry->fp && entry->fp_refcount == 0) {
+               if (entry->fp != entry->phar->fp) {
+                       php_stream_close(entry->fp);
+                       entry->fp = NULL;
+               }
        }
 
        /* note new location within tar */
@@ -405,6 +417,7 @@ int phar_tar_flush(phar_archive_data *archive, char *user_stub, long len, char *
        entry.is_modified = 1;
        entry.is_tar = 1;
        entry.tar_type = '0';
+       entry.phar = archive;
        /* set alias */
        if (archive->is_explicit_alias) {
                entry.filename = estrndup(".phar/alias.txt", sizeof(".phar/alias.txt")-1);