static void print_modules(void) /* {{{ */ { HashTable sorted_registry; zend_hash_init(&sorted_registry, 50, NULL, NULL, 0); zend_hash_copy(&sorted_registry, &module_registry, NULL); zend_hash_sort(&sorted_registry, module_name_cmp, 0); zend_hash_apply(&sorted_registry, print_module_info); zend_hash_destroy(&sorted_registry); }
ZEND_API int zend_ts_hash_sort(TsHashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber) { int retval; begin_write(ht); retval = zend_hash_sort(TS_HASH(ht), sort_func, compare_func, renumber); end_write(ht); return retval; }
/* {{{ _php_regcomp */ static int _php_regcomp(regex_t *preg, const char *pattern, int cflags) { int r = 0; int patlen = strlen(pattern); reg_cache *rc = NULL; if (zend_hash_num_elements(&EREG(ht_rc)) >= EREG_CACHE_SIZE) { /* easier than dealing with overflow as it happens */ if (EREG(lru_counter) >= (1 << 31) || zend_hash_sort(&EREG(ht_rc), zend_qsort, ereg_lru_cmp, 0) == FAILURE) { zend_hash_clean(&EREG(ht_rc)); EREG(lru_counter) = 0; } else { int num_clean = EREG_CACHE_SIZE / 4; zend_hash_apply_with_argument(&EREG(ht_rc), ereg_clean_cache, &num_clean); } } rc = zend_hash_str_find_ptr(&EREG(ht_rc), pattern, patlen); if (rc && rc->cflags == cflags) { #ifdef HAVE_REGEX_T_RE_MAGIC /* * We use a saved magic number to see whether cache is corrupted, and if it * is, we flush it and compile the pattern from scratch. */ if (rc->preg.re_magic != reg_magic) { zend_hash_clean(&EREG(ht_rc)); EREG(lru_counter) = 0; } else { memcpy(preg, &rc->preg, sizeof(*preg)); return r; } } r = regcomp(preg, pattern, cflags); if(!r) { reg_cache rcp; rcp.cflags = cflags; rcp.lastuse = ++(EREG(lru_counter)); memcpy(&rcp.preg, preg, sizeof(*preg)); /* * Since we don't have access to the actual MAGIC1 definition in the private * header file, we save the magic value immediately after compilation. Hopefully, * it's good. */ if (!reg_magic) reg_magic = preg->re_magic; zend_hash_str_update_mem(&EREG(ht_rc), pattern, patlen, &rcp, sizeof(rcp)); } #else memcpy(preg, &rc->preg, sizeof(*preg)); } else {
/* ArchiveWriter::finish {{{ * */ ZEND_METHOD(ArchiveWriter, finish) { zval *this = getThis(); int resource_id; HashPosition pos; archive_file_t *arch; archive_entry_t **entry; int result, error_num; const char *error_string; mode_t mode; php_stream *stream; zend_error_handling error_handling; zend_replace_error_handling(EH_THROW, ce_ArchiveException, &error_handling TSRMLS_CC); if (!_archive_get_fd(this, &arch TSRMLS_CC)) { zend_restore_error_handling(&error_handling TSRMLS_CC); return; } if (zend_hash_sort(arch->entries, zend_qsort, _archive_pathname_compare, 0 TSRMLS_CC) == FAILURE) { RETURN_FALSE; } zend_hash_internal_pointer_reset_ex(arch->entries, &pos); while (zend_hash_get_current_data_ex(arch->entries, (void **)&entry, &pos) == SUCCESS) { mode = archive_entry_mode((*entry)->entry); if (S_ISREG(mode) && archive_entry_size((*entry)->entry) > 0) { if ((stream = php_stream_open_wrapper_ex((*entry)->filename, "r", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, NULL))) { char buf[PHP_ARCHIVE_BUF_LEN]; int header_written=0; int read_bytes; while ((read_bytes = php_stream_read(stream, buf, PHP_ARCHIVE_BUF_LEN))) { if (!header_written) { /* write header only after the first successful read */ result = archive_write_header(arch->arch, (*entry)->entry); if (result == ARCHIVE_FATAL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write entry header for file %s: fatal error", (*entry)->filename); zend_restore_error_handling(&error_handling TSRMLS_CC); return; } header_written = 1; } result = archive_write_data(arch->arch, buf, read_bytes); if (result <= 0) { error_num = archive_errno(arch->arch); error_string = archive_error_string(arch->arch); if (error_num && error_string) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write file %s to archive: error #%d, %s", (*entry)->filename, error_num, error_string); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write file %s: unknown error %d", (*entry)->filename, result); } php_stream_close(stream); zend_restore_error_handling(&error_handling TSRMLS_CC); return; } } php_stream_close(stream); } } else { result = archive_write_header(arch->arch, (*entry)->entry); if (result == ARCHIVE_FATAL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write entry header for file %s: fatal error", (*entry)->filename); zend_restore_error_handling(&error_handling TSRMLS_CC); return; } } zend_hash_move_forward_ex(arch->entries, &pos); } if ((resource_id = _archive_get_rsrc_id(this TSRMLS_CC))) { add_property_resource(this, "fd", 0); zend_list_delete(resource_id); zend_restore_error_handling(&error_handling TSRMLS_CC); RETURN_TRUE; } php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to finish writing of archive file"); zend_restore_error_handling(&error_handling TSRMLS_CC); }
/** * Create a opendir() directory stream handle by iterating over each of the * files in a phar and retrieving its relative path. From this, construct * a list of files/directories that are "in" the directory represented by dir */ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest) /* {{{ */ { HashTable *data; size_t dirlen = strlen(dir); char *entry, *found, *save; zend_string *str_key; uint32_t keylen; zend_ulong unused; ALLOC_HASHTABLE(data); zend_hash_init(data, 64, NULL, NULL, 0); if ((*dir == '/' && dirlen == 1 && (manifest->nNumOfElements == 0)) || (dirlen >= sizeof(".phar")-1 && !memcmp(dir, ".phar", sizeof(".phar")-1))) { /* make empty root directory for empty phar */ /* make empty directory for .phar magic directory */ efree(dir); return php_stream_alloc(&phar_dir_ops, data, NULL, "r"); } zend_hash_internal_pointer_reset(manifest); while (FAILURE != zend_hash_has_more_elements(manifest)) { if (HASH_KEY_NON_EXISTENT == zend_hash_get_current_key(manifest, &str_key, &unused)) { break; } keylen = ZSTR_LEN(str_key); if (keylen <= (uint32_t)dirlen) { if (keylen == 0 || keylen < (uint32_t)dirlen || !strncmp(ZSTR_VAL(str_key), dir, dirlen)) { if (SUCCESS != zend_hash_move_forward(manifest)) { break; } continue; } } if (*dir == '/') { /* root directory */ if (keylen >= sizeof(".phar")-1 && !memcmp(ZSTR_VAL(str_key), ".phar", sizeof(".phar")-1)) { /* do not add any magic entries to this directory */ if (SUCCESS != zend_hash_move_forward(manifest)) { break; } continue; } if (NULL != (found = (char *) memchr(ZSTR_VAL(str_key), '/', keylen))) { /* the entry has a path separator and is a subdirectory */ entry = (char *) safe_emalloc(found - ZSTR_VAL(str_key), 1, 1); memcpy(entry, ZSTR_VAL(str_key), found - ZSTR_VAL(str_key)); keylen = found - ZSTR_VAL(str_key); entry[keylen] = '\0'; } else { entry = (char *) safe_emalloc(keylen, 1, 1); memcpy(entry, ZSTR_VAL(str_key), keylen); entry[keylen] = '\0'; } goto PHAR_ADD_ENTRY; } else { if (0 != memcmp(ZSTR_VAL(str_key), dir, dirlen)) { /* entry in directory not found */ if (SUCCESS != zend_hash_move_forward(manifest)) { break; } continue; } else { if (ZSTR_VAL(str_key)[dirlen] != '/') { if (SUCCESS != zend_hash_move_forward(manifest)) { break; } continue; } } } save = ZSTR_VAL(str_key); save += dirlen + 1; /* seek to just past the path separator */ if (NULL != (found = (char *) memchr(save, '/', keylen - dirlen - 1))) { /* is subdirectory */ save -= dirlen + 1; entry = (char *) safe_emalloc(found - save + dirlen, 1, 1); memcpy(entry, save + dirlen + 1, found - save - dirlen - 1); keylen = found - save - dirlen - 1; entry[keylen] = '\0'; } else { /* is file */ save -= dirlen + 1; entry = (char *) safe_emalloc(keylen - dirlen, 1, 1); memcpy(entry, save + dirlen + 1, keylen - dirlen - 1); entry[keylen - dirlen - 1] = '\0'; keylen = keylen - dirlen - 1; } PHAR_ADD_ENTRY: if (keylen) { phar_add_empty(data, entry, keylen); } efree(entry); if (SUCCESS != zend_hash_move_forward(manifest)) { break; } } if (FAILURE != zend_hash_has_more_elements(data)) { efree(dir); if (zend_hash_sort(data, phar_compare_dir_name, 0) == FAILURE) { FREE_HASHTABLE(data); return NULL; } return php_stream_alloc(&phar_dir_ops, data, NULL, "r"); } else { efree(dir); return php_stream_alloc(&phar_dir_ops, data, NULL, "r"); } }