MFHead @348740

Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Alan Somers 2019-06-06 16:20:50 +00:00
commit 0269ae4c19
1898 changed files with 30864 additions and 75564 deletions

View File

@ -4,7 +4,8 @@
# The user-driven targets are:
#
# universe - *Really* build *everything* (buildworld and
# all kernels on all architectures).
# all kernels on all architectures). Define the
# MAKE_JUST_KERNELS variable to only build kernels.
# tinderbox - Same as universe, but presents a list of failed build
# targets and exits with an error if there were any.
# buildworld - Rebuild *everything*, including glue to help do
@ -45,12 +46,6 @@
# native-xtools-install
# - Install the files to the given DESTDIR/NXTP where
# NXTP defaults to /nxb-bin.
#
# "quick" way to test all kernel builds:
# _jflag=`sysctl -n hw.ncpu`
# _jflag=$(($_jflag * 2))
# [ $_jflag -gt 12 ] && _jflag=12
# make universe -DMAKE_JUST_KERNELS JFLAG=-j${_jflag}
#
# This makefile is simple by design. The FreeBSD make automatically reads
# the /usr/share/mk/sys.mk unless the -m argument is specified on the

View File

@ -939,13 +939,8 @@ _sanity_check: .PHONY .MAKE
_cleanobj_fast_depend_hack: .PHONY
# Syscall stubs rewritten in C and obsolete MD assembly implementations
# Date SVN Rev Syscalls
# 20180404 r332048 sigreturn
# 20180405 r332080 shmat
# 20180406 r332119 setlogin
# 20180411 r332443 exect
# 20180525 r334224 vadvise
# 20180604 r334626 brk sbrk
.for f in brk exect sbrk setlogin shmat sigreturn vadvise
.for f in brk sbrk
@if [ -e "${OBJTOP}/lib/libc/.depend.${f}.o" ] && \
egrep -qw '${f}\.[sS]' ${OBJTOP}/lib/libc/.depend.${f}.o; then \
echo "Removing stale dependencies for ${f} syscall wrappers"; \
@ -2105,7 +2100,8 @@ _bootstrap_tools_links+=m4 lex
# r334881 added libdwarf constants used by ctfconvert.
# r338478 fixed a crash in objcopy for mips64el objects
# r339083 libelf: correct mips64el test to use ELF header
.if ${BOOTSTRAPPING} < 1200085
# r348347 Add missing powerpc64 relocation support to libdwarf
.if ${BOOTSTRAPPING} < 1300030
_elftoolchain_libs= lib/libelf lib/libdwarf
${_bt}-lib/libelf: ${_bt_m4_depend}
${_bt}-lib/libdwarf: ${_bt_m4_depend}

View File

@ -38,9 +38,44 @@
# xargs -n1 | sort | uniq -d;
# done
# 20190523: Remove obsolete kgzip and support files
OLD_FILES+=usr/sbin/kgzip
OLD_FILES+=usr/lib/kgzldr.o
OLD_FILES+=usr/share/man/man8/kgzip.8.gz
# 20190517: Remove obsolete 10 and 10/100 ethernet drivers.
OLD_FILES+=usr/share/man/man4/bm.4.gz
OLD_FILES+=usr/share/man/man4/cs.4.gz
OLD_FILES+=usr/share/man/man4/de.4.gz
OLD_FILES+=usr/share/man/man4/if_de.4.gz
OLD_FILES+=usr/share/man/man4/ed.4.gz
OLD_FILES+=usr/share/man/man4/if_ed.4.gz
OLD_FILES+=usr/share/man/man4/ep.4.gz
OLD_FILES+=usr/share/man/man4/ex.4.gz
OLD_FILES+=usr/share/man/man4/fe.4.gz
OLD_FILES+=usr/share/man/man4/pcn.4.gz
OLD_FILES+=usr/share/man/man4/if_pcn.4.gz
OLD_FILES+=usr/share/man/man4/sf.4.gz
OLD_FILES+=usr/share/man/man4/if_sf.4.gz
OLD_FILES+=usr/share/man/man4/sn.4.gz
OLD_FILES+=usr/share/man/man4/if_sn.4.gz
OLD_FILES+=usr/share/man/man4/tl.4.gz
OLD_FILES+=usr/share/man/man4/if_tl.4.gz
OLD_FILES+=usr/share/man/man4/tx.4.gz
OLD_FILES+=usr/share/man/man4/if_tx.4.gz
OLD_FILES+=usr/share/man/man4/txp.4.gz
OLD_FILES+=usr/share/man/man4/if_txp.4.gz
OLD_FILES+=usr/share/man/man4/vx.4.gz
OLD_FILES+=usr/share/man/man4/wb.4.gz
OLD_FILES+=usr/share/man/man4/xe.4.gz
OLD_FILES+=usr/share/man/man4/if_xe.4.gz
# 20190513: libcap_sysctl interface change
OLD_FILES+=lib/casper/libcap_sysctl.1
# 20190509: tests/sys/opencrypto requires the net/py-dpkt package.
OLD_FILES+=usr/tests/sys/opencrypto/dpkt.py
OLD_FILES+=usr/tests/sys/opencrypto/dpkt.pyc
# 20190326: tzdata 2019a import
OLD_FILES+=usr/share/zoneinfo/Etc/UCT
# 20190304: new libc++ import which bumps version from 7.0.1 to 8.0.0.
OLD_FILES+=usr/include/c++/v1/experimental/dynarray
# 20190304: new clang import which bumps version from 7.0.1 to 8.0.0.
@ -199,16 +234,21 @@ OLD_FILES+=usr/include/sys/seq.h
OLD_FILES+=usr/lib/libprivateifconfig.a
OLD_FILES+=usr/lib/libprivateifconfig_p.a
# 20190131: pfil(9) changed
OLD_FILES+=usr/share/man/man9/pfil_hook_get.9
OLD_FILES+=usr/share/man/man9/pfil_rlock.9
OLD_FILES+=usr/share/man/man9/pfil_runlock.9
OLD_FILES+=usr/share/man/man9/pfil_wlock.9
OLD_FILES+=usr/share/man/man9/pfil_wunlock.9
OLD_FILES+=usr/share/man/man9/pfil_hook_get.9.gz
OLD_FILES+=usr/share/man/man9/pfil_rlock.9.gz
OLD_FILES+=usr/share/man/man9/pfil_runlock.9.gz
OLD_FILES+=usr/share/man/man9/pfil_wlock.9.gz
OLD_FILES+=usr/share/man/man9/pfil_wunlock.9.gz
# 20190126: adv(4) / adw(4) removal
OLD_FILES+=usr/share/man/man4/adv.4.gz
OLD_FILES+=usr/share/man/man4/adw.4.gz
# 20190123: nonexistant cred_update_thread(9) removed
OLD_FILES+=usr/share/man/man9/cred_update_thread.9.gz
# 20190114: old pbuf allocator removed
OLD_FILES+=usr/share/man/man9/getpbuf.9.gz
OLD_FILES+=usr/share/man/man9/pbuf.9.gz
OLD_FILES+=usr/share/man/man9/relpbuf.9.gz
OLD_FILES+=usr/share/man/man9/trypbuf.9.gz
# 20181219: ibcs removal
OLD_FILES+=usr/share/examples/ibcs2/hello.uu
OLD_FILES+=usr/share/examples/ibcs2/README

View File

@ -31,7 +31,7 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 13.x IS SLOW:
disable the most expensive debugging functionality run
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
20190513:
20190606:
The vfs.fusefs.sync_unmount and vfs.fusefs.init_backgrounded sysctls
and the "-o sync_unmount" and "-o init_backgrounded" mount options have
been removed from mount_fusefs(8). You can safely remove them from
@ -43,6 +43,14 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 13.x IS SLOW:
felt the need to set any of them to a non-default value, please tell
asomers@FreeBSD.org why.
20190513:
User-wired pages now have their own counter,
vm.stats.vm.v_user_wire_count. The vm.max_wired sysctl was renamed
to vm.max_user_wired and changed from an unsigned int to an unsigned
long. bhyve VMs wired with the -S are now subject to the user
wiring limit; the vm.max_user_wired sysctl may need to be tuned to
avoid running into the limit.
20190507:
The IPSEC option has been removed from GENERIC. Users requiring
ipsec(4) must now load the ipsec(4) kernel module.
@ -79,13 +87,6 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 13.x IS SLOW:
met as for the diagnostic sysctls above. Defaults to zero, i.e.,
produce warnings in dmesg when the conditions are met.
20190416:
The tunable "security.stack_protect.permit_nonrandom_cookies" may be
set to a non-zero value to boot systems that do not provide early
entropy. Otherwise, such systems may see the panic message:
"cannot initialize stack cookies because random device is not yet
seeded."
20190416:
The loadable random module KPI has changed; the random_infra_init()
routine now requires a 3rd function pointer for a bool (*)(void)

View File

@ -7,7 +7,7 @@ CLEANFILES = freebsd-version freebsd-version.sh
NEWVERS = ${SRCTOP}/sys/conf/newvers.sh
freebsd-version.sh: ${.CURDIR}/freebsd-version.sh.in ${NEWVERS}
eval $$(egrep '^(TYPE|REVISION|BRANCH)=' ${NEWVERS}) ; \
eval $$(sh ${NEWVERS} -v); \
if ! sed -e "\
s/@@TYPE@@/$${TYPE}/g; \
s/@@REVISION@@/$${REVISION}/g; \

View File

@ -0,0 +1,43 @@
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2019 Mariusz Zaborski <oshogbo@FreeBSD.org>
* Use is subject to license terms.
*/
__attribute__((optnone)) void
frax(void)
{
asm volatile("mov $0x41414141, %%rax"
: : : "rax"
);
}
int
main(void)
{
while (1) {
frax();
}
return (0);
}

View File

@ -0,0 +1,36 @@
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2019 Mariusz Zaborski <oshogbo@FreeBSD.org>
* Use is subject to license terms.
*/
#pragma D option quiet
pid$1::frax:return / uregs[R_RAX] == 0x41414141 / {
exit(0);
}
pid$1::frax:return / uregs[R_RAX] != 0x41414141 / {
printf("wrong rax value: %d\n", uregs[R_RAX]);
exit(1);
}

View File

@ -0,0 +1,82 @@
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2019 Mariusz Zaborski <oshogbo@FreeBSD.org>
* Use is subject to license terms.
*/
/*
* ASSERTION:
* Positive test to make sure that we can invoke amd64
* ureg[] aliases.
*
* SECTION: User Process Tracing/uregs Array
*
* NOTES: This test does no verification - the value of the output
* is not deterministic.
*/
#pragma D option quiet
BEGIN
{
printf("R_GS = 0x%x\n", uregs[R_GS]);
printf("R_ES = 0x%x\n", uregs[R_ES]);
printf("R_DS = 0x%x\n", uregs[R_DS]);
printf("R_CS = 0x%x\n", uregs[R_CS]);
printf("R_RFL = 0x%x\n", uregs[R_RFL]);
printf("R_SS = 0x%x\n", uregs[R_SS]);
printf("R_TRAPNO = 0x%x\n", uregs[R_TRAPNO]);
printf("R_URSP = 0x%x\n", uregs[R_RSP]);
printf("R_RDI = 0x%x\n", uregs[R_RDI]);
printf("R_RSI = 0x%x\n", uregs[R_RSI]);
printf("R_RBP = 0x%x\n", uregs[R_RBP]);
printf("R_RBX = 0x%x\n", uregs[R_RBX]);
printf("R_RDX = 0x%x\n", uregs[R_RDX]);
printf("R_RCX = 0x%x\n", uregs[R_RCX]);
printf("R_RAX = 0x%x\n", uregs[R_RAX]);
printf("R_RIP = 0x%x\n", uregs[R_RIP]);
printf("R_RDI = 0x%x\n", uregs[R_RDI]);
printf("R_R9 = 0x%x\n", uregs[R_R9]);
printf("R_R10 = 0x%x\n", uregs[R_R10]);
printf("R_R11 = 0x%x\n", uregs[R_R11]);
printf("R_R12 = 0x%x\n", uregs[R_R12]);
printf("R_R13 = 0x%x\n", uregs[R_R13]);
printf("R_R14 = 0x%x\n", uregs[R_R14]);
printf("R_R15 = 0x%x\n", uregs[R_R15]);
/* 32 bits */
printf("R_EFL = 0x%x\n", uregs[R_EFL]);
printf("R_UESP = 0x%x\n", uregs[R_UESP]);
printf("R_ERR = 0x%x\n", uregs[R_ERR]);
printf("R_EIP = 0x%x\n", uregs[R_EIP]);
printf("R_EDI = 0x%x\n", uregs[R_EDI]);
printf("R_ESI = 0x%x\n", uregs[R_ESI]);
printf("R_EBP = 0x%x\n", uregs[R_EBP]);
printf("R_EBX = 0x%x\n", uregs[R_EBX]);
printf("R_EDX = 0x%x\n", uregs[R_EDX]);
printf("R_ECX = 0x%x\n", uregs[R_ECX]);
printf("R_EAX = 0x%x\n", uregs[R_EAX]);
exit(0);
}

View File

@ -63,6 +63,7 @@
#include <sys/zfeature.h>
#include <sys/abd.h>
#include <sys/blkptr.h>
#include <sys/dsl_scan.h>
#include <zfs_comutil.h>
#include <libcmdutils.h>
#undef verify
@ -111,6 +112,7 @@ static uint64_t max_inflight = 1000;
static int leaked_objects = 0;
static void snprintf_blkptr_compact(char *, size_t, const blkptr_t *);
static void mos_obj_refd(uint64_t);
/*
* These libumem hooks provide a reasonable set of defaults for the allocator's
@ -1592,6 +1594,8 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
DO(CHILD_RSRV);
DO(REFRSRV);
#undef DO
(void) printf("\t\tclones = %llu\n",
(u_longlong_t)dd->dd_clones);
}
/*ARGSUSED*/
@ -1773,6 +1777,33 @@ dump_full_bpobj(bpobj_t *bpo, const char *name, int indent)
}
}
static void
bpobj_count_refd(bpobj_t *bpo)
{
mos_obj_refd(bpo->bpo_object);
if (bpo->bpo_havesubobj && bpo->bpo_phys->bpo_subobjs != 0) {
mos_obj_refd(bpo->bpo_phys->bpo_subobjs);
for (uint64_t i = 0; i < bpo->bpo_phys->bpo_num_subobjs; i++) {
uint64_t subobj;
bpobj_t subbpo;
int error;
VERIFY0(dmu_read(bpo->bpo_os,
bpo->bpo_phys->bpo_subobjs,
i * sizeof (subobj), sizeof (subobj), &subobj, 0));
error = bpobj_open(&subbpo, bpo->bpo_os, subobj);
if (error != 0) {
(void) printf("ERROR %u while trying to open "
"subobj id %llu\n",
error, (u_longlong_t)subobj);
continue;
}
bpobj_count_refd(&subbpo);
bpobj_close(&subbpo);
}
}
}
static void
dump_deadlist(dsl_deadlist_t *dl)
{
@ -1781,6 +1812,23 @@ dump_deadlist(dsl_deadlist_t *dl)
char bytes[32];
char comp[32];
char uncomp[32];
uint64_t empty_bpobj =
dmu_objset_spa(dl->dl_os)->spa_dsl_pool->dp_empty_bpobj;
/* force the tree to be loaded */
dsl_deadlist_space_range(dl, 0, UINT64_MAX, &unused, &unused, &unused);
if (dl->dl_oldfmt) {
if (dl->dl_bpobj.bpo_object != empty_bpobj)
bpobj_count_refd(&dl->dl_bpobj);
} else {
mos_obj_refd(dl->dl_object);
for (dle = avl_first(&dl->dl_tree); dle;
dle = AVL_NEXT(&dl->dl_tree, dle)) {
if (dle->dle_bpobj.bpo_object != empty_bpobj)
bpobj_count_refd(&dle->dle_bpobj);
}
}
/* make sure nicenum has enough space */
CTASSERT(sizeof (bytes) >= NN_NUMBUF_SZ);
@ -1806,9 +1854,6 @@ dump_deadlist(dsl_deadlist_t *dl)
(void) printf("\n");
/* force the tree to be loaded */
dsl_deadlist_space_range(dl, 0, UINT64_MAX, &unused, &unused, &unused);
for (dle = avl_first(&dl->dl_tree); dle;
dle = AVL_NEXT(&dl->dl_tree, dle)) {
if (dump_opt['d'] >= 5) {
@ -2219,6 +2264,30 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
dmu_buf_rele(db, FTAG);
}
static void
count_dir_mos_objects(dsl_dir_t *dd)
{
mos_obj_refd(dd->dd_object);
mos_obj_refd(dsl_dir_phys(dd)->dd_child_dir_zapobj);
mos_obj_refd(dsl_dir_phys(dd)->dd_deleg_zapobj);
mos_obj_refd(dsl_dir_phys(dd)->dd_props_zapobj);
mos_obj_refd(dsl_dir_phys(dd)->dd_clones);
}
static void
count_ds_mos_objects(dsl_dataset_t *ds)
{
mos_obj_refd(ds->ds_object);
mos_obj_refd(dsl_dataset_phys(ds)->ds_next_clones_obj);
mos_obj_refd(dsl_dataset_phys(ds)->ds_props_obj);
mos_obj_refd(dsl_dataset_phys(ds)->ds_userrefs_obj);
mos_obj_refd(dsl_dataset_phys(ds)->ds_snapnames_zapobj);
if (!dsl_dataset_is_snapshot(ds)) {
count_dir_mos_objects(ds->ds_dir);
}
}
static const char *objset_types[DMU_OST_NUMTYPES] = {
"NONE", "META", "ZPL", "ZVOL", "OTHER", "ANY" };
@ -2271,10 +2340,11 @@ dump_dir(objset_t *os)
dmu_objset_name(os, osname);
(void) printf("Dataset %s [%s], ID %llu, cr_txg %llu, "
"%s, %llu objects%s\n",
"%s, %llu objects%s%s\n",
osname, type, (u_longlong_t)dmu_objset_id(os),
(u_longlong_t)dds.dds_creation_txg,
numbuf, (u_longlong_t)usedobjs, blkbuf);
numbuf, (u_longlong_t)usedobjs, blkbuf,
(dds.dds_inconsistent) ? " (inconsistent)" : "");
if (zopt_objects != 0) {
for (i = 0; i < zopt_objects; i++)
@ -2295,6 +2365,7 @@ dump_dir(objset_t *os)
(void) printf("ds_remap_deadlist:\n");
dump_deadlist(&ds->ds_remap_deadlist);
}
count_ds_mos_objects(ds);
}
if (verbosity < 2)
@ -4459,6 +4530,161 @@ verify_checkpoint(spa_t *spa)
return (error);
}
/* ARGSUSED */
static void
mos_leaks_cb(void *arg, uint64_t start, uint64_t size)
{
for (uint64_t i = start; i < size; i++) {
(void) printf("MOS object %llu referenced but not allocated\n",
(u_longlong_t)i);
}
}
static range_tree_t *mos_refd_objs;
static void
mos_obj_refd(uint64_t obj)
{
if (obj != 0 && mos_refd_objs != NULL)
range_tree_add(mos_refd_objs, obj, 1);
}
static void
mos_leak_vdev(vdev_t *vd)
{
mos_obj_refd(vd->vdev_dtl_object);
mos_obj_refd(vd->vdev_ms_array);
mos_obj_refd(vd->vdev_top_zap);
mos_obj_refd(vd->vdev_indirect_config.vic_births_object);
mos_obj_refd(vd->vdev_indirect_config.vic_mapping_object);
mos_obj_refd(vd->vdev_leaf_zap);
if (vd->vdev_checkpoint_sm != NULL)
mos_obj_refd(vd->vdev_checkpoint_sm->sm_object);
if (vd->vdev_indirect_mapping != NULL) {
mos_obj_refd(vd->vdev_indirect_mapping->
vim_phys->vimp_counts_object);
}
if (vd->vdev_obsolete_sm != NULL)
mos_obj_refd(vd->vdev_obsolete_sm->sm_object);
for (uint64_t m = 0; m < vd->vdev_ms_count; m++) {
metaslab_t *ms = vd->vdev_ms[m];
mos_obj_refd(space_map_object(ms->ms_sm));
}
for (uint64_t c = 0; c < vd->vdev_children; c++) {
mos_leak_vdev(vd->vdev_child[c]);
}
}
static int
dump_mos_leaks(spa_t *spa)
{
int rv = 0;
objset_t *mos = spa->spa_meta_objset;
dsl_pool_t *dp = spa->spa_dsl_pool;
/* Visit and mark all referenced objects in the MOS */
mos_obj_refd(DMU_POOL_DIRECTORY_OBJECT);
mos_obj_refd(spa->spa_pool_props_object);
mos_obj_refd(spa->spa_config_object);
mos_obj_refd(spa->spa_ddt_stat_object);
mos_obj_refd(spa->spa_feat_desc_obj);
mos_obj_refd(spa->spa_feat_enabled_txg_obj);
mos_obj_refd(spa->spa_feat_for_read_obj);
mos_obj_refd(spa->spa_feat_for_write_obj);
mos_obj_refd(spa->spa_history);
mos_obj_refd(spa->spa_errlog_last);
mos_obj_refd(spa->spa_errlog_scrub);
mos_obj_refd(spa->spa_all_vdev_zaps);
mos_obj_refd(spa->spa_dsl_pool->dp_bptree_obj);
mos_obj_refd(spa->spa_dsl_pool->dp_tmp_userrefs_obj);
mos_obj_refd(spa->spa_dsl_pool->dp_scan->scn_phys.scn_queue_obj);
bpobj_count_refd(&spa->spa_deferred_bpobj);
mos_obj_refd(dp->dp_empty_bpobj);
bpobj_count_refd(&dp->dp_obsolete_bpobj);
bpobj_count_refd(&dp->dp_free_bpobj);
mos_obj_refd(spa->spa_l2cache.sav_object);
mos_obj_refd(spa->spa_spares.sav_object);
mos_obj_refd(spa->spa_condensing_indirect_phys.
scip_next_mapping_object);
mos_obj_refd(spa->spa_condensing_indirect_phys.
scip_prev_obsolete_sm_object);
if (spa->spa_condensing_indirect_phys.scip_next_mapping_object != 0) {
vdev_indirect_mapping_t *vim =
vdev_indirect_mapping_open(mos,
spa->spa_condensing_indirect_phys.scip_next_mapping_object);
mos_obj_refd(vim->vim_phys->vimp_counts_object);
vdev_indirect_mapping_close(vim);
}
if (dp->dp_origin_snap != NULL) {
dsl_dataset_t *ds;
dsl_pool_config_enter(dp, FTAG);
VERIFY0(dsl_dataset_hold_obj(dp,
dsl_dataset_phys(dp->dp_origin_snap)->ds_next_snap_obj,
FTAG, &ds));
count_ds_mos_objects(ds);
dump_deadlist(&ds->ds_deadlist);
dsl_dataset_rele(ds, FTAG);
dsl_pool_config_exit(dp, FTAG);
count_ds_mos_objects(dp->dp_origin_snap);
dump_deadlist(&dp->dp_origin_snap->ds_deadlist);
}
count_dir_mos_objects(dp->dp_mos_dir);
if (dp->dp_free_dir != NULL)
count_dir_mos_objects(dp->dp_free_dir);
if (dp->dp_leak_dir != NULL)
count_dir_mos_objects(dp->dp_leak_dir);
mos_leak_vdev(spa->spa_root_vdev);
for (uint64_t class = 0; class < DDT_CLASSES; class++) {
for (uint64_t type = 0; type < DDT_TYPES; type++) {
for (uint64_t cksum = 0;
cksum < ZIO_CHECKSUM_FUNCTIONS; cksum++) {
ddt_t *ddt = spa->spa_ddt[cksum];
mos_obj_refd(ddt->ddt_object[type][class]);
}
}
}
/*
* Visit all allocated objects and make sure they are referenced.
*/
uint64_t object = 0;
while (dmu_object_next(mos, &object, B_FALSE, 0) == 0) {
if (range_tree_contains(mos_refd_objs, object, 1)) {
range_tree_remove(mos_refd_objs, object, 1);
} else {
dmu_object_info_t doi;
const char *name;
dmu_object_info(mos, object, &doi);
if (doi.doi_type & DMU_OT_NEWTYPE) {
dmu_object_byteswap_t bswap =
DMU_OT_BYTESWAP(doi.doi_type);
name = dmu_ot_byteswap[bswap].ob_name;
} else {
name = dmu_ot[doi.doi_type].ot_name;
}
(void) printf("MOS object %llu (%s) leaked\n",
(u_longlong_t)object, name);
rv = 2;
}
}
(void) range_tree_walk(mos_refd_objs, mos_leaks_cb, NULL);
if (!range_tree_is_empty(mos_refd_objs))
rv = 2;
range_tree_vacate(mos_refd_objs, NULL, NULL);
range_tree_destroy(mos_refd_objs);
return (rv);
}
static void
dump_zpool(spa_t *spa)
{
@ -4490,7 +4716,9 @@ dump_zpool(spa_t *spa)
dump_metaslab_groups(spa);
if (dump_opt['d'] || dump_opt['i']) {
mos_refd_objs = range_tree_create(NULL, NULL);
dump_dir(dp->dp_meta_objset);
if (dump_opt['d'] >= 3) {
dsl_pool_t *dp = spa->spa_dsl_pool;
dump_full_bpobj(&spa->spa_deferred_bpobj,
@ -4517,6 +4745,9 @@ dump_zpool(spa_t *spa)
(void) dmu_objset_find(spa_name(spa), dump_one_dir,
NULL, DS_FIND_SNAPSHOTS | DS_FIND_CHILDREN);
if (rc == 0 && !dump_opt['L'])
rc = dump_mos_leaks(spa);
for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
uint64_t refcount;
@ -4546,6 +4777,7 @@ dump_zpool(spa_t *spa)
rc = verify_device_removal_feature_counts(spa);
}
}
if (rc == 0 && (dump_opt['b'] || dump_opt['c']))
rc = dump_block_stats(spa);

View File

@ -9,6 +9,7 @@
.\"
.\"
.\" Copyright (c) 2016, 2017 by Delphix. All rights reserved.
.\" Copyright (c) 2018 Datto Inc.
.\"
.Dd October 02, 2017
.Dt ZFS-PROGRAM 1M
@ -18,7 +19,7 @@
.Nd executes ZFS channel programs
.Sh SYNOPSIS
.Cm zfs program
.Op Fl n
.Op Fl jn
.Op Fl t Ar instruction-limit
.Op Fl m Ar memory-limit
.Ar pool
@ -46,6 +47,11 @@ will be run on
and any attempts to access or modify other pools will cause an error.
.Sh OPTIONS
.Bl -tag -width "-t"
.It Fl j
Display channel program output in JSON format.
When this flag is specified and standard output is empty -
channel program encountered an error.
The details of such an error will be printed to standard error in plain text.
.It Fl n
Executes a read-only channel program, which runs faster.
The program cannot change on-disk state by calling functions from the

View File

@ -29,6 +29,7 @@
.\" Copyright (c) 2014, Xin LI <delphij@FreeBSD.org>
.\" Copyright (c) 2014-2015, The FreeBSD Foundation, All Rights Reserved.
.\" Copyright 2018 Joyent, Inc.
.\" Copyright (c) 2018 Datto Inc.
.\"
.\" $FreeBSD$
.\"
@ -291,7 +292,7 @@
.Op Ar snapshot Ns | Ns Ar filesystem
.Nm
.Cm program
.Op Fl n
.Op Fl jn
.Op Fl t Ar timeout
.Op Fl m Ar memory_limit
.Ar pool script
@ -3364,7 +3365,7 @@ Display the path's inode change time as the first column of output.
.It Xo
.Nm
.Cm program
.Op Fl n
.Op Fl jn
.Op Fl t Ar timeout
.Op Fl m Ar memory_limit
.Ar pool script
@ -3387,6 +3388,11 @@ For full documentation of the ZFS channel program interface, see the manual
page for
.Xr zfs-program 8 .
.Bl -tag -width indent
.It Fl j
Display channel program output in JSON format.
When this flag is specified and standard output is empty -
channel program encountered an error.
The details of such an error will be printed to standard error in plain text.
.It Fl n
Executes a read-only channel program, which runs faster.
The program cannot change on-disk state by calling functions from

View File

@ -30,6 +30,7 @@
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
* Copyright 2016 Nexenta Systems, Inc.
* Copyright (c) 2018 Datto Inc.
*/
#include <assert.h>
@ -351,7 +352,7 @@ get_usage(zfs_help_t idx)
case HELP_BOOKMARK:
return (gettext("\tbookmark <snapshot> <bookmark>\n"));
case HELP_CHANNEL_PROGRAM:
return (gettext("\tprogram [-n] [-t <instruction limit>] "
return (gettext("\tprogram [-jn] [-t <instruction limit>] "
"[-m <memory limit (b)>] <pool> <program file> "
"[lua args...]\n"));
}
@ -2361,6 +2362,7 @@ us_compare(const void *larg, const void *rarg, void *unused)
case ZFS_PROP_NAME:
propname = "name";
if (numname) {
compare_nums:
(void) nvlist_lookup_uint64(lnvl, propname,
&lv64);
(void) nvlist_lookup_uint64(rnvl, propname,
@ -2368,10 +2370,12 @@ us_compare(const void *larg, const void *rarg, void *unused)
if (rv64 != lv64)
rc = (rv64 < lv64) ? 1 : -1;
} else {
(void) nvlist_lookup_string(lnvl, propname,
&lvstr);
(void) nvlist_lookup_string(rnvl, propname,
&rvstr);
if ((nvlist_lookup_string(lnvl, propname,
&lvstr) == ENOENT) ||
(nvlist_lookup_string(rnvl, propname,
&rvstr) == ENOENT)) {
goto compare_nums;
}
rc = strcmp(lvstr, rvstr);
}
break;
@ -7235,12 +7239,12 @@ zfs_do_channel_program(int argc, char **argv)
nvlist_t *outnvl;
uint64_t instrlimit = ZCP_DEFAULT_INSTRLIMIT;
uint64_t memlimit = ZCP_DEFAULT_MEMLIMIT;
boolean_t sync_flag = B_TRUE;
boolean_t sync_flag = B_TRUE, json_output = B_FALSE;
zpool_handle_t *zhp;
/* check options */
while (-1 !=
(c = getopt(argc, argv, "nt:(instr-limit)m:(memory-limit)"))) {
(c = getopt(argc, argv, "jnt:(instr-limit)m:(memory-limit)"))) {
switch (c) {
case 't':
case 'm': {
@ -7282,6 +7286,10 @@ zfs_do_channel_program(int argc, char **argv)
sync_flag = B_FALSE;
break;
}
case 'j': {
json_output = B_TRUE;
break;
}
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
@ -7404,11 +7412,14 @@ zfs_do_channel_program(int argc, char **argv)
gettext("Channel program execution failed:\n%s\n"),
errstring);
} else {
(void) printf("Channel program fully executed ");
if (nvlist_empty(outnvl)) {
(void) printf("with no return value.\n");
if (json_output) {
(void) nvlist_print_json(stdout, outnvl);
} else if (nvlist_empty(outnvl)) {
(void) fprintf(stdout, gettext("Channel program fully "
"executed and did not produce output.\n"));
} else {
(void) printf("with return value:\n");
(void) fprintf(stdout, gettext("Channel program fully "
"executed and produced output:\n"));
dump_nvlist(outnvl, 4);
}
}

View File

@ -604,10 +604,6 @@ Amount of storage space within the pool that has been physically allocated.
.It Sy capacity
Percentage of pool space used. This property can also be referred to by its
shortened column name, "cap".
.It Sy comment
A text string consisting of printable ASCII characters that will be stored
such that it is available even if the pool becomes faulted. An administrator
can provide additional information about a pool using this property.
.It Sy dedupratio
The deduplication ratio specified for a pool, expressed as a multiplier.
For example, a

View File

@ -338,7 +338,6 @@ ztest_func_t ztest_spa_create_destroy;
ztest_func_t ztest_fault_inject;
ztest_func_t ztest_ddt_repair;
ztest_func_t ztest_dmu_snapshot_hold;
ztest_func_t ztest_spa_rename;
ztest_func_t ztest_scrub;
ztest_func_t ztest_dsl_dataset_promote_busy;
ztest_func_t ztest_vdev_attach_detach;
@ -384,7 +383,6 @@ ztest_info_t ztest_info[] = {
{ ztest_ddt_repair, 1, &zopt_sometimes },
{ ztest_dmu_snapshot_hold, 1, &zopt_sometimes },
{ ztest_reguid, 1, &zopt_rarely },
{ ztest_spa_rename, 1, &zopt_rarely },
{ ztest_scrub, 1, &zopt_often },
{ ztest_spa_upgrade, 1, &zopt_rarely },
{ ztest_dsl_dataset_promote_busy, 1, &zopt_rarely },
@ -1935,6 +1933,7 @@ zil_replay_func_t *ztest_replay_vector[TX_MAX_TYPE] = {
* ZIL get_data callbacks
*/
/* ARGSUSED */
static void
ztest_get_done(zgd_t *zgd, int error)
{
@ -1947,9 +1946,6 @@ ztest_get_done(zgd_t *zgd, int error)
ztest_range_unlock(zgd->zgd_rl);
ztest_object_unlock(zd, object);
if (error == 0 && zgd->zgd_bp)
zil_lwb_add_block(zgd->zgd_lwb, zgd->zgd_bp);
umem_free(zgd, sizeof (*zgd));
}
@ -5550,59 +5546,6 @@ ztest_reguid(ztest_ds_t *zd, uint64_t id)
VERIFY3U(load, ==, spa_load_guid(spa));
}
/*
* Rename the pool to a different name and then rename it back.
*/
/* ARGSUSED */
void
ztest_spa_rename(ztest_ds_t *zd, uint64_t id)
{
char *oldname, *newname;
spa_t *spa;
rw_enter(&ztest_name_lock, RW_WRITER);
oldname = ztest_opts.zo_pool;
newname = umem_alloc(strlen(oldname) + 5, UMEM_NOFAIL);
(void) strcpy(newname, oldname);
(void) strcat(newname, "_tmp");
/*
* Do the rename
*/
VERIFY3U(0, ==, spa_rename(oldname, newname));
/*
* Try to open it under the old name, which shouldn't exist
*/
VERIFY3U(ENOENT, ==, spa_open(oldname, &spa, FTAG));
/*
* Open it under the new name and make sure it's still the same spa_t.
*/
VERIFY3U(0, ==, spa_open(newname, &spa, FTAG));
ASSERT(spa == ztest_spa);
spa_close(spa, FTAG);
/*
* Rename it back to the original
*/
VERIFY3U(0, ==, spa_rename(newname, oldname));
/*
* Make sure it can still be opened
*/
VERIFY3U(0, ==, spa_open(oldname, &spa, FTAG));
ASSERT(spa == ztest_spa);
spa_close(spa, FTAG);
umem_free(newname, strlen(newname) + 1);
rw_exit(&ztest_name_lock);
}
static vdev_t *
ztest_random_concrete_vdev_leaf(vdev_t *vd)
{
@ -6661,7 +6604,6 @@ main(int argc, char **argv)
ztest_shared_callstate_t *zc;
char timebuf[100];
char numbuf[NN_NUMBUF_SZ];
spa_t *spa;
char *cmd;
boolean_t hasalt;
char *fd_data_str = getenv("ZTEST_FD_DATA");
@ -6836,24 +6778,6 @@ main(int argc, char **argv)
(void) printf("\n");
}
/*
* It's possible that we killed a child during a rename test,
* in which case we'll have a 'ztest_tmp' pool lying around
* instead of 'ztest'. Do a blind rename in case this happened.
*/
kernel_init(FREAD);
if (spa_open(ztest_opts.zo_pool, &spa, FTAG) == 0) {
spa_close(spa, FTAG);
} else {
char tmpname[ZFS_MAX_DATASET_NAME_LEN];
kernel_fini();
kernel_init(FREAD | FWRITE);
(void) snprintf(tmpname, sizeof (tmpname), "%s_tmp",
ztest_opts.zo_pool);
(void) spa_rename(tmpname, ztest_opts.zo_pool);
}
kernel_fini();
ztest_run_zdb(ztest_opts.zo_pool);
}

View File

@ -30,7 +30,7 @@
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2017 Nexenta Systems, Inc.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
* Copyright 2017 RackTop Systems.
* Copyright 2017-2018 RackTop Systems.
*/
#include <ctype.h>
@ -1842,13 +1842,18 @@ zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
if (ret != 0) {
if (zc.zc_nvlist_dst_filled == B_FALSE) {
(void) zfs_standard_error(hdl, errno, errbuf);
goto error;
}
/* Get the list of unset properties back and report them. */
nvlist_t *errorprops = NULL;
if (zcmd_read_dst_nvlist(hdl, &zc, &errorprops) != 0)
goto error;
for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
for (nvpair_t *elem = nvlist_next_nvpair(errorprops, NULL);
elem != NULL;
elem = nvlist_next_nvpair(nvl, elem)) {
elem = nvlist_next_nvpair(errorprops, elem)) {
zfs_prop_t prop = zfs_name_to_prop(nvpair_name(elem));
zfs_setprop_error(hdl, prop, errno, errbuf);
}

View File

@ -22,7 +22,7 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2015, 2017 by Delphix. All rights reserved.
* Copyright (c) 2015, 2018 by Delphix. All rights reserved.
* Copyright 2016 Joyent, Inc.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
*/
@ -47,7 +47,7 @@
#include "libzfs_impl.h"
#define ZDIFF_SNAPDIR "/.zfs/snapshot/"
#define ZDIFF_SHARESDIR "/.zfs/shares/"
#define ZDIFF_SHARESDIR "/.zfs/shares/"
#define ZDIFF_PREFIX "zfs-diff-%d"
#define ZDIFF_ADDED '+'
@ -114,7 +114,7 @@ get_stats_for_obj(differ_info_t *di, const char *dsname, uint64_t obj,
(void) snprintf(di->errbuf, sizeof (di->errbuf),
dgettext(TEXT_DOMAIN,
"Unable to determine path or stats for "
"object %lld in %s"), obj, dsname);
"object %jd in %s"), (uintmax_t)obj, dsname);
return (-1);
}
}
@ -361,13 +361,13 @@ describe_free(FILE *fp, differ_info_t *di, uint64_t object, char *namebuf,
if (get_stats_for_obj(di, di->fromsnap, object, namebuf,
maxlen, &sb) != 0) {
/* Let it slide, if in the delete queue on from side */
if (di->zerr == ENOENT && sb.zs_links == 0) {
di->zerr = 0;
return (0);
}
return (-1);
}
/* Don't print if in the delete queue on from side */
if (di->zerr == ESTALE) {
di->zerr = 0;
return (0);
}
print_file(fp, di, ZDIFF_REMOVED, namebuf, &sb);
return (0);
@ -406,8 +406,8 @@ write_free_diffs(FILE *fp, differ_info_t *di, dmu_diff_record_t *dr)
} else {
(void) snprintf(di->errbuf, sizeof (di->errbuf),
dgettext(TEXT_DOMAIN,
"next allocated object (> %lld) find failure"),
zc.zc_obj);
"next allocated object (> %jd) find failure"),
(uintmax_t)zc.zc_obj);
di->zerr = errno;
break;
}

View File

@ -4,6 +4,14 @@
TESTS_SUBDIRS+= common
.if ${MACHINE_CPUARCH} == "i386"
TESTS_SUBDIRS+= i386
.endif
.if ${MACHINE_CPUARCH} == "amd64"
TESTS_SUBDIRS+= amd64
.endif
.PATH: ${SRCTOP}/tests
KYUAFILE= yes

View File

@ -0,0 +1,20 @@
# $FreeBSD$
#
# This Makefile was generated by $srcdir/cddl/usr.sbin/dtrace/tests/tools/genmakefiles.sh.
#
PACKAGE= tests
${PACKAGE}FILES= \
tst.rax.d \
tst.uregsarray.d \
TESTEXES= \
CFILES= \
tst.rax.c \
.include "../../dtrace.test.mk"

View File

@ -0,0 +1,12 @@
# $FreeBSD$
TESTSDIR= ${TESTSBASE}/cddl/usr.sbin/dtrace/i386
TESTS_SUBDIRS+= arrays \
funcs \
pid \
ustack
.PATH: ${.CURDIR:H:H:H:H:H}/tests
KYUAFILE= YES
.include <bsd.test.mk>

View File

@ -0,0 +1,19 @@
# $FreeBSD$
#
# This Makefile was generated by $srcdir/cddl/usr.sbin/dtrace/tests/tools/genmakefiles.sh.
#
PACKAGE= tests
${PACKAGE}FILES= \
tst.uregsarray.d \
TESTEXES= \
CFILES= \
.include "../../dtrace.test.mk"

View File

@ -0,0 +1,22 @@
# $FreeBSD$
#
# This Makefile was generated by $srcdir/cddl/usr.sbin/dtrace/tests/tools/genmakefiles.sh.
#
PACKAGE= tests
${PACKAGE}FILES= \
tst.badcopyin.d \
tst.badcopyinstr.d \
tst.badcopyout.d \
tst.badcopyoutstr.d \
TESTEXES= \
CFILES= \
.include "../../dtrace.test.mk"

View File

@ -0,0 +1,23 @@
# $FreeBSD$
#
# This Makefile was generated by $srcdir/cddl/usr.sbin/dtrace/tests/tools/genmakefiles.sh.
#
PACKAGE= tests
${PACKAGE}FILES= \
tst.badinstr.d \
tst.branch.d \
tst.embedded.d \
tst.ret.d \
tst.retlist.ksh \
TESTEXES= \
CFILES= \
.include "../../dtrace.test.mk"

View File

@ -0,0 +1,26 @@
# $FreeBSD$
#
# This Makefile was generated by $srcdir/cddl/usr.sbin/dtrace/tests/tools/genmakefiles.sh.
#
PACKAGE= tests
${PACKAGE}FILES= \
annotated_helper.d \
helper_helper.d \
tst.annotated.d \
tst.annotated.d.out \
tst.circstack.d \
tst.helper.d \
tst.helper.d.out \
TESTEXES= \
CFILES= \
tst.annotated.c \
tst.helper.c \
.include "../../dtrace.test.mk"

View File

@ -24,9 +24,10 @@ fmtflist()
genmakefile()
{
local basedir=$1
local class=$1
local group=$2
local tdir=${CONTRIB_TESTDIR}/${basedir}
local tdir=${CONTRIB_TESTDIR}/${class}/${group}
local tfiles=$(find $tdir -type f -a \
\( -name \*.d -o -name \*.ksh -o -name \*.out \) | sort | fmtflist)
local tcfiles=$(find $tdir -type f -a -name \*.c | sort | fmtflist)
@ -34,7 +35,7 @@ genmakefile()
# One-off variable definitions.
local special
case "$basedir" in
case "$group" in
proc)
special="
LIBADD.tst.sigwait.exe+= rt
@ -80,7 +81,7 @@ $special
.include "../../dtrace.test.mk"
__EOF__
mv -f $makefile ${ORIGINDIR}/../common/${basedir}/Makefile
mv -f $makefile ${ORIGINDIR}/../${class}/${group}/Makefile
}
set -e
@ -93,9 +94,10 @@ export LC_ALL=C
readonly ORIGINDIR=$(realpath $(dirname $0))
readonly TOPDIR=$(realpath ${ORIGINDIR}/../../../../..)
readonly CONTRIB_TESTDIR=${TOPDIR}/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common
readonly CONTRIB_TESTDIR=${TOPDIR}/cddl/contrib/opensolaris/cmd/dtrace/test/tst
# Generate a Makefile for each test group under common/.
for dir in $(find ${CONTRIB_TESTDIR} -mindepth 1 -maxdepth 1 -type d); do
genmakefile $(basename $dir)
for class in common i386 amd64; do
for group in $(find ${CONTRIB_TESTDIR}/$class -mindepth 1 -maxdepth 1 -type d); do
genmakefile $class $(basename $group)
done
done

View File

@ -378,9 +378,6 @@ create_elf_from_srec(struct elfcopy *ecp, int ifd)
errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s",
elf_errmsg(-1));
/* Generate section name string table (.shstrtab). */
set_shstrtab(ecp);
/* Update sh_name pointer for each section header entry. */
update_shdr(ecp, 0);
@ -605,9 +602,6 @@ create_elf_from_ihex(struct elfcopy *ecp, int ifd)
errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s",
elf_errmsg(-1));
/* Generate section name string table (.shstrtab). */
set_shstrtab(ecp);
/* Update sh_name pointer for each section header entry. */
update_shdr(ecp, 0);

View File

@ -250,11 +250,8 @@ create_elf_from_binary(struct elfcopy *ecp, int ifd, const char *ifn)
errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s",
elf_errmsg(-1));
/* Generate section name string table (.shstrtab). */
ecp->flags |= SYMTAB_EXIST;
set_shstrtab(ecp);
/* Update sh_name pointer for each section header entry. */
ecp->flags |= SYMTAB_EXIST;
update_shdr(ecp, 0);
/* Properly set sh_link field of .symtab section. */

View File

@ -135,9 +135,13 @@ struct section {
int pseudo;
int nocopy;
Elftc_String_Table *strtab;
TAILQ_ENTRY(section) sec_list; /* next section */
};
TAILQ_HEAD(sectionlist, section);
/* Internal data structure for segments. */
struct segment {
uint64_t vaddr; /* virtual addr (VMA) */
@ -311,7 +315,6 @@ struct sec_action *lookup_sec_act(struct elfcopy *_ecp,
struct symop *lookup_symop_list(struct elfcopy *_ecp, const char *_name,
unsigned int _op);
void resync_sections(struct elfcopy *_ecp);
void set_shstrtab(struct elfcopy *_ecp);
void setup_phdr(struct elfcopy *_ecp);
void update_shdr(struct elfcopy *_ecp, int _update_link);

View File

@ -388,9 +388,6 @@ create_elf(struct elfcopy *ecp)
*/
copy_content(ecp);
/* Generate section name string table (.shstrtab). */
set_shstrtab(ecp);
/*
* Second processing of output sections: Update section headers.
* At this stage we set name string index, update st_link and st_info
@ -486,6 +483,9 @@ free_elf(struct elfcopy *ecp)
/* Free symbol table buffers. */
free_symtab(ecp);
/* Free section name string table. */
elftc_string_table_destroy(ecp->shstrtab->strtab);
/* Free internal section list. */
if (!TAILQ_EMPTY(&ecp->v_sec)) {
TAILQ_FOREACH_SAFE(sec, &ecp->v_sec, sec_list, sec_temp) {
@ -1565,7 +1565,6 @@ main(int argc, char **argv)
ecp = calloc(1, sizeof(*ecp));
if (ecp == NULL)
err(EXIT_FAILURE, "calloc failed");
memset(ecp, 0, sizeof(*ecp));
ecp->itf = ecp->otf = ETF_ELF;
ecp->iec = ecp->oec = ELFCLASSNONE;

View File

@ -42,19 +42,18 @@ static void check_section_rename(struct elfcopy *ecp, struct section *s);
static void filter_reloc(struct elfcopy *ecp, struct section *s);
static int get_section_flags(struct elfcopy *ecp, const char *name);
static void insert_sections(struct elfcopy *ecp);
static void insert_to_strtab(struct section *t, const char *s);
static int is_append_section(struct elfcopy *ecp, const char *name);
static int is_compress_section(struct elfcopy *ecp, const char *name);
static int is_debug_section(const char *name);
static int is_dwo_section(const char *name);
static int is_modify_section(struct elfcopy *ecp, const char *name);
static int is_print_section(struct elfcopy *ecp, const char *name);
static int lookup_string(struct section *t, const char *s);
static void modify_section(struct elfcopy *ecp, struct section *s);
static void pad_section(struct elfcopy *ecp, struct section *s);
static void print_data(const char *d, size_t sz);
static void print_section(struct section *s);
static void *read_section(struct section *s, size_t *size);
static void set_shstrtab(struct elfcopy *ecp);
static void update_reloc(struct elfcopy *ecp, struct section *s);
static void update_section_group(struct elfcopy *ecp, struct section *s);
@ -119,21 +118,19 @@ is_remove_reloc_sec(struct elfcopy *ecp, uint32_t sh_info)
errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
elf_errmsg(-1));
is = NULL;
while ((is = elf_nextscn(ecp->ein, is)) != NULL) {
if (sh_info == elf_ndxscn(is)) {
if (gelf_getshdr(is, &ish) == NULL)
errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
elf_errmsg(-1));
if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) ==
NULL)
errx(EXIT_FAILURE, "elf_strptr failed: %s",
elf_errmsg(-1));
if (is_remove_section(ecp, name))
return (1);
else
return (0);
}
is = elf_getscn(ecp->ein, sh_info);
if (is != NULL) {
if (gelf_getshdr(is, &ish) == NULL)
errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
elf_errmsg(-1));
if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) ==
NULL)
errx(EXIT_FAILURE, "elf_strptr failed: %s",
elf_errmsg(-1));
if (is_remove_section(ecp, name))
return (1);
else
return (0);
}
elferr = elf_errno();
if (elferr != 0)
@ -314,18 +311,18 @@ insert_to_sec_list(struct elfcopy *ecp, struct section *sec, int tail)
{
struct section *s;
if (!tail) {
if (tail || TAILQ_EMPTY(&ecp->v_sec) ||
TAILQ_LAST(&ecp->v_sec, sectionlist)->off <= sec->off) {
TAILQ_INSERT_TAIL(&ecp->v_sec, sec, sec_list);
} else {
TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
if (sec->off < s->off) {
TAILQ_INSERT_BEFORE(s, sec, sec_list);
goto inc_nos;
break;
}
}
}
TAILQ_INSERT_TAIL(&ecp->v_sec, sec, sec_list);
inc_nos:
if (sec->pseudo == 0)
ecp->nos++;
}
@ -1338,10 +1335,9 @@ insert_sections(struct elfcopy *ecp)
void
add_to_shstrtab(struct elfcopy *ecp, const char *name)
{
struct section *s;
s = ecp->shstrtab;
insert_to_strtab(s, name);
if (elftc_string_table_insert(ecp->shstrtab->strtab, name) == 0)
errx(EXIT_FAILURE, "elftc_string_table_insert failed");
}
void
@ -1351,6 +1347,9 @@ update_shdr(struct elfcopy *ecp, int update_link)
GElf_Shdr osh;
int elferr;
/* Finalize the section name string table (.shstrtab). */
set_shstrtab(ecp);
TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
if (s->pseudo)
continue;
@ -1360,7 +1359,8 @@ update_shdr(struct elfcopy *ecp, int update_link)
elf_errmsg(-1));
/* Find section name in string table and set sh_name. */
osh.sh_name = lookup_string(ecp->shstrtab, s->name);
osh.sh_name = elftc_string_table_lookup(ecp->shstrtab->strtab,
s->name);
/*
* sh_link needs to be updated, since the index of the
@ -1410,19 +1410,22 @@ init_shstrtab(struct elfcopy *ecp)
s->loadable = 0;
s->type = SHT_STRTAB;
s->vma = 0;
s->strtab = elftc_string_table_create(0);
insert_to_strtab(s, "");
insert_to_strtab(s, ".symtab");
insert_to_strtab(s, ".strtab");
insert_to_strtab(s, ".shstrtab");
add_to_shstrtab(ecp, "");
add_to_shstrtab(ecp, ".symtab");
add_to_shstrtab(ecp, ".strtab");
add_to_shstrtab(ecp, ".shstrtab");
}
void
static void
set_shstrtab(struct elfcopy *ecp)
{
struct section *s;
Elf_Data *data;
GElf_Shdr sh;
const char *image;
size_t sz;
s = ecp->shstrtab;
@ -1455,19 +1458,21 @@ set_shstrtab(struct elfcopy *ecp)
* which are reserved for this in the beginning of shstrtab.
*/
if (!(ecp->flags & SYMTAB_EXIST)) {
s->sz -= sizeof(".symtab\0.strtab");
memmove(s->buf, (char *)s->buf + sizeof(".symtab\0.strtab"),
s->sz);
elftc_string_table_remove(s->strtab, ".symtab");
elftc_string_table_remove(s->strtab, ".strtab");
}
sh.sh_size = s->sz;
image = elftc_string_table_image(s->strtab, &sz);
s->sz = sz;
sh.sh_size = sz;
if (!gelf_update_shdr(s->os, &sh))
errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
elf_errmsg(-1));
data->d_align = 1;
data->d_buf = s->buf;
data->d_size = s->sz;
data->d_buf = (void *)(uintptr_t)image;
data->d_size = sz;
data->d_off = 0;
data->d_type = ELF_T_BYTE;
data->d_version = EV_CURRENT;
@ -1593,73 +1598,6 @@ add_gnu_debuglink(struct elfcopy *ecp)
ecp->flags |= SEC_ADD;
}
static void
insert_to_strtab(struct section *t, const char *s)
{
const char *r;
char *b, *c;
size_t len, slen;
int append;
if (t->sz == 0) {
t->cap = 512;
if ((t->buf = malloc(t->cap)) == NULL)
err(EXIT_FAILURE, "malloc failed");
}
slen = strlen(s);
append = 0;
b = t->buf;
for (c = b; c < b + t->sz;) {
len = strlen(c);
if (!append && len >= slen) {
r = c + (len - slen);
if (strcmp(r, s) == 0)
return;
} else if (len < slen && len != 0) {
r = s + (slen - len);
if (strcmp(c, r) == 0) {
t->sz -= len + 1;
memmove(c, c + len + 1, t->sz - (c - b));
append = 1;
continue;
}
}
c += len + 1;
}
while (t->sz + slen + 1 >= t->cap) {
t->cap *= 2;
if ((t->buf = realloc(t->buf, t->cap)) == NULL)
err(EXIT_FAILURE, "realloc failed");
}
b = t->buf;
strncpy(&b[t->sz], s, slen);
b[t->sz + slen] = '\0';
t->sz += slen + 1;
}
static int
lookup_string(struct section *t, const char *s)
{
const char *b, *c, *r;
size_t len, slen;
slen = strlen(s);
b = t->buf;
for (c = b; c < b + t->sz;) {
len = strlen(c);
if (len >= slen) {
r = c + (len - slen);
if (strcmp(r, s) == 0)
return (r - b);
}
c += len + 1;
}
return (-1);
}
static uint32_t crctable[256] =
{
0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,

View File

@ -44,7 +44,7 @@ _dwarf_get_reloc_type(Dwarf_P_Debug dbg, int is64)
case DW_ISA_SPARC:
return (is64 ? R_SPARC_UA64 : R_SPARC_UA32);
case DW_ISA_PPC:
return (R_PPC_ADDR32);
return (is64 ? R_PPC64_ADDR64 : R_PPC_ADDR32);
case DW_ISA_ARM:
return (R_ARM_ABS32);
case DW_ISA_MIPS:
@ -97,6 +97,12 @@ _dwarf_get_reloc_size(Dwarf_Debug dbg, Dwarf_Unsigned rel_type)
if (rel_type == R_PPC_ADDR32)
return (4);
break;
case EM_PPC64:
if (rel_type == R_PPC_ADDR32)
return (4);
else if (rel_type == R_PPC64_ADDR64)
return (8);
break;
case EM_MIPS:
if (rel_type == R_MIPS_32)
return (4);

View File

@ -30,6 +30,7 @@
#define __LIBELF_H_
#include <sys/queue.h>
#include <sys/tree.h>
#include "_libelf_config.h"
@ -80,6 +81,9 @@ extern struct _libelf_globals _libelf;
#define LIBELF_F_SHDRS_LOADED 0x200000U /* whether all shdrs were read in */
#define LIBELF_F_SPECIAL_FILE 0x400000U /* non-regular file */
RB_HEAD(scntree, _Elf_Scn);
RB_PROTOTYPE(scntree, _Elf_Scn, e_scn, elfscn_cmp);
struct _Elf {
int e_activations; /* activation count */
unsigned int e_byteorder; /* ELFDATA* */
@ -122,7 +126,7 @@ struct _Elf {
Elf32_Phdr *e_phdr32;
Elf64_Phdr *e_phdr64;
} e_phdr;
STAILQ_HEAD(, _Elf_Scn) e_scn; /* section list */
struct scntree e_scn; /* sections */
size_t e_nphdr; /* number of Phdr entries */
size_t e_nscn; /* number of sections */
size_t e_strndx; /* string table section index */
@ -147,7 +151,7 @@ struct _Elf_Scn {
} s_shdr;
STAILQ_HEAD(, _Libelf_Data) s_data; /* translated data */
STAILQ_HEAD(, _Libelf_Data) s_rawdata; /* raw data */
STAILQ_ENTRY(_Elf_Scn) s_next;
RB_ENTRY(_Elf_Scn) s_tree;
struct _Elf *s_elf; /* parent ELF descriptor */
unsigned int s_flags; /* flags for the section as a whole */
size_t s_ndx; /* index# for this section */

View File

@ -66,8 +66,7 @@ elf_end(Elf *e)
/*
* Reclaim all section descriptors.
*/
STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next,
tscn)
RB_FOREACH_SAFE(scn, scntree, &e->e_u.e_elf.e_scn, tscn)
scn = _libelf_release_scn(scn);
break;
case ELF_K_NUM:

View File

@ -38,6 +38,19 @@
ELFTC_VCSID("$Id: elf_scn.c 3632 2018-10-10 21:12:43Z jkoshy $");
static int
elfscn_cmp(struct _Elf_Scn *s1, struct _Elf_Scn *s2)
{
if (s1->s_ndx < s2->s_ndx)
return (-1);
if (s1->s_ndx > s2->s_ndx)
return (1);
return (0);
}
RB_GENERATE(scntree, _Elf_Scn, s_tree, elfscn_cmp);
/*
* Load an ELF section table and create a list of Elf_Scn structures.
*/
@ -95,9 +108,9 @@ _libelf_load_section_headers(Elf *e, void *ehdr)
*/
i = 0;
if (!STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) {
assert(STAILQ_FIRST(&e->e_u.e_elf.e_scn) ==
STAILQ_LAST(&e->e_u.e_elf.e_scn, _Elf_Scn, s_next));
if (!RB_EMPTY(&e->e_u.e_elf.e_scn)) {
assert(RB_MIN(scntree, &e->e_u.e_elf.e_scn) ==
RB_MAX(scntree, &e->e_u.e_elf.e_scn));
i = 1;
src += fsz;
@ -148,10 +161,16 @@ elf_getscn(Elf *e, size_t index)
_libelf_load_section_headers(e, ehdr) == 0)
return (NULL);
STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next)
for (s = RB_ROOT(&e->e_u.e_elf.e_scn); s != NULL;) {
if (s->s_ndx == index)
return (s);
if (s->s_ndx < index)
s = RB_RIGHT(s, s_tree);
else
s = RB_LEFT(s, s_tree);
}
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
@ -201,7 +220,7 @@ elf_newscn(Elf *e)
_libelf_load_section_headers(e, ehdr) == 0)
return (NULL);
if (STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) {
if (RB_EMPTY(&e->e_u.e_elf.e_scn)) {
assert(e->e_u.e_elf.e_nscn == 0);
if ((scn = _libelf_allocate_scn(e, (size_t) SHN_UNDEF)) ==
NULL)
@ -231,5 +250,5 @@ elf_nextscn(Elf *e, Elf_Scn *s)
}
return (s == NULL ? elf_getscn(e, (size_t) 1) :
STAILQ_NEXT(s, s_next));
RB_NEXT(scntree, &e->e_u.e_elf.e_scn, s));
}

View File

@ -452,7 +452,7 @@ _libelf_resync_sections(Elf *e, off_t rc, struct _Elf_Extent_List *extents)
* Make a pass through sections, computing the extent of each
* section.
*/
STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next) {
RB_FOREACH(s, scntree, &e->e_u.e_elf.e_scn) {
if (ec == ELFCLASS32)
sh_type = s->s_shdr.s_shdr32.sh_type;
else
@ -980,7 +980,7 @@ _libelf_write_shdr(Elf *e, unsigned char *nf, struct _Elf_Extent *ex)
fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1);
STAILQ_FOREACH(scn, &e->e_u.e_elf.e_scn, s_next) {
RB_FOREACH(scn, scntree, &e->e_u.e_elf.e_scn) {
if (ec == ELFCLASS32)
src.d_buf = &scn->s_shdr.s_shdr32;
else
@ -1142,7 +1142,7 @@ _libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents)
e->e_flags &= ~ELF_F_DIRTY;
STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next, tscn)
RB_FOREACH_SAFE(scn, scntree, &e->e_u.e_elf.e_scn, tscn)
_libelf_release_scn(scn);
if (e->e_class == ELFCLASS32) {

View File

@ -76,7 +76,7 @@ _libelf_init_elf(Elf *e, Elf_Kind kind)
switch (kind) {
case ELF_K_ELF:
STAILQ_INIT(&e->e_u.e_elf.e_scn);
RB_INIT(&e->e_u.e_elf.e_scn);
break;
default:
break;
@ -111,7 +111,7 @@ _libelf_release_elf(Elf *e)
break;
}
assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
assert(RB_EMPTY(&e->e_u.e_elf.e_scn));
if (e->e_flags & LIBELF_F_AR_HEADER) {
arh = e->e_hdr.e_arhdr;
@ -174,7 +174,7 @@ _libelf_allocate_scn(Elf *e, size_t ndx)
STAILQ_INIT(&s->s_data);
STAILQ_INIT(&s->s_rawdata);
STAILQ_INSERT_TAIL(&e->e_u.e_elf.e_scn, s, s_next);
RB_INSERT(scntree, &e->e_u.e_elf.e_scn, s);
return (s);
}
@ -202,7 +202,7 @@ _libelf_release_scn(Elf_Scn *s)
assert(e != NULL);
STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next);
RB_REMOVE(scntree, &e->e_u.e_elf.e_scn, s);
free(s);

View File

@ -46,7 +46,7 @@ _libelf_load_extended(Elf *e, int ec, uint64_t shoff, uint16_t phnum,
uint32_t shtype;
_libelf_translator_function *xlator;
assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
assert(RB_EMPTY(&e->e_u.e_elf.e_scn));
fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, 1);
assert(fsz > 0);

View File

@ -39,7 +39,7 @@ _libelf_getscn0(Elf *e)
{
Elf_Scn *s;
if ((s = STAILQ_FIRST(&e->e_u.e_elf.e_scn)) != NULL)
if ((s = RB_MIN(scntree, &e->e_u.e_elf.e_scn)) != NULL)
return (s);
return (_libelf_allocate_scn(e, (size_t) SHN_UNDEF));

View File

@ -167,11 +167,9 @@ elftc_string_table_destroy(Elftc_String_Table *st)
for (n = 0; n < st->st_nbuckets; n++)
SLIST_FOREACH_SAFE(s, &st->st_buckets[n], ste_next, t)
free(s);
free(s);
free(st->st_string_pool);
free(st);
return;
}
Elftc_String_Table *
@ -318,7 +316,7 @@ elftc_string_table_insert(Elftc_String_Table *st, const char *string)
if ((ste = malloc(sizeof(*ste))) == NULL)
return (0);
if ((ste->ste_idx = elftc_string_table_add_to_pool(st,
string)) == 0) {
string)) == 0) {
free(ste);
return (0);
}

View File

@ -144,7 +144,7 @@ looks up the string referenced by argument
in the string table specified by argument
.Ar table ,
and if found, returns the offset associated with the string.
The returned offset will be valid till the next call to function
The returned offset will be valid until the next call to
.Fn elftc_string_table_image .
.Pp
Function

View File

@ -24,7 +24,7 @@
.\"
.\" $Id: readelf.1 3642 2018-10-14 14:24:28Z jkoshy $
.\"
.Dd September 13, 2012
.Dd May 30, 2019
.Dt READELF 1
.Os
.Sh NAME
@ -113,6 +113,8 @@ Print symbol tables.
.It Fl t | Fl -section-details
Print additional information about sections, such as the flags
fields in section headers.
Implies
.Fl S .
.It Fl v | Fl -version
Prints a version identifier for
.Nm

View File

@ -7500,7 +7500,7 @@ main(int argc, char **argv)
re->options |= RE_S;
break;
case 't':
re->options |= RE_T;
re->options |= RE_SS | RE_T;
break;
case 'u':
re->options |= RE_U;

View File

@ -1,3 +1,13 @@
Apr 16, 2019: Support for non-recursive list and extract
Apr 14, 2019: New tar option: --exclude-vcs
Mar 27, 2019: Support for file and directory symlinks on Windows
Mar 12, 2019: Important fixes for storing file attributes and flags
Jan 20, 2019: Support for xz, lzma, ppmd8 and bzip2 compression in zip archives
Oct 06, 2018: RAR 5.0 reader
Sep 03, 2018: libarchive 3.3.3 released

View File

@ -46,7 +46,7 @@ verify_files(const char *msg)
/* Symlink */
if (canSymlink())
assertIsSymlink("symlink", "file");
assertIsSymlink("symlink", "file", 0);
/* Another file with 1 link and different permissions. */
failure(msg);
@ -173,7 +173,7 @@ DEFINE_TEST(test_basic)
/* Symlink to above file. */
if (canSymlink()) {
assertMakeSymlink("symlink", "file");
assertMakeSymlink("symlink", "file", 0);
fprintf(filelist, "symlink\n");
if (is_LargeInode("symlink")) {
strncat(result,

View File

@ -114,7 +114,7 @@ DEFINE_TEST(test_format_newc)
/* "symlink" */
if (canSymlink()) {
assertMakeSymlink("symlink", "file1");
assertMakeSymlink("symlink", "file1", 0);
fprintf(list, "symlink\n");
}
@ -233,7 +233,12 @@ DEFINE_TEST(test_format_newc)
assert(is_hex(e, 110));
assertEqualMem(e + 0, "070701", 6); /* Magic */
assert(is_hex(e + 6, 8)); /* ino */
#if defined(_WIN32) && !defined(CYGWIN)
/* Mode: Group members bits and others bits do not work. */
assertEqualInt(0xa180, from_hex(e + 14, 8) & 0xffc0);
#else
assertEqualInt(0xa1ff, from_hex(e + 14, 8)); /* Mode */
#endif
assertEqualInt(from_hex(e + 22, 8), uid); /* uid */
assertEqualInt(gid, from_hex(e + 30, 8)); /* gid */
assertEqualMem(e + 38, "00000001", 8); /* nlink */

View File

@ -71,7 +71,7 @@ unpack_test(const char *from, const char *options, const char *se)
/* Symlink */
if (canSymlink())
assertIsSymlink("symlink", "file");
assertIsSymlink("symlink", "file", 0);
/* dir */
assertIsDir("dir", 0775);

View File

@ -30,8 +30,10 @@ __FBSDID("$FreeBSD$");
* tests won't run on Windows. */
#if defined(_WIN32) && !defined(__CYGWIN__)
#define CAT "type"
#define SEP "\\"
#else
#define CAT "cat"
#define SEP "/"
#endif
DEFINE_TEST(test_option_L_upper)
@ -51,7 +53,7 @@ DEFINE_TEST(test_option_L_upper)
fprintf(filelist, "file\n");
/* Symlink to above file. */
assertMakeSymlink("symlink", "file");
assertMakeSymlink("symlink", "file", 0);
fprintf(filelist, "symlink\n");
fclose(filelist);
@ -61,7 +63,7 @@ DEFINE_TEST(test_option_L_upper)
assertTextFileContents("1 block\n", "copy.err");
failure("Regular -p without -L should preserve symlinks.");
assertIsSymlink("copy/symlink", NULL);
assertIsSymlink("copy/symlink", NULL, 0);
r = systemf(CAT " filelist | %s -pd -L copy-L >copy-L.out 2>copy-L.err", testprog);
assertEqualInt(r, 0);
@ -77,13 +79,14 @@ DEFINE_TEST(test_option_L_upper)
assertMakeDir("unpack", 0755);
assertChdir("unpack");
r = systemf(CAT " ../archive.out | %s -i >unpack.out 2>unpack.err", testprog);
r = systemf(CAT " .." SEP "archive.out | %s -i >unpack.out 2>unpack.err", testprog);
failure("Error invoking %s -i", testprog);
assertEqualInt(r, 0);
assertTextFileContents("1 block\n", "unpack.err");
assertChdir("..");
assertIsSymlink("unpack/symlink", NULL);
assertIsSymlink("unpack/symlink", NULL, 0);
r = systemf(CAT " filelist | %s -oL >archive-L.out 2>archive-L.err", testprog);
failure("Error invoking %s -oL", testprog);
@ -92,7 +95,8 @@ DEFINE_TEST(test_option_L_upper)
assertMakeDir("unpack-L", 0755);
assertChdir("unpack-L");
r = systemf(CAT " ../archive-L.out | %s -i >unpack-L.out 2>unpack-L.err", testprog);
r = systemf(CAT " .." SEP "archive-L.out | %s -i >unpack-L.out 2>unpack-L.err", testprog);
failure("Error invoking %s -i < archive-L.out", testprog);
assertEqualInt(r, 0);
assertTextFileContents("1 block\n", "unpack-L.err");

View File

@ -71,8 +71,13 @@ test_create(void)
* #ifdef this section out. Most of the test below is
* still valid. */
memset(&times, 0, sizeof(times));
#if defined(_WIN32) && !defined(CYGWIN)
times.actime = 86400;
times.modtime = 86400;
#else
times.actime = 1;
times.modtime = 3;
#endif
assertEqualInt(0, utime(files[i].name, &times));
/* Record whatever atime the file ended up with. */

View File

@ -85,7 +85,7 @@ DEFINE_TEST(test_option_c)
/* "symlink" */
if (canSymlink()) {
assertMakeSymlink("symlink", "file");
assertMakeSymlink("symlink", "file", 0);
fprintf(filelist, "symlink\n");
}

View File

@ -338,9 +338,9 @@ typedef const char *archive_passphrase_callback(struct archive *,
#define ARCHIVE_FORMAT_LHA 0xB0000
#define ARCHIVE_FORMAT_CAB 0xC0000
#define ARCHIVE_FORMAT_RAR 0xD0000
#define ARCHIVE_FORMAT_RAR_V5 (ARCHIVE_FORMAT_RAR | 1)
#define ARCHIVE_FORMAT_7ZIP 0xE0000
#define ARCHIVE_FORMAT_WARC 0xF0000
#define ARCHIVE_FORMAT_RAR_V5 0x100000
/*
* Codes returned by archive_read_format_capabilities().
@ -1095,6 +1095,8 @@ __LA_DECL int archive_match_excluded(struct archive *,
*/
__LA_DECL int archive_match_path_excluded(struct archive *,
struct archive_entry *);
/* Control recursive inclusion of directory content when directory is included. Default on. */
__LA_DECL int archive_match_set_inclusion_recursion(struct archive *, int);
/* Add exclusion pathname pattern. */
__LA_DECL int archive_match_exclude_pattern(struct archive *, const char *);
__LA_DECL int archive_match_exclude_pattern_w(struct archive *,

View File

@ -168,6 +168,7 @@ archive_entry_clear(struct archive_entry *entry)
archive_entry_xattr_clear(entry);
archive_entry_sparse_clear(entry);
free(entry->stat);
entry->ae_symlink_type = AE_SYMLINK_TYPE_UNDEFINED;
memset(entry, 0, sizeof(*entry));
return entry;
}
@ -202,6 +203,9 @@ archive_entry_clone(struct archive_entry *entry)
entry2->ae_set = entry->ae_set;
archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname);
/* Copy symlink type */
entry2->ae_symlink_type = entry->ae_symlink_type;
/* Copy encryption status */
entry2->encryption = entry->encryption;
@ -253,6 +257,7 @@ archive_entry_new2(struct archive *a)
if (entry == NULL)
return (NULL);
entry->archive = a;
entry->ae_symlink_type = AE_SYMLINK_TYPE_UNDEFINED;
return (entry);
}
@ -675,6 +680,12 @@ archive_entry_symlink(struct archive_entry *entry)
return (NULL);
}
int
archive_entry_symlink_type(struct archive_entry *entry)
{
return (entry->ae_symlink_type);
}
const char *
archive_entry_symlink_utf8(struct archive_entry *entry)
{
@ -1245,6 +1256,12 @@ archive_entry_set_symlink(struct archive_entry *entry, const char *linkname)
entry->ae_set &= ~AE_SET_SYMLINK;
}
void
archive_entry_set_symlink_type(struct archive_entry *entry, int type)
{
entry->ae_symlink_type = type;
}
void
archive_entry_set_symlink_utf8(struct archive_entry *entry, const char *linkname)
{
@ -1749,6 +1766,10 @@ static const struct flag {
{ "nohidden", L"nohidden", UF_HIDDEN, 0},
{ "nouhidden", L"nouhidden", UF_HIDDEN, 0},
#endif
#ifdef FILE_ATTRIBUTE_HIDDEN
{ "nohidden", L"nohidden", FILE_ATTRIBUTE_HIDDEN, 0},
{ "nouhidden", L"nouhidden", FILE_ATTRIBUTE_HIDDEN, 0},
#endif
#ifdef UF_OFFLINE
{ "nooffline", L"nooffline", UF_OFFLINE, 0},
{ "nouoffline", L"nouoffline", UF_OFFLINE, 0},
@ -1758,6 +1779,11 @@ static const struct flag {
{ "nourdonly", L"nourdonly", UF_READONLY, 0},
{ "noreadonly", L"noreadonly", UF_READONLY, 0},
#endif
#ifdef FILE_ATTRIBUTE_READONLY
{ "nordonly", L"nordonly", FILE_ATTRIBUTE_READONLY, 0},
{ "nourdonly", L"nourdonly", FILE_ATTRIBUTE_READONLY, 0},
{ "noreadonly", L"noreadonly", FILE_ATTRIBUTE_READONLY, 0},
#endif
#ifdef UF_SPARSE
{ "nosparse", L"nosparse", UF_SPARSE, 0},
{ "nousparse", L"nousparse", UF_SPARSE, 0},
@ -1770,6 +1796,10 @@ static const struct flag {
{ "nosystem", L"nosystem", UF_SYSTEM, 0},
{ "nousystem", L"nousystem", UF_SYSTEM, 0},
#endif
#ifdef FILE_ATTRIBUTE_SYSTEM
{ "nosystem", L"nosystem", FILE_ATTRIBUTE_SYSTEM, 0},
{ "nousystem", L"nousystem", FILE_ATTRIBUTE_SYSTEM, 0},
#endif
#if defined(FS_UNRM_FL) /* 'u' */
{ "noundel", L"noundel", FS_UNRM_FL, 0},
#elif defined(EXT2_UNRM_FL)

View File

@ -190,6 +190,13 @@ struct archive_entry;
#define AE_IFDIR ((__LA_MODE_T)0040000)
#define AE_IFIFO ((__LA_MODE_T)0010000)
/*
* Symlink types
*/
#define AE_SYMLINK_TYPE_UNDEFINED 0
#define AE_SYMLINK_TYPE_FILE 1
#define AE_SYMLINK_TYPE_DIRECTORY 2
/*
* Basic object manipulation
*/
@ -275,6 +282,7 @@ __LA_DECL int archive_entry_size_is_set(struct archive_entry *);
__LA_DECL const char *archive_entry_strmode(struct archive_entry *);
__LA_DECL const char *archive_entry_symlink(struct archive_entry *);
__LA_DECL const char *archive_entry_symlink_utf8(struct archive_entry *);
__LA_DECL int archive_entry_symlink_type(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_symlink_w(struct archive_entry *);
__LA_DECL la_int64_t archive_entry_uid(struct archive_entry *);
__LA_DECL const char *archive_entry_uname(struct archive_entry *);
@ -350,6 +358,7 @@ __LA_DECL void archive_entry_unset_size(struct archive_entry *);
__LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_sourcepath_w(struct archive_entry *, const wchar_t *);
__LA_DECL void archive_entry_set_symlink(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_symlink_type(struct archive_entry *, int);
__LA_DECL void archive_entry_set_symlink_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_symlink(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *);
@ -692,7 +701,6 @@ __LA_DECL void archive_entry_linkify(struct archive_entry_linkresolver *,
struct archive_entry **, struct archive_entry **);
__LA_DECL struct archive_entry *archive_entry_partial_links(
struct archive_entry_linkresolver *res, unsigned int *links);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,62 @@
.\" Copyright (c) 2019 Martin Matuska
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd April 15, 2019
.Dt ARCHIVE_ENTRY_MISC 3
.Os
.Sh NAME
.Nm archive_entry_symlink_type ,
.Nm archive_entry_set_symlink_type
.Nd miscellaneous functions for manipulating properties of archive_entry.
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive_entry.h
.Ft int
.Fn archive_entry_symlink_type "struct archive_entry *a"
.Ft void
.Fn archive_entry_set_symlink_type "struct archive_entry *a" "int"
.Sh DESCRIPTION
The function
.Fn archive_entry_symlink_type
returns and the function
.Fn archive_entry_set_symlink_type
sets the type of the symbolic link stored in an archive entry. These functions
have special meaning on operating systems that support multiple symbolic link
types (e.g. Microsoft Windows).
.Pp
Supported values are:
.Bl -tag -width "AE_SYMLINK_TYPE_DIRECTORY" -compact
.It AE_SYMLINK_TYPE_UNDEFINED
Symbolic link target type is not defined (default on unix systems)
.It AE_SYMLINK_TYPE_FILE
Symbolic link points to a file
.It AE_SYMLINK_TYPE_DIRECTORY
Symbolic link points to a directory
.El
.Sh SEE ALSO
.Xr archive_entry 3 ,
.Xr archive_entry_paths 3 ,
.Xr archive_entry_stat 3 ,
.Xr libarchive 3

View File

@ -176,6 +176,9 @@ struct archive_entry {
/* Miscellaneous. */
char strmode[12];
/* Symlink type support */
int ae_symlink_type;
};
#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */

View File

@ -83,6 +83,7 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
static int
__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
{
#pragma GCC diagnostic ignored "-Wcast-qual"
BCRYPT_ALG_HANDLE hAlg;
BCRYPT_HASH_HANDLE hHash;
DWORD hash_len;

View File

@ -93,6 +93,9 @@ struct archive_match {
/* exclusion/inclusion set flag. */
int setflag;
/* Recursively include directory content? */
int recursive_include;
/*
* Matching filename patterns.
*/
@ -223,6 +226,7 @@ archive_match_new(void)
return (NULL);
a->archive.magic = ARCHIVE_MATCH_MAGIC;
a->archive.state = ARCHIVE_STATE_NEW;
a->recursive_include = 1;
match_list_init(&(a->inclusions));
match_list_init(&(a->exclusions));
__archive_rb_tree_init(&(a->exclusion_tree), &rb_ops_mbs);
@ -470,6 +474,28 @@ archive_match_path_excluded(struct archive *_a,
#endif
}
/*
* When recursive inclusion of directory content is enabled,
* an inclusion pattern that matches a directory will also
* include everything beneath that directory. Enabled by default.
*
* For compatibility with GNU tar, exclusion patterns always
* match if a subset of the full patch matches (i.e., they are
* are not rooted at the beginning of the path) and thus there
* is no corresponding non-recursive exclusion mode.
*/
int
archive_match_set_inclusion_recursion(struct archive *_a, int enabled)
{
struct archive_match *a;
archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
ARCHIVE_STATE_NEW, "archive_match_set_inclusion_recursion");
a = (struct archive_match *)_a;
a->recursive_include = enabled;
return (ARCHIVE_OK);
}
/*
* Utility functions to get statistic information for inclusion patterns.
*/
@ -781,7 +807,10 @@ static int
match_path_inclusion(struct archive_match *a, struct match *m,
int mbs, const void *pn)
{
int flag = PATHMATCH_NO_ANCHOR_END;
/* Recursive operation requires only a prefix match. */
int flag = a->recursive_include ?
PATHMATCH_NO_ANCHOR_END :
0;
int r;
if (mbs) {
@ -1232,7 +1261,7 @@ set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
archive_set_error(&(a->archive), EINVAL, "pathname is empty");
return (ARCHIVE_FAILED);
}
if (stat(path, &st) != 0) {
if (la_stat(path, &st) != 0) {
archive_set_error(&(a->archive), errno, "Failed to stat()");
return (ARCHIVE_FAILED);
}

View File

@ -69,6 +69,8 @@
* either Windows or Posix APIs. */
#if (defined(__WIN32__) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)
#include "archive_windows.h"
#else
#define la_stat(path,stref) stat(path,stref)
#endif
/*

View File

@ -611,6 +611,15 @@ choose_filters(struct archive_read *a)
return (ARCHIVE_FATAL);
}
int
__archive_read_header(struct archive_read *a, struct archive_entry *entry)
{
if (a->filter->read_header)
return a->filter->read_header(a->filter, entry);
else
return (ARCHIVE_OK);
}
/*
* Read header of next entry.
*/

View File

@ -191,7 +191,7 @@ archive_read_disk_entry_from_file(struct archive *_a,
}
} else
#endif
if (stat(path, &s) != 0) {
if (la_stat(path, &s) != 0) {
archive_set_error(&a->archive, errno,
"Can't stat %s", path);
return (ARCHIVE_FAILED);

View File

@ -909,7 +909,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
}
}
break;
}
}
} while (lst == NULL);
#ifdef __APPLE__
@ -1295,10 +1295,23 @@ archive_read_disk_descend(struct archive *_a)
if (t->visit_type != TREE_REGULAR || !t->descend)
return (ARCHIVE_OK);
/*
* We must not treat the initial specified path as a physical dir,
* because if we do then we will try and ascend out of it by opening
* ".." which is (a) wrong and (b) causes spurious permissions errors
* if ".." is not readable by us. Instead, treat it as if it were a
* symlink. (This uses an extra fd, but it can only happen once at the
* top level of a traverse.) But we can't necessarily assume t->st is
* valid here (though t->lst is), which complicates the logic a
* little.
*/
if (tree_current_is_physical_dir(t)) {
tree_push(t, t->basename, t->current_filesystem_id,
t->lst.st_dev, t->lst.st_ino, &t->restore_time);
t->stack->flags |= isDir;
if (t->stack->parent->parent != NULL)
t->stack->flags |= isDir;
else
t->stack->flags |= isDirLink;
} else if (tree_current_is_dir(t)) {
tree_push(t, t->basename, t->current_filesystem_id,
t->st.st_dev, t->st.st_ino, &t->restore_time);
@ -2151,6 +2164,17 @@ tree_open(const char *path, int symlink_mode, int restore_time)
static struct tree *
tree_reopen(struct tree *t, const char *path, int restore_time)
{
#if defined(O_PATH)
/* Linux */
const int o_flag = O_PATH;
#elif defined(O_SEARCH)
/* SunOS */
const int o_flag = O_SEARCH;
#elif defined(O_EXEC)
/* FreeBSD */
const int o_flag = O_EXEC;
#endif
t->flags = (restore_time != 0)?needsRestoreTimes:0;
t->flags |= onInitialDir;
t->visit_type = 0;
@ -2172,6 +2196,15 @@ tree_reopen(struct tree *t, const char *path, int restore_time)
t->stack->flags = needsFirstVisit;
t->maxOpenCount = t->openCount = 1;
t->initial_dir_fd = open(".", O_RDONLY | O_CLOEXEC);
#if defined(O_PATH) || defined(O_SEARCH) || defined(O_EXEC)
/*
* Most likely reason to fail opening "." is that it's not readable,
* so try again for execute. The consequences of not opening this are
* unhelpful and unnecessary errors later.
*/
if (t->initial_dir_fd < 0)
t->initial_dir_fd = open(".", o_flag | O_CLOEXEC);
#endif
__archive_ensure_cloexec_flag(t->initial_dir_fd);
t->working_dir_fd = tree_dup(t->initial_dir_fd);
return (t);
@ -2479,7 +2512,7 @@ tree_current_stat(struct tree *t)
#else
if (tree_enter_working_dir(t) != 0)
return NULL;
if (stat(tree_current_access_path(t), &t->st) != 0)
if (la_stat(tree_current_access_path(t), &t->st) != 0)
#endif
return NULL;
t->flags |= hasStat;

View File

@ -98,6 +98,8 @@ struct archive_read_filter {
int (*close)(struct archive_read_filter *self);
/* Function that handles switching from reading one block to the next/prev */
int (*sswitch)(struct archive_read_filter *self, unsigned int iindex);
/* Read any header metadata if available. */
int (*read_header)(struct archive_read_filter *self, struct archive_entry *entry);
/* My private data. */
void *data;
@ -250,6 +252,7 @@ int64_t __archive_read_seek(struct archive_read*, int64_t, int);
int64_t __archive_read_filter_seek(struct archive_read_filter *, int64_t, int);
int64_t __archive_read_consume(struct archive_read *, int64_t);
int64_t __archive_read_filter_consume(struct archive_read_filter *, int64_t);
int __archive_read_header(struct archive_read *, struct archive_entry *);
int __archive_read_program(struct archive_read_filter *, const char *);
void __archive_read_free_filters(struct archive_read *);
struct archive_read_extract *__archive_read_get_extract(struct archive_read *);

View File

@ -73,6 +73,9 @@ archive_read_set_format(struct archive *_a, int code)
case ARCHIVE_FORMAT_RAR:
strcpy(str, "rar");
break;
case ARCHIVE_FORMAT_RAR_V5:
strcpy(str, "rar5");
break;
case ARCHIVE_FORMAT_TAR:
strcpy(str, "tar");
break;

View File

@ -37,6 +37,9 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@ -45,6 +48,8 @@ __FBSDID("$FreeBSD$");
#endif
#include "archive.h"
#include "archive_entry.h"
#include "archive_endian.h"
#include "archive_private.h"
#include "archive_read_private.h"
@ -56,6 +61,8 @@ struct private_data {
size_t out_block_size;
int64_t total_out;
unsigned long crc;
uint32_t mtime;
char *name;
char eof; /* True = found end of compressed data. */
};
@ -123,7 +130,8 @@ archive_read_support_filter_gzip(struct archive *_a)
* count of bits verified, suitable for use by bidder.
*/
static ssize_t
peek_at_header(struct archive_read_filter *filter, int *pbits)
peek_at_header(struct archive_read_filter *filter, int *pbits,
struct private_data *state)
{
const unsigned char *p;
ssize_t avail, len;
@ -144,7 +152,9 @@ peek_at_header(struct archive_read_filter *filter, int *pbits)
return (0);
bits += 3;
header_flags = p[3];
/* Bytes 4-7 are mod time. */
/* Bytes 4-7 are mod time in little endian. */
if (state)
state->mtime = archive_le32dec(p + 4);
/* Byte 8 is deflate flags. */
/* XXXX TODO: return deflate flags back to consume_header for use
in initializing the decompressor. */
@ -161,6 +171,7 @@ peek_at_header(struct archive_read_filter *filter, int *pbits)
/* Null-terminated optional filename. */
if (header_flags & 8) {
ssize_t file_start = len;
do {
++len;
if (avail < len)
@ -169,6 +180,12 @@ peek_at_header(struct archive_read_filter *filter, int *pbits)
if (p == NULL)
return (0);
} while (p[len - 1] != 0);
if (state) {
/* Reset the name in case of repeat header reads. */
free(state->name);
state->name = strdup((const char *)&p[file_start]);
}
}
/* Null-terminated optional comment. */
@ -214,11 +231,28 @@ gzip_bidder_bid(struct archive_read_filter_bidder *self,
(void)self; /* UNUSED */
if (peek_at_header(filter, &bits_checked))
if (peek_at_header(filter, &bits_checked, NULL))
return (bits_checked);
return (0);
}
static int
gzip_read_header(struct archive_read_filter *self, struct archive_entry *entry)
{
struct private_data *state;
state = (struct private_data *)self->data;
/* A mtime of 0 is considered invalid/missing. */
if (state->mtime != 0)
archive_entry_set_mtime(entry, state->mtime, 0);
/* If the name is available, extract it. */
if (state->name)
archive_entry_set_pathname(entry, state->name);
return (ARCHIVE_OK);
}
#ifndef HAVE_ZLIB_H
@ -272,6 +306,7 @@ gzip_bidder_init(struct archive_read_filter *self)
self->read = gzip_filter_read;
self->skip = NULL; /* not supported */
self->close = gzip_filter_close;
self->read_header = gzip_read_header;
state->in_stream = 0; /* We're not actually within a stream yet. */
@ -289,7 +324,7 @@ consume_header(struct archive_read_filter *self)
state = (struct private_data *)self->data;
/* If this is a real header, consume it. */
len = peek_at_header(self->upstream, NULL);
len = peek_at_header(self->upstream, NULL, state);
if (len == 0)
return (ARCHIVE_EOF);
__archive_read_filter_consume(self->upstream, len);
@ -374,7 +409,7 @@ gzip_filter_read(struct archive_read_filter *self, const void **p)
{
struct private_data *state;
size_t decompressed;
ssize_t avail_in;
ssize_t avail_in, max_in;
int ret;
state = (struct private_data *)self->data;
@ -408,6 +443,12 @@ gzip_filter_read(struct archive_read_filter *self, const void **p)
"truncated gzip input");
return (ARCHIVE_FATAL);
}
if (UINT_MAX >= SSIZE_MAX)
max_in = SSIZE_MAX;
else
max_in = UINT_MAX;
if (avail_in > max_in)
avail_in = max_in;
state->stream.avail_in = (uInt)avail_in;
/* Decompress and consume some of that data. */
@ -469,6 +510,7 @@ gzip_filter_close(struct archive_read_filter *self)
}
}
free(state->name);
free(state->out_block);
free(state);
return (ret);

View File

@ -1509,8 +1509,8 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
}
if (mszip == 1 && cab->stream.next_in[0] != 0x4b)
goto nomszip;
else if (cab->stream.next_in[0] != 0x43 ||
cab->stream.next_in[1] != 0x4b)
else if (mszip == 2 && (cab->stream.next_in[0] != 0x43 ||
cab->stream.next_in[1] != 0x4b))
goto nomszip;
cab->stream.next_in += mszip;
cab->stream.avail_in -= mszip;

View File

@ -45,6 +45,9 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_CTYPE_H
#include <ctype.h>
#endif
#include "archive.h"
#include "archive_entry.h"
@ -1011,7 +1014,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
{
ssize_t len;
uintmax_t counter;
char *p;
char *p, *s;
struct mtree_option *global;
struct mtree_entry *last_entry;
int r, is_form_d;
@ -1025,6 +1028,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
(void)detect_form(a, &is_form_d);
for (counter = 1; ; ++counter) {
r = ARCHIVE_OK;
len = readline(a, mtree, &p, 65536);
if (len == 0) {
mtree->this_entry = mtree->entries;
@ -1045,6 +1049,15 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
continue;
if (*p == '\r' || *p == '\n' || *p == '\0')
continue;
/* Non-printable characters are not allowed */
for (s = p;s < p + len - 1; s++) {
if (!isprint(*s)) {
r = ARCHIVE_FATAL;
break;
}
}
if (r != ARCHIVE_OK)
break;
if (*p != '/') {
r = process_add_entry(a, mtree, &global, p, len,
&last_entry, is_form_d);

View File

@ -1024,8 +1024,10 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
case COMPRESS_METHOD_GOOD:
case COMPRESS_METHOD_BEST:
ret = read_data_compressed(a, buff, size, offset);
if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN)
if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN) {
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
rar->start_new_table = 1;
}
break;
default:

View File

@ -120,7 +120,9 @@ archive_read_format_raw_read_header(struct archive_read *a,
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_perm(entry, 0644);
/* I'm deliberately leaving most fields unset here. */
return (ARCHIVE_OK);
/* Let the filter fill out any fields it might have. */
return __archive_read_header(a, entry);
}
static int

View File

@ -694,11 +694,13 @@ tar_read_header(struct archive_read *a, struct tar *tar,
struct archive_entry *entry, size_t *unconsumed)
{
ssize_t bytes;
int err;
int err, eof_vol_header;
const char *h;
const struct archive_entry_header_ustar *header;
const struct archive_entry_header_gnutar *gnuheader;
eof_vol_header = 0;
/* Loop until we find a workable header record. */
for (;;) {
tar_flush_unconsumed(a, unconsumed);
@ -788,6 +790,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
break;
case 'V': /* GNU volume header */
err = header_volume(a, tar, entry, h, unconsumed);
if (err == ARCHIVE_EOF)
eof_vol_header = 1;
break;
case 'X': /* Used by SUN tar; same as 'x'. */
a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
@ -862,9 +866,17 @@ tar_read_header(struct archive_read *a, struct tar *tar,
}
return (err);
}
if (err == ARCHIVE_EOF)
/* EOF when recursively reading a header is bad. */
archive_set_error(&a->archive, EINVAL, "Damaged tar archive");
if (err == ARCHIVE_EOF) {
if (!eof_vol_header) {
/* EOF when recursively reading a header is bad. */
archive_set_error(&a->archive, EINVAL,
"Damaged tar archive");
} else {
/* If we encounter just a GNU volume header treat
* this situation as an empty archive */
return (ARCHIVE_EOF);
}
}
return (ARCHIVE_FATAL);
}
@ -1944,6 +1956,15 @@ pax_attribute(struct archive_read *a, struct tar *tar,
pax_time(value, &s, &n);
archive_entry_set_birthtime(entry, s, n);
}
if (strcmp(key, "LIBARCHIVE.symlinktype") == 0) {
if (strcmp(value, "file") == 0) {
archive_entry_set_symlink_type(entry,
AE_SYMLINK_TYPE_FILE);
} else if (strcmp(value, "dir") == 0) {
archive_entry_set_symlink_type(entry,
AE_SYMLINK_TYPE_DIRECTORY);
}
}
if (memcmp(key, "LIBARCHIVE.xattr.", 17) == 0)
pax_attribute_xattr(entry, key, value);
break;

View File

@ -744,8 +744,9 @@ _warc_rdlen(const char *buf, size_t bsz)
/* there must be at least one digit */
if (!isdigit((unsigned char)*val))
return -1;
errno = 0;
len = strtol(val, &on, 10);
if (on != eol) {
if (errno != 0 || on != eol) {
/* line must end here */
return -1;
}

View File

@ -798,7 +798,8 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry)
xattr = file->xattr_list;
while (xattr != NULL) {
const void *d;
size_t outbytes, used;
size_t outbytes = 0;
size_t used = 0;
r = move_reading_point(a, xattr->offset);
if (r != ARCHIVE_OK)
@ -820,8 +821,18 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry)
r = checksum_final(a,
xattr->a_sum.val, xattr->a_sum.len,
xattr->e_sum.val, xattr->e_sum.len);
if (r != ARCHIVE_OK)
if (r != ARCHIVE_OK) {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"Xattr checksum error");
r = ARCHIVE_WARN;
break;
}
if (xattr->name.s == NULL) {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"Xattr name error");
r = ARCHIVE_WARN;
break;
}
archive_entry_xattr_add_entry(entry,
xattr->name.s, d, outbytes);
xattr = xattr->next;
@ -847,7 +858,7 @@ xar_read_data(struct archive_read *a,
const void **buff, size_t *size, int64_t *offset)
{
struct xar *xar;
size_t used;
size_t used = 0;
int r;
xar = (struct xar *)(a->format->data);

View File

@ -472,27 +472,49 @@ zip_time(const char *p)
* triplets. id and size are 2 bytes each.
*/
static int
process_extra(struct archive_read *a, const char *p, size_t extra_length, struct zip_entry* zip_entry)
process_extra(struct archive_read *a, struct archive_entry *entry,
const char *p, size_t extra_length, struct zip_entry* zip_entry)
{
unsigned offset = 0;
struct zip *zip = (struct zip *)(a->format->data);
if (extra_length == 0) {
return ARCHIVE_OK;
}
if (extra_length < 4) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Too-small extra data: Need at least 4 bytes, but only found %d bytes", (int)extra_length);
return ARCHIVE_FAILED;
size_t i = 0;
/* Some ZIP files may have trailing 0 bytes. Let's check they
* are all 0 and ignore them instead of returning an error.
*
* This is not techincally correct, but some ZIP files look
* like this and other tools support those files - so let's
* also support them.
*/
for (; i < extra_length; i++) {
if (p[i] != 0) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Too-small extra data: "
"Need at least 4 bytes, "
"but only found %d bytes",
(int)extra_length);
return ARCHIVE_FAILED;
}
}
return ARCHIVE_OK;
}
while (offset <= extra_length - 4) {
unsigned short headerid = archive_le16dec(p + offset);
unsigned short datasize = archive_le16dec(p + offset + 2);
offset += 4;
if (offset + datasize > extra_length) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Extra data overflow: Need %d bytes but only found %d bytes",
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT, "Extra data overflow: "
"Need %d bytes but only found %d bytes",
(int)datasize, (int)(extra_length - offset));
return ARCHIVE_FAILED;
}
@ -507,9 +529,12 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
if (zip_entry->uncompressed_size == 0xffffffff) {
uint64_t t = 0;
if (datasize < 8
|| (t = archive_le64dec(p + offset)) > INT64_MAX) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed 64-bit uncompressed size");
|| (t = archive_le64dec(p + offset)) >
INT64_MAX) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed 64-bit "
"uncompressed size");
return ARCHIVE_FAILED;
}
zip_entry->uncompressed_size = t;
@ -519,9 +544,12 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
if (zip_entry->compressed_size == 0xffffffff) {
uint64_t t = 0;
if (datasize < 8
|| (t = archive_le64dec(p + offset)) > INT64_MAX) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed 64-bit compressed size");
|| (t = archive_le64dec(p + offset)) >
INT64_MAX) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed 64-bit "
"compressed size");
return ARCHIVE_FAILED;
}
zip_entry->compressed_size = t;
@ -531,9 +559,12 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
if (zip_entry->local_header_offset == 0xffffffff) {
uint64_t t = 0;
if (datasize < 8
|| (t = archive_le64dec(p + offset)) > INT64_MAX) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed 64-bit local header offset");
|| (t = archive_le64dec(p + offset)) >
INT64_MAX) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed 64-bit "
"local header offset");
return ARCHIVE_FAILED;
}
zip_entry->local_header_offset = t;
@ -566,7 +597,8 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
/* Extended time field "UT". */
int flags;
if (datasize == 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Incomplete extended time field");
return ARCHIVE_FAILED;
}
@ -648,7 +680,8 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
* if bitmap & 1, 2 byte "version made by"
* if bitmap & 2, 2 byte "internal file attributes"
* if bitmap & 4, 4 byte "external file attributes"
* if bitmap & 8, 2 byte comment length + n byte comment
* if bitmap & 8, 2 byte comment length + n byte
* comment
*/
int bitmap, bitmap_last;
@ -699,13 +732,18 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
= external_attributes >> 16;
} else if (zip_entry->system == 0) {
// Interpret MSDOS directory bit
if (0x10 == (external_attributes & 0x10)) {
zip_entry->mode = AE_IFDIR | 0775;
if (0x10 == (external_attributes &
0x10)) {
zip_entry->mode =
AE_IFDIR | 0775;
} else {
zip_entry->mode = AE_IFREG | 0664;
zip_entry->mode =
AE_IFREG | 0664;
}
if (0x01 == (external_attributes & 0x01)) {
// Read-only bit; strip write permissions
if (0x01 == (external_attributes &
0x01)) {
/* Read-only bit;
* strip write permissions */
zip_entry->mode &= 0555;
}
} else {
@ -732,6 +770,59 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
}
break;
}
case 0x7075:
{
/* Info-ZIP Unicode Path Extra Field. */
if (datasize < 5 || entry == NULL)
break;
offset += 5;
datasize -= 5;
/* The path name in this field is always encoded
* in UTF-8. */
if (zip->sconv_utf8 == NULL) {
zip->sconv_utf8 =
archive_string_conversion_from_charset(
&a->archive, "UTF-8", 1);
/* If the converter from UTF-8 is not
* available, then the path name from the main
* field will more likely be correct. */
if (zip->sconv_utf8 == NULL)
break;
}
/* Make sure the CRC32 of the filename matches. */
if (!zip->ignore_crc32) {
const char *cp = archive_entry_pathname(entry);
if (cp) {
unsigned long file_crc =
zip->crc32func(0, cp, strlen(cp));
unsigned long utf_crc =
archive_le32dec(p + offset - 4);
if (file_crc != utf_crc) {
#ifdef DEBUG
fprintf(stderr,
"CRC filename mismatch; "
"CDE is %lx, but UTF8 "
"is outdated with %lx\n",
file_crc, utf_crc);
#endif
break;
}
}
}
if (archive_entry_copy_pathname_l(entry,
p + offset, datasize, zip->sconv_utf8) != 0) {
/* Ignore the error, and fallback to the path
* name from the main field. */
#ifdef DEBUG
fprintf(stderr, "Failed to read the ZIP "
"0x7075 extra field path.\n");
#endif
}
break;
}
case 0x7855:
/* Info-ZIP Unix Extra Field (type 2) "Ux". */
#ifdef DEBUG
@ -766,7 +857,8 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
}
if (datasize >= (2 + uidsize + 3)) {
/* get a gid size. */
gidsize = 0xff & (int)p[offset+2+uidsize];
gidsize = 0xff &
(int)p[offset+2+uidsize];
if (gidsize == 2)
zip_entry->gid =
archive_le16dec(
@ -783,7 +875,8 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
case 0x9901:
/* WinZip AES extra data field. */
if (datasize < 6) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Incomplete AES field");
return ARCHIVE_FAILED;
}
@ -803,12 +896,6 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
}
offset += datasize;
}
if (offset != extra_length) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed extra data: Consumed %d bytes of %d bytes",
(int)offset, (int)extra_length);
return ARCHIVE_FAILED;
}
return ARCHIVE_OK;
}
@ -928,7 +1015,8 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL);
}
if (ARCHIVE_OK != process_extra(a, h, extra_length, zip_entry)) {
if (ARCHIVE_OK != process_extra(a, entry, h, extra_length,
zip_entry)) {
return ARCHIVE_FATAL;
}
__archive_read_consume(a, extra_length);
@ -945,8 +1033,8 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
zip_entry->mode |= 0664;
}
/* Windows archivers sometimes use backslash as the directory separator.
Normalize to slash. */
/* Windows archivers sometimes use backslash as the directory
* separator. Normalize to slash. */
if (zip_entry->system == 0 &&
(wp = archive_entry_pathname_w(entry)) != NULL) {
if (wcschr(wp, L'/') == NULL && wcschr(wp, L'\\') != NULL) {
@ -1255,7 +1343,8 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
zip->entry->crc32 = archive_le32dec(p + 4);
compressed = archive_le64dec(p + 8);
uncompressed = archive_le64dec(p + 16);
if (compressed > INT64_MAX || uncompressed > INT64_MAX) {
if (compressed > INT64_MAX || uncompressed >
INT64_MAX) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Overflow of 64-bit file sizes");
@ -1372,7 +1461,8 @@ consume_optional_marker(struct archive_read *a, struct zip *zip)
zip->entry->crc32 = archive_le32dec(p);
compressed = archive_le64dec(p + 4);
uncompressed = archive_le64dec(p + 12);
if (compressed > INT64_MAX || uncompressed > INT64_MAX) {
if (compressed > INT64_MAX ||
uncompressed > INT64_MAX) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Overflow of 64-bit file sizes");
@ -1444,12 +1534,16 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip)
} alone_header;
#pragma pack(pop)
/* To unpack ZIPX's "LZMA" (id 14) stream we can use standard liblzma that
* is a part of XZ Utils. The stream format stored inside ZIPX file is a
* modified "lzma alone" file format, that was used by the `lzma` utility
* which was later deprecated in favour of `xz` utility. Since those
* formats are nearly the same, we can use a standard "lzma alone" decoder
* from XZ Utils. */
if(zip->zipx_lzma_valid) {
lzma_end(&zip->zipx_lzma_stream);
zip->zipx_lzma_valid = 0;
}
/* To unpack ZIPX's "LZMA" (id 14) stream we can use standard liblzma
* that is a part of XZ Utils. The stream format stored inside ZIPX
* file is a modified "lzma alone" file format, that was used by the
* `lzma` utility which was later deprecated in favour of `xz` utility. * Since those formats are nearly the same, we can use a standard
* "lzma alone" decoder from XZ Utils. */
memset(&zip->zipx_lzma_stream, 0, sizeof(zip->zipx_lzma_stream));
r = lzma_alone_decoder(&zip->zipx_lzma_stream, UINT64_MAX);
@ -1477,8 +1571,8 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip)
* lzma_params is a 5-byte blob that has to be decoded to extract
* parameters of this LZMA stream. The uncompressed_size field is an
* uint64_t value that contains information about the size of the
* uncompressed file, or UINT64_MAX if this value is unknown. The <data...>
* part is the actual lzma-compressed data stream.
* uncompressed file, or UINT64_MAX if this value is unknown.
* The <data...> part is the actual lzma-compressed data stream.
*
* Now here's the structure of the stream inside the ZIPX file:
*
@ -1488,17 +1582,17 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip)
* 2byte 2byte 5 bytes n bytes
* <magic1><magic2><lzma_params><data...>
*
* This means that the ZIPX file contains an additional magic1 and magic2
* headers, the lzma_params field contains the same parameter set as in the
* "lzma alone" format, and the <data...> field is the same as in the "lzma
* alone" format as well. Note that also the zipx format is missing the
* uncompressed_size field.
* This means that the ZIPX file contains an additional magic1 and
* magic2 headers, the lzma_params field contains the same parameter
* set as in the "lzma alone" format, and the <data...> field is the
* same as in the "lzma alone" format as well. Note that also the zipx
* format is missing the uncompressed_size field.
*
* So, in order to use the "lzma alone" decoder for the zipx lzma stream,
* we simply need to shuffle around some fields, prepare a new lzma alone
* header, feed it into lzma alone decoder so it will initialize itself
* properly, and then we can start feeding normal zipx lzma stream into the
* decoder.
* So, in order to use the "lzma alone" decoder for the zipx lzma
* stream, we simply need to shuffle around some fields, prepare a new
* lzma alone header, feed it into lzma alone decoder so it will
* initialize itself properly, and then we can start feeding normal
* zipx lzma stream into the decoder.
*/
/* Read magic1,magic2,lzma_params from the ZIPX stream. */
@ -1514,8 +1608,8 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip)
return (ARCHIVE_FATAL);
}
/* Prepare an lzma alone header: copy the lzma_params blob into a proper
* place into the lzma alone header. */
/* Prepare an lzma alone header: copy the lzma_params blob into
* a proper place into the lzma alone header. */
memcpy(&alone_header.bytes[0], p + 4, 5);
/* Initialize the 'uncompressed size' field to unknown; we'll manually
@ -1541,8 +1635,9 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip)
zip->zipx_lzma_stream.avail_out = zip->uncompressed_buffer_size;
zip->zipx_lzma_stream.total_out = 0;
/* Feed only the header into the lzma alone decoder. This will effectively
* initialize the decoder, and will not produce any output bytes yet. */
/* Feed only the header into the lzma alone decoder. This will
* effectively initialize the decoder, and will not produce any
* output bytes yet. */
r = lzma_code(&zip->zipx_lzma_stream, LZMA_RUN);
if (r != LZMA_OK) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
@ -1617,7 +1712,8 @@ zip_read_data_zipx_xz(struct archive_read *a, const void **buff,
if((int64_t) zip->zipx_lzma_stream.total_in !=
zip->entry_bytes_remaining)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"xz premature end of stream");
return (ARCHIVE_FATAL);
}
@ -1662,12 +1758,13 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff,
return (ret);
}
/* Fetch more compressed data. The same note as in deflate handler applies
* here as well:
/* Fetch more compressed data. The same note as in deflate handler
* applies here as well:
*
* Note: '1' here is a performance optimization. Recall that the
* decompression layer returns a count of available bytes; asking for more
* than that forces the decompressor to combine reads by copying data.
* decompression layer returns a count of available bytes; asking for
* more than that forces the decompressor to combine reads by copying
* data.
*/
compressed_buf = __archive_read_ahead(a, 1, &bytes_avail);
if (bytes_avail < 0) {
@ -1684,8 +1781,9 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff,
zip->zipx_lzma_stream.total_in = 0;
zip->zipx_lzma_stream.next_out = zip->uncompressed_buffer;
zip->zipx_lzma_stream.avail_out =
/* These lzma_alone streams lack end of stream marker, so let's make
* sure the unpacker won't try to unpack more than it's supposed to. */
/* These lzma_alone streams lack end of stream marker, so let's
* make sure the unpacker won't try to unpack more than it's
* supposed to. */
zipmin((int64_t) zip->uncompressed_buffer_size,
zip->entry->uncompressed_size -
zip->entry_uncompressed_bytes_read);
@ -1810,7 +1908,8 @@ zipx_ppmd8_init(struct archive_read *a, struct zip *zip)
return (ARCHIVE_FATAL);
}
__archive_ppmd8_functions.Ppmd8_Init(&zip->ppmd8, order, restore_method);
__archive_ppmd8_functions.Ppmd8_Init(&zip->ppmd8, order,
restore_method);
/* Allocate the buffer that will hold uncompressed data. */
free(zip->uncompressed_buffer);
@ -1856,8 +1955,8 @@ zip_read_data_zipx_ppmd(struct archive_read *a, const void **buff,
return ret;
}
/* Fetch for more data. We're reading 1 byte here, but libarchive should
* prefetch more bytes. */
/* Fetch for more data. We're reading 1 byte here, but libarchive
* should prefetch more bytes. */
(void) __archive_read_ahead(a, 1, &bytes_avail);
if(bytes_avail < 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
@ -1871,7 +1970,8 @@ zip_read_data_zipx_ppmd(struct archive_read *a, const void **buff,
/* Decompression loop. */
do {
int sym = __archive_ppmd8_functions.Ppmd8_DecodeSymbol(&zip->ppmd8);
int sym = __archive_ppmd8_functions.Ppmd8_DecodeSymbol(
&zip->ppmd8);
if(sym < 0) {
zip->end_of_entry = 1;
break;
@ -1880,8 +1980,9 @@ zip_read_data_zipx_ppmd(struct archive_read *a, const void **buff,
/* This field is set by ppmd_read() when there was no more data
* to be read. */
if(zip->ppmd8_stream_failed) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated PPMd8 file body");
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated PPMd8 file body");
return (ARCHIVE_FATAL);
}
@ -1985,9 +2086,10 @@ zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff,
in_bytes = zipmin(zip->entry_bytes_remaining, bytes_avail);
if(in_bytes < 1) {
/* libbz2 doesn't complain when caller feeds avail_in == 0. It will
* actually return success in this case, which is undesirable. This is
* why we need to make this check manually. */
/* libbz2 doesn't complain when caller feeds avail_in == 0.
* It will actually return success in this case, which is
* undesirable. This is why we need to make this check
* manually. */
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated bzip2 file body");
@ -2014,16 +2116,18 @@ zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff,
case BZ_OK:
break;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Failed to clean up bzip2 decompressor");
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Failed to clean up bzip2 "
"decompressor");
return ARCHIVE_FATAL;
}
zip->end_of_entry = 1;
break;
case BZ_OK:
/* The decompressor has successfully decoded this chunk of
* data, but more data is still in queue. */
/* The decompressor has successfully decoded this
* chunk of data, but more data is still in queue. */
break;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@ -2131,8 +2235,10 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
if (zip->tctx_valid || zip->cctx_valid) {
if (zip->decrypted_bytes_remaining < (size_t)bytes_avail) {
size_t buff_remaining =
(zip->decrypted_buffer + zip->decrypted_buffer_size)
- (zip->decrypted_ptr + zip->decrypted_bytes_remaining);
(zip->decrypted_buffer +
zip->decrypted_buffer_size)
- (zip->decrypted_ptr +
zip->decrypted_bytes_remaining);
if (buff_remaining > (size_t)bytes_avail)
buff_remaining = (size_t)bytes_avail;
@ -2143,12 +2249,12 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
+ buff_remaining)
> zip->entry_bytes_remaining) {
if (zip->entry_bytes_remaining <
(int64_t)zip->decrypted_bytes_remaining)
(int64_t)zip->decrypted_bytes_remaining)
buff_remaining = 0;
else
buff_remaining =
(size_t)zip->entry_bytes_remaining
- zip->decrypted_bytes_remaining;
- zip->decrypted_bytes_remaining;
}
}
if (buff_remaining > 0) {
@ -2167,7 +2273,8 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
+ zip->decrypted_bytes_remaining,
&dsize);
}
zip->decrypted_bytes_remaining += buff_remaining;
zip->decrypted_bytes_remaining +=
buff_remaining;
}
}
bytes_avail = zip->decrypted_bytes_remaining;
@ -2751,7 +2858,7 @@ archive_read_format_zip_cleanup(struct archive_read *a)
inflateEnd(&zip->stream);
#endif
#if HAVA_LZMA_H && HAVE_LIBLZMA
#if HAVE_LZMA_H && HAVE_LIBLZMA
if (zip->zipx_lzma_valid) {
lzma_end(&zip->zipx_lzma_stream);
}
@ -3391,7 +3498,8 @@ expose_parent_dirs(struct zip *zip, const char *name, size_t name_length)
}
static int
slurp_central_directory(struct archive_read *a, struct zip *zip)
slurp_central_directory(struct archive_read *a, struct archive_entry* entry,
struct zip *zip)
{
ssize_t i;
unsigned found;
@ -3501,8 +3609,10 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
filename_length = archive_le16dec(p + 28);
extra_length = archive_le16dec(p + 30);
comment_length = archive_le16dec(p + 32);
/* disk_start = archive_le16dec(p + 34); */ /* Better be zero. */
/* internal_attributes = archive_le16dec(p + 36); */ /* text bit */
/* disk_start = archive_le16dec(p + 34);
* Better be zero.
* internal_attributes = archive_le16dec(p + 36);
* text bit */
external_attributes = archive_le32dec(p + 38);
zip_entry->local_header_offset =
archive_le32dec(p + 42) + correction;
@ -3538,7 +3648,8 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
"Truncated ZIP file header");
return ARCHIVE_FATAL;
}
if (ARCHIVE_OK != process_extra(a, p + filename_length, extra_length, zip_entry)) {
if (ARCHIVE_OK != process_extra(a, entry, p + filename_length,
extra_length, zip_entry)) {
return ARCHIVE_FATAL;
}
@ -3560,7 +3671,8 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
* a directory. We should treat it as a non
* resource fork file to expose it. */
if (name[filename_length-1] != '/' &&
(r - name < 3 || r[0] != '.' || r[1] != '_')) {
(r - name < 3 || r[0] != '.' ||
r[1] != '_')) {
__archive_rb_tree_insert_node(
&zip->tree, &zip_entry->node);
/* Expose its parent directories. */
@ -3637,8 +3749,10 @@ zip_read_mac_metadata(struct archive_read *a, struct archive_entry *entry,
switch(rsrc->compression) {
case 0: /* No compression. */
if (rsrc->uncompressed_size != rsrc->compressed_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed OS X metadata entry: inconsistent size");
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed OS X metadata entry: "
"inconsistent size");
return (ARCHIVE_FATAL);
}
#ifdef HAVE_ZLIB_H
@ -3797,7 +3911,7 @@ archive_read_format_zip_seekable_read_header(struct archive_read *a,
a->archive.archive_format_name = "ZIP";
if (zip->zip_entries == NULL) {
r = slurp_central_directory(a, zip);
r = slurp_central_directory(a, entry, zip);
if (r != ARCHIVE_OK)
return r;
/* Get first entry whose local header offset is lower than
@ -3827,8 +3941,8 @@ archive_read_format_zip_seekable_read_header(struct archive_read *a,
__archive_read_reset_passphrase(a);
/* File entries are sorted by the header offset, we should mostly
* use __archive_read_consume to advance a read point to avoid redundant
* data reading. */
* use __archive_read_consume to advance a read point to avoid
* redundant data reading. */
offset = archive_filter_bytes(&a->archive, 0);
if (offset < zip->entry->local_header_offset)
__archive_read_consume(a,

View File

@ -449,7 +449,7 @@ __archive_mktemp(const char *tmpdir)
temp_name.s[temp_name.length-1] = '\0';
temp_name.length --;
}
if (stat(temp_name.s, &st) < 0)
if (la_stat(temp_name.s, &st) < 0)
goto exit_tmpfile;
if (!S_ISDIR(st.st_mode)) {
errno = ENOTDIR;

View File

@ -390,10 +390,13 @@ archive_compressor_xz_options(struct archive_write_filter *f,
data->compression_level = 6;
return (ARCHIVE_OK);
} else if (strcmp(key, "threads") == 0) {
char *endptr;
if (value == NULL)
return (ARCHIVE_WARN);
data->threads = (int)strtoul(value, NULL, 10);
if (data->threads == 0 && errno != 0) {
errno = 0;
data->threads = (int)strtoul(value, &endptr, 10);
if (errno != 0 || *endptr != '\0') {
data->threads = 1;
return (ARCHIVE_WARN);
}

View File

@ -2032,7 +2032,7 @@ restore_entry(struct archive_write_disk *a)
* follow the symlink if we're creating a dir.
*/
if (S_ISDIR(a->mode))
r = stat(a->name, &a->st);
r = la_stat(a->name, &a->st);
/*
* If it's not a dir (or it's a broken symlink),
* then don't follow it.
@ -2198,7 +2198,7 @@ create_filesystem_object(struct archive_write_disk *a)
#ifdef HAVE_LSTAT
r = lstat(a->name, &st);
#else
r = stat(a->name, &st);
r = la_stat(a->name, &st);
#endif
if (r != 0)
r = errno;
@ -2712,7 +2712,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
* This is needed to extract hardlinks over
* symlinks.
*/
r = stat(head, &st);
r = la_stat(head, &st);
if (r != 0) {
tail[0] = c;
if (errno == ENOENT) {
@ -3052,7 +3052,7 @@ create_dir(struct archive_write_disk *a, char *path)
* here loses the ability to extract through symlinks. Also note
* that this should not use the a->st cache.
*/
if (stat(path, &st) == 0) {
if (la_stat(path, &st) == 0) {
if (S_ISDIR(st.st_mode))
return (ARCHIVE_OK);
if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
@ -3110,7 +3110,7 @@ create_dir(struct archive_write_disk *a, char *path)
* don't add it to the fixup list here, as it's already been
* added.
*/
if (stat(path, &st) == 0 && S_ISDIR(st.st_mode))
if (la_stat(path, &st) == 0 && S_ISDIR(st.st_mode))
return (ARCHIVE_OK);
archive_set_error(&a->archive, errno, "Failed to create dir '%s'",

View File

@ -1114,6 +1114,10 @@ archive_write_pax_header(struct archive_write *a,
if (!need_extension && acl_types != 0)
need_extension = 1;
/* If the symlink type is defined, we need an extension */
if (!need_extension && archive_entry_symlink_type(entry_main) > 0)
need_extension = 1;
/*
* Libarchive used to include these in extended headers for
* restricted pax format, but that confused people who
@ -1247,6 +1251,17 @@ archive_write_pax_header(struct archive_write *a,
archive_string_free(&entry_name);
return (ARCHIVE_FATAL);
}
/* Store extended symlink information */
if (archive_entry_symlink_type(entry_main) ==
AE_SYMLINK_TYPE_FILE) {
add_pax_attr(&(pax->pax_header),
"LIBARCHIVE.symlinktype", "file");
} else if (archive_entry_symlink_type(entry_main) ==
AE_SYMLINK_TYPE_DIRECTORY) {
add_pax_attr(&(pax->pax_header),
"LIBARCHIVE.symlinktype", "dir");
}
}
/* Only regular files have data. */

View File

@ -496,10 +496,13 @@ xar_options(struct archive_write *a, const char *key, const char *value)
return (ARCHIVE_OK);
}
if (strcmp(key, "threads") == 0) {
char *endptr;
if (value == NULL)
return (ARCHIVE_FAILED);
xar->opt_threads = (int)strtoul(value, NULL, 10);
if (xar->opt_threads == 0 && errno != 0) {
errno = 0;
xar->opt_threads = (int)strtoul(value, &endptr, 10);
if (errno != 0 || *endptr != '\0') {
xar->opt_threads = 1;
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC,

View File

@ -27,6 +27,10 @@ __FBSDID("$FreeBSD$");
#include <locale.h>
#ifdef HAVE_LINUX_FS_H
#include <linux/fs.h> /* for Linux file flags */
#endif
#ifndef HAVE_WCSCPY
static wchar_t * wcscpy(wchar_t *s1, const wchar_t *s2)
{
@ -337,16 +341,37 @@ DEFINE_TEST(test_entry)
/* TODO: Make this system-independent. */
assertEqualString(archive_entry_fflags_text(e),
"uappnd,nouchg,nodump,noopaque,uunlnk,nosystem");
#endif
#if defined(__FreeBSD__) || defined(__APPLE__)
/* Test archive_entry_copy_fflags_text_w() */
archive_entry_copy_fflags_text_w(e, L" ,nouappnd, nouchg, dump,uunlnk");
archive_entry_copy_fflags_text_w(e, L" ,nouappnd, nouchg, dump,hidden");
archive_entry_fflags(e, &set, &clear);
assertEqualInt(16, set);
assertEqualInt(7, clear);
assertEqualInt(UF_HIDDEN, set);
assertEqualInt(UF_NODUMP | UF_IMMUTABLE | UF_APPEND, clear);
/* Test archive_entry_copy_fflags_text() */
archive_entry_copy_fflags_text(e, " ,nouappnd, nouchg, dump,uunlnk");
archive_entry_copy_fflags_text(e, " ,nouappnd, nouchg, dump,hidden");
archive_entry_fflags(e, &set, &clear);
assertEqualInt(16, set);
assertEqualInt(7, clear);
assertEqualInt(UF_HIDDEN, set);
assertEqualInt(UF_NODUMP | UF_IMMUTABLE | UF_APPEND, clear);
#elif defined(_WIN32) && !defined(CYGWIN)
archive_entry_copy_fflags_text_w(e, L"rdonly,hidden,nosystem");
archive_entry_fflags(e, &set, &clear);
assertEqualInt(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN, set);
assertEqualInt(FILE_ATTRIBUTE_SYSTEM, clear);
archive_entry_copy_fflags_text(e, "rdonly,hidden,nosystem");
archive_entry_fflags(e, &set, &clear);
assertEqualInt(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN, set);
assertEqualInt(FILE_ATTRIBUTE_SYSTEM, clear);
#elif defined FS_IOC_GETFLAGS /* Linux */
archive_entry_copy_fflags_text_w(e, L"sappnd,schg,dump,noundel");
archive_entry_fflags(e, &set, &clear);
assertEqualInt(FS_APPEND_FL | FS_IMMUTABLE_FL, set);
assertEqualInt(FS_NODUMP_FL | FS_UNRM_FL, clear);
archive_entry_copy_fflags_text(e, "sappnd,schg,dump,noundel");
archive_entry_fflags(e, &set, &clear);
assertEqualInt(FS_APPEND_FL | FS_IMMUTABLE_FL, set);
assertEqualInt(FS_NODUMP_FL | FS_UNRM_FL, clear);
#endif
/* See test_acl_basic.c for tests of ACL set/get consistency. */

View File

@ -58,6 +58,14 @@ test_fuzz(const struct files *filesets)
size_t blk_size;
int64_t blk_offset;
int n;
const char *skip_fuzz_tests;
skip_fuzz_tests = getenv("SKIP_TEST_FUZZ");
if (skip_fuzz_tests != NULL) {
skipping("Skipping fuzz tests due to SKIP_TEST_FUZZ "
"environment variable");
return;
}
for (n = 0; filesets[n].names != NULL; ++n) {
const size_t buffsize = 30000000;

View File

@ -40,7 +40,30 @@ atimeIsUpdated(void)
{
const char *fn = "fs_noatime";
struct stat st;
#if defined(_WIN32) && !defined(CYGWIN)
char *buff = NULL;
char *ptr;
int r;
r = systemf("fsutil behavior query disableLastAccess > query_atime");
if (r == 0) {
buff = slurpfile(NULL, "query_atime");
if (buff != NULL) {
ptr = buff;
while(*ptr != '\0' && !isdigit(*ptr)) {
ptr++;
}
if (*ptr == '0') {
free(buff);
return(1);
} else if (*ptr == '1' || *ptr == '2') {
free(buff);
return(0);
}
free(buff);
}
}
#endif
if (!assertMakeFile(fn, 0666, "a"))
return (0);
if (!assertUtimes(fn, 1, 0, 1, 0))
@ -570,13 +593,13 @@ test_symlink_hybrid(void)
assertMakeDir("h", 0755);
assertChdir("h");
assertMakeDir("d1", 0755);
assertMakeSymlink("ld1", "d1");
assertMakeSymlink("ld1", "d1", 1);
assertMakeFile("d1/file1", 0644, "d1/file1");
assertMakeFile("d1/file2", 0644, "d1/file2");
assertMakeSymlink("d1/link1", "file1");
assertMakeSymlink("d1/linkX", "fileX");
assertMakeSymlink("link2", "d1/file2");
assertMakeSymlink("linkY", "d1/fileY");
assertMakeSymlink("d1/link1", "file1", 0);
assertMakeSymlink("d1/linkX", "fileX", 0);
assertMakeSymlink("link2", "d1/file2", 0);
assertMakeSymlink("linkY", "d1/fileY", 0);
assertChdir("..");
assert((ae = archive_entry_new()) != NULL);
@ -727,13 +750,13 @@ test_symlink_logical(void)
assertMakeDir("l", 0755);
assertChdir("l");
assertMakeDir("d1", 0755);
assertMakeSymlink("ld1", "d1");
assertMakeSymlink("ld1", "d1", 1);
assertMakeFile("d1/file1", 0644, "d1/file1");
assertMakeFile("d1/file2", 0644, "d1/file2");
assertMakeSymlink("d1/link1", "file1");
assertMakeSymlink("d1/linkX", "fileX");
assertMakeSymlink("link2", "d1/file2");
assertMakeSymlink("linkY", "d1/fileY");
assertMakeSymlink("d1/link1", "file1", 0);
assertMakeSymlink("d1/linkX", "fileX", 0);
assertMakeSymlink("link2", "d1/file2", 0);
assertMakeSymlink("linkY", "d1/fileY", 0);
assertChdir("..");
/* Note: this test uses archive_read_next_header()
@ -961,8 +984,8 @@ test_symlink_logical_loop(void)
assertMakeDir("d1/d2/d3", 0755);
assertMakeDir("d2", 0755);
assertMakeFile("d2/file1", 0644, "d2/file1");
assertMakeSymlink("d1/d2/ld1", "../../d1");
assertMakeSymlink("d1/d2/ld2", "../../d2");
assertMakeSymlink("d1/d2/ld1", "../../d1", 1);
assertMakeSymlink("d1/d2/ld2", "../../d2", 1);
assertChdir("..");
assert((ae = archive_entry_new()) != NULL);
@ -1567,6 +1590,254 @@ test_nodump(void)
archive_entry_free(ae);
}
static void
test_parent(void)
{
struct archive *a;
struct archive_entry *ae;
const void *p;
size_t size;
int64_t offset;
int file_count;
int match_count;
int r;
assertMakeDir("lock", 0311);
assertMakeDir("lock/dir1", 0755);
assertMakeFile("lock/dir1/f1", 0644, "0123456789");
assertMakeDir("lock/lock2", 0311);
assertMakeDir("lock/lock2/dir1", 0755);
assertMakeFile("lock/lock2/dir1/f1", 0644, "0123456789");
assert((ae = archive_entry_new()) != NULL);
assert((a = archive_read_disk_new()) != NULL);
/*
* Test1: Traverse lock/dir1 as .
*/
assertChdir("lock/dir1");
failure("Directory traversals should work as well");
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "."));
file_count = 2;
match_count = 0;
while (file_count--) {
archive_entry_clear(ae);
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
if (strcmp(archive_entry_pathname(ae), ".") == 0) {
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
++match_count;
} else if (strcmp(archive_entry_pathname(ae), "./f1") == 0) {
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
assertEqualInt(archive_entry_size(ae), 10);
assertEqualIntA(a, ARCHIVE_OK,
archive_read_data_block(a, &p, &size, &offset));
assertEqualInt((int)size, 10);
assertEqualInt((int)offset, 0);
assertEqualMem(p, "0123456789", 10);
assertEqualInt(ARCHIVE_EOF,
archive_read_data_block(a, &p, &size, &offset));
assertEqualInt((int)size, 0);
assertEqualInt((int)offset, 10);
++match_count;
}
if (archive_read_disk_can_descend(a)) {
/* Descend into the current object */
assertEqualIntA(a, ARCHIVE_OK,
archive_read_disk_descend(a));
}
}
failure("Did not match expected filenames");
assertEqualInt(match_count, 2);
/*
* There is no entry. This will however fail if the directory traverse
* tries to ascend past the initial directory, since it lacks permission
* to do so.
*/
failure("There should be no entry and no error");
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
/* Close the disk object. */
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
assertChdir("../..");
/*
* Test2: Traverse lock/dir1 directly
*/
failure("Directory traversals should work as well");
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock/dir1"));
file_count = 2;
match_count = 0;
while (file_count--) {
archive_entry_clear(ae);
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
if (strcmp(archive_entry_pathname(ae), "lock/dir1") == 0) {
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
++match_count;
} else if (strcmp(archive_entry_pathname(ae), "lock/dir1/f1") == 0) {
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
assertEqualInt(archive_entry_size(ae), 10);
assertEqualIntA(a, ARCHIVE_OK,
archive_read_data_block(a, &p, &size, &offset));
assertEqualInt((int)size, 10);
assertEqualInt((int)offset, 0);
assertEqualMem(p, "0123456789", 10);
assertEqualInt(ARCHIVE_EOF,
archive_read_data_block(a, &p, &size, &offset));
assertEqualInt((int)size, 0);
assertEqualInt((int)offset, 10);
++match_count;
}
if (archive_read_disk_can_descend(a)) {
/* Descend into the current object */
assertEqualIntA(a, ARCHIVE_OK,
archive_read_disk_descend(a));
}
}
failure("Did not match expected filenames");
assertEqualInt(match_count, 2);
/*
* There is no entry. This will however fail if the directory traverse
* tries to ascend past the initial directory, since it lacks permission
* to do so.
*/
failure("There should be no entry and no error");
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
/* Close the disk object. */
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
/*
* Test3: Traverse lock/dir1/.
*/
failure("Directory traversals should work as well");
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock/dir1/."));
file_count = 2;
match_count = 0;
while (file_count--) {
archive_entry_clear(ae);
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
if (strcmp(archive_entry_pathname(ae), "lock/dir1/.") == 0) {
assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
++match_count;
} else if (strcmp(archive_entry_pathname(ae), "lock/dir1/./f1") == 0) {
assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
assertEqualInt(archive_entry_size(ae), 10);
assertEqualIntA(a, ARCHIVE_OK,
archive_read_data_block(a, &p, &size, &offset));
assertEqualInt((int)size, 10);
assertEqualInt((int)offset, 0);
assertEqualMem(p, "0123456789", 10);
assertEqualInt(ARCHIVE_EOF,
archive_read_data_block(a, &p, &size, &offset));
assertEqualInt((int)size, 0);
assertEqualInt((int)offset, 10);
++match_count;
}
if (archive_read_disk_can_descend(a)) {
/* Descend into the current object */
assertEqualIntA(a, ARCHIVE_OK,
archive_read_disk_descend(a));
}
}
failure("Did not match expected filenames");
assertEqualInt(match_count, 2);
/*
* There is no entry. This will however fail if the directory traverse
* tries to ascend past the initial directory, since it lacks permission
* to do so.
*/
failure("There should be no entry and no error");
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
/* Close the disk object. */
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
/*
* Test4: Traverse lock/lock2/dir1 from inside lock.
*
* This test is expected to fail on platforms with no O_EXEC or
* equivalent (e.g. O_PATH on Linux or O_SEARCH on SunOS), because
* the current traversal code can't handle the case where it can't
* obtain an open fd for the initial current directory. We need to
* check that condition here, because if O_EXEC _does_ exist, we don't
* want to overlook any failure.
*/
assertChdir("lock");
failure("Directory traversals should work as well");
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock2/dir1"));
archive_entry_clear(ae);
r = archive_read_next_header2(a, ae);
if (r == ARCHIVE_FAILED) {
#if defined(O_PATH) || defined(O_SEARCH) || defined(O_EXEC)
assertEqualIntA(a, ARCHIVE_OK, r);
#endif
/* Close the disk object. */
archive_read_close(a);
} else {
file_count = 2;
match_count = 0;
while (file_count--) {
if (file_count == 0)
assertEqualIntA(a, ARCHIVE_OK,
archive_read_next_header2(a, ae));
if (strcmp(archive_entry_pathname(ae),
"lock2/dir1") == 0) {
assertEqualInt(archive_entry_filetype(ae),
AE_IFDIR);
++match_count;
} else if (strcmp(archive_entry_pathname(ae),
"lock2/dir1/f1") == 0) {
assertEqualInt(archive_entry_filetype(ae),
AE_IFREG);
assertEqualInt(archive_entry_size(ae), 10);
assertEqualIntA(a, ARCHIVE_OK,
archive_read_data_block(a, &p, &size,
&offset));
assertEqualInt((int)size, 10);
assertEqualInt((int)offset, 0);
assertEqualMem(p, "0123456789", 10);
assertEqualInt(ARCHIVE_EOF,
archive_read_data_block(a, &p, &size,
&offset));
assertEqualInt((int)size, 0);
assertEqualInt((int)offset, 10);
++match_count;
}
if (archive_read_disk_can_descend(a)) {
/* Descend into the current object */
assertEqualIntA(a, ARCHIVE_OK,
archive_read_disk_descend(a));
}
}
failure("Did not match expected filenames");
assertEqualInt(match_count, 2);
/*
* There is no entry. This will however fail if the directory
* traverse tries to ascend past the initial directory, since
* it lacks permission to do so.
*/
failure("There should be no entry and no error");
assertEqualIntA(a, ARCHIVE_EOF,
archive_read_next_header2(a, ae));
/* Close the disk object. */
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
}
assertChdir("..");
/* Destroy the disk object. */
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
archive_entry_free(ae);
}
DEFINE_TEST(test_read_disk_directory_traversals)
{
/* Basic test. */
@ -1583,4 +1854,6 @@ DEFINE_TEST(test_read_disk_directory_traversals)
test_callbacks();
/* Test nodump. */
test_nodump();
/* Test parent overshoot. */
test_parent();
}

View File

@ -161,7 +161,7 @@ DEFINE_TEST(test_read_extract)
assertIsDir("dir4/b", 0755);
assertIsDir("dir4/c", 0711);
if (canSymlink())
assertIsSymlink("symlink", "file");
assertIsSymlink("symlink", "file", 0);
free(buff);
free(file_buff);

View File

@ -717,4 +717,28 @@ DEFINE_TEST(test_read_format_mtree_nonexistent_contents_file)
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
/*
* Check mtree file with non-printable ascii characters
*/
DEFINE_TEST(test_read_format_mtree_noprint)
{
const char reffile[] = "test_read_format_mtree_noprint.mtree";
struct archive_entry *ae;
struct archive *a;
extract_reference_file(reffile);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK,
archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK,
archive_read_support_format_all(a));
assertEqualIntA(a, ARCHIVE_OK,
archive_read_open_filename(a, reffile, 11));
assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae));
assertEqualString("Can't parse line 3", archive_error_string(a));
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}

View File

@ -0,0 +1,4 @@
begin 644 test_read_format_mtree_noprint.mtree
K(VUT<F5E"F1I<E]O:R!T>7!E/61I<@ID:7)?P[;%H<2'('1Y<&4]9&ER"@``
`
end

View File

@ -28,6 +28,22 @@
#include <locale.h>
DEFINE_TEST(test_read_format_rar_set_format)
{
struct archive *a;
struct archive_entry *ae;
const char reffile[] = "test_read_format_rar.rar";
extract_reference_file(reffile);
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_support_filter_all(a));
assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_RAR));
assertA(0 == archive_read_open_filename(a, reffile, 10240));
assertA(0 == archive_read_next_header(a, &ae));
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
DEFINE_TEST(test_read_format_rar_basic)
{
char buff[64];
@ -3740,3 +3756,26 @@ DEFINE_TEST(test_read_format_rar_multivolume_uncompressed_files)
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
}
DEFINE_TEST(test_read_format_rar_ppmd_use_after_free)
{
uint8_t buf[16];
const char* reffile = "test_read_format_rar_ppmd_use_after_free.rar";
struct archive_entry *ae;
struct archive *a;
extract_reference_file(reffile);
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_support_filter_all(a));
assertA(0 == archive_read_support_format_all(a));
assertA(0 == archive_read_open_filename(a, reffile, 10240));
assertA(ARCHIVE_OK == archive_read_next_header(a, &ae));
assertA(archive_read_data(a, buf, sizeof(buf)) <= 0);
assertA(ARCHIVE_OK == archive_read_next_header(a, &ae));
assertA(archive_read_data(a, buf, sizeof(buf)) <= 0);
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
begin 644 test_read_format_rar5_distance_overflow.rar
M4F%R(1H'`0"-[P+2``(''/\@("`@_R4``B`@("`@("`@("`@(/__("`@("`@
M(/\@("`@("`@((9ML63,PX"&AK%:S+?_(/\@_R#_(/\@_R#_(/\@`"``!R`@
MR<G)``#_(,G)R?___R#___\@____(/___R#___\@____R4#)R<G___\@____
M(/\@____("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@(/__________
M____________________________________________________("`@("`@
.("`@("`@("`@("#_("``
`
end

View File

@ -0,0 +1,10 @@
begin 644 test_read_format_rar5_extra_field_version.rar
M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`"BNGU4(0(#!%D&7^V#`I?:-URW@4'R
M@`,!"&)I;B\R=&\S`P0``<7)5B550C]U!#WY13&:5TJ$=$IZ(*3`C\#F0%O\
M)$)*@]X[RK.Z.G*HUT;V5FO&;:X/FDW,W`95I8T%@@C:DD="_8Z.9+CQH^IG
M8!ZF0N)JSY2?R(W@25K`U&W)Q1X"`MD`!M\`[8,"E]HW7+>!0?*``P$(8FEN
M+S)T;S/%R58E54(_=00]^44QFE=*A'1*>B"DP(_`YD!;_"1"2H/>.\JSNCIR
MJ-=&]E9KQFVN#YI-S-P&5:6-!8((VI)'0OV.CF2X\:/J9V`>ID+B:L^4G\B-
,X$E:P!UW5E$#!00`
`
end

View File

@ -0,0 +1,13 @@
begin 640 test_read_format_rar5_fileattr.rar
M4F%R(1H'`0#SX8+K"P$%!P`&`0&`@(``-$;*1"@"`PN+``2+`"&+W8Z;@```
M#')E861O;FQY+G1X=`H#`J*C5`BE!M4!,3(S-#4V-S@@#0JYZ,#-)@(#"XL`
M!(L`(F^$/86````*:&ED9&5N+G1X=`H#`G(Q.0^E!M4!,C,T-38W.#D@#0H>
M%_EV)@(#"XL`!(L`)"V,TBB````*<WES=&5M+G1X=`H#`F:K01.E!M4!,S0U
M-C<X.3`@#0HQ>$42*0(#"XL`!(L`(RZ?$!V````-<F]?:&ED9&5N+G1X=`H#
M`JIEBD2M!M4!-C<X.3`Q,C,@#0HQAL?6)@(#"P`%`!$`````@```#&1I<E]R
M96%D;VYL>0H#`HS,%ABE!M4!Q!O^+"0"`PL`!0`2`````(````ID:7)?:&ED
M9&5N"@,">JRV&:4&U0'&L*8=)`(#"P`%`!0`````@```"F1I<E]S>7-T96T*
M`P(@+D4;I0;5`2YJ1$0F`@,+``4`$P````"````,9&ER7W)O:&ED9&5N"@,"
0CW7S@JT&U0$==U91`P4$````
`
end

View File

@ -0,0 +1,6 @@
begin 644 test_read_format_rar5_hardlink.rar
M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`!KI,1X'@("A0`&A0"D@P(XC;=<(1>3
M?8```0AF:6QE+G1X=#$R,S0*[8@"T2X"`PT`!@6D@P(XC;=<`````(```0QH
@87)D;&EN:RYT>'0,!00`"&9I;&4N='AT'7=640,%!```
`
end

View File

@ -0,0 +1,9 @@
begin 644 test_read_format_rar5_invalid_dict_reference.rar
M4F%R(1H'`0"-[P+2``+#!QR`!P`F^P#_^_O[^_O[^R4``B$<`0(`#@```0``
M`"#2````_____QH(`/__^P#_W5)04(#_`(:&;;%DS+?,L0```````````+%D
MS+*RLK*R/@``____Y`"R````XP```````!4``````.X`````````````````
M%5<M;&@W;3$W"2!S;'$2C5L`_____@D0````$"('``"8F)@+````/__?````
M@```2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$A(2$@S2(``2$A(2$A(
>2$A(2$A(2$A(2$A(2$A(2$Q(2$A(2$A(2$A(2)](
`
end

View File

@ -0,0 +1,9 @@
begin 644 test_read_format_rar5_leftshift1.rar
M4F%R(1H'`0"-[P+2``(''(`'`"``_R4``B$<`0(`#@```0```"#2````____
M_P`(`/__^P#_W0`"(8#_`(:&;;%DS+?,L=:NL0#(3`$`````````````````
M``"``````````+!DS+*RL[*RL@```-P``````````````````(``````````
ML&3,LK*RLK*R````W`````#X____````````````````````````%5H>;&@T
M+3HW"2!SB^)_<Z3_`````?40'Q\?'Q\?'Q\?'Q\?'Q\?'Q\?'Q\?'Q\`````
5`````````````````/H`>@``````
`
end

View File

@ -0,0 +1,6 @@
begin 644 test_read_format_rar5_leftshift2.rar
M4F%R(1H'`0"-[P+2``(''(`'`2``_RL``B'+`0(`,O__````-WJ\KR<<)0`"
M(;<*`BY*`!```&;%T#%24%"`_R4`[@K+(2Y*`&$``'__`/\E``(N2@`0`0(`
0(?__`%N&?Q2UH.CHZ.CHZ```
`
end

View File

@ -0,0 +1,9 @@
begin 644 test_read_format_rar5_nonempty_dir_stream.rar
M4F%R(1H'`0"-[P+2``(''($'$7\`_R4``BP<`0(`(0#_Y@```"#2````____
M_P`(`/__^P#_W0`"(8#_`(:&;;%DS+?,L8```!;(&P#>``#__^_P```4```&
M`````````````+`!`@`A`/_F````(-(```#_____``@`___[`/_=``(A``++
M``"`]/^`!P!#^_____\"(2$!`@`A````_R4``B$A`0(`@````0```"#&`/_=
M``(A@/\`AH9ML63,M\R`_P```,@;`````!@`````_0`````````!87(A&@<`
5`(WO`M(``O8'&X`'`#C[_X`E``(A
`
end

View File

@ -0,0 +1,8 @@
begin 644 test_read_format_rar5_owner.rar
M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`!W:E-^+0(##H4`!H4`I(,"_8VW7"$7
MDWV```$(<F]O="YT>'0-!@,$<F]O=`5W:&5E;#$R,S0*2J"P0S,"`Q*%``:%
M`*2#`FZ-MUQFP<VL@``!"FYO8F]D>2YT>'01!@,&;F]B;V1Y!VYO9W)O=7`U
M-C<X"L=81/8I`@,'A0`&A0"D@P)LD[=<>B#;(H```0MN=6UE<FEC+G1X=`8&
2#(].N$4Y.3DY"AUW5E$#!00`
`
end

View File

@ -0,0 +1,15 @@
begin 644 test_read_format_rar5_readtables_overflow.rar
M4F%R(1H'`0"-[P+2`)3+'_4`C>\"T@`"T@"4RQ_5]0#O0````,L?Q_T``(`"
MT@"4RQ_=V-C8`)3+']W=]0"-\`+2`)3+']WU`(WO`M(``M(`E,L?U?4`[P+2
M`)3+'\?]``"``M(`E,L?W=C8V`"4RQ_=]0#V`(WO`M'UV,?8V-C8$=C8V-C8
MV(W8V-C8V-C8V-C8V-C8V-C8V-C8V-C8V-C8!]C8V-C8V-C8V-C8V-C8V-C8
MV-C8V-C8V-C(V-C8V-C2`)3+']W8V-C8V-C8V-C8V-C8V-C8@-C8V-C8V-C8
MV/+8V-C8V-C8V-C8`038V-C8V-C8V-C8V-C8V-C8V`?8V-C8V-C8V-C8!-C8
MV-C8V-C8V-C8V-C8V-C8V`?8V-C8V-C8V-C8V-C8`(`"V`7V`(WO`M'U`]L?
MW?4`C>\"T@`"T@"4'__U`(WO`N``E,L?W84`C0`0T@"4RQ_=V-C8V-C8V`"4
MR_\R]0#V`(W8V-C8V-C8V-C8V-C8V-C8V-C8V-C8V`?8V-C8V-C8V-C8V-C8
MV-C8V-C8V-C8V-C8R-C8V-C8T@"4RQ_=V-C8V-C8V-C8V-C8V-C8V(#8V-C8
MV-C8````9-C8V-C8V!'8V-C8V-C8]]C8V-C8V-C8V-C8V/+8V-C8V-C8V-C8
=`038V-C8V-C8V-C8V-C8V-C8V`?8V-C8V-C8V-@`
`
end

View File

@ -0,0 +1,8 @@
begin 644 test_read_format_rar5_symlink.rar
M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`"$O8RN'@("A0`&A0"D@P(XC;=<(1>3
M?8!``0AF:6QE+G1X=#$R,S0*8QI3.2T"`PT`!@CMPP)7C;=<`````(!``0MS
M>6UL:6YK+G1X=`P%`0`(9FEL92YT>'2.NOQU)`(#"``&`^W#`DF6MUP`````
M@$`!!V1I<FQI;FL'!0$!`V1I<J/_?\87`@(`!P#M@P%&EK=<`````(```0-D
*:7(==U91`P4$````
`
end

View File

@ -0,0 +1,7 @@
begin 644 test_read_format_rar5_truncated_huff.rar
M4F%R(1H'`0"-[P+2``'#]#P\7P$'`0"-[P+2``+2`!;#M#Q::7!)2?__'`!I
M?_O_0B\*0RX-,'%O.\(#!-'^T#4````0`P1_``!#(3`P,./H`P```*^OKZ^O
MKZ^OKZ^OKZ^OKZ^OKZ^OKZ^OKZ^OKZ^OKZ^OKZ\0`*^OKZ^A``KZ``$`2^\#
9T>WMNP$+-5H*^@`!`$OOB]$````0"S5:*@``
`
end

View File

@ -1,68 +1,69 @@
begin 644 test_read_format_rar5_win32.rar
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
;0];M1^11#SKD/'L0\&IZ_]!^T!UW5E$#!00`
M4F%R(1H'`0#SX8+K"P$%!P`&`0&`@(``EV&"+"$"`PL`!0`0`````(````=T
M97-T9&ER"@,"5N<QTHH!U0&_NE<D)`(#"^D"!+`)(,UPRGR``P`(=&5S="YB
M:6X*`P(\[7R!#5K4`<KT90$G96!4'U5V7;^4DG')SV6660QPV663&,62$X9"
M223AD)"2220DXY))(0A))"$)))"22$(2$LVU;WM],PZ`?1T#KC^>NI_W0?[W
MVO?=>:\Z7^@`0`$`R""?GX]O7T\O'O[NSKZNGHY^7DX^+AX-_=W-K9U];5U-
M/2T,_-S,K)R,?&Q<3#P;^]O+NYN+>VM;2SLK&OKJVKJJFGI:2CHJ&@GYV<FY
MF7EI232R4C(1Z%`?CHR*B8<Z<-FH:$@H!^?'MZ>'9T<W)Q;VUK:6=E8V%?75
MM95U53(3?U_(_0)3Z)3G^$2718HP9Y87:C@IIBF4%^9"T7:=1C+#.,"H1_^@
ME,9I"E]E4*Q65@N+`9%H-RX'=>$&P`\Q!(R">9A6-`NFH9;8-YN'@X!@<@^N
M81.@IG88#P-MZ'N]AU?0C?Q80(T8,><*'DT)@V+XX.8Z'"($J>&%%CMC0_GQ
M4(!L(0T(A-(QG)`O)0`QGD%J)0(#"^L"!(`@(,:R$WZ``P`)=&5S=#$N8FEN
M"@,"$I6A@`U:U`'-\6<!$&1&92]7!7^22222222222222222222222222222
M222222222222222222222222222222223GY^RW,[??J[><7#G7SNUN[YG1F[
MO3O]%F,,Z?#,/6YOF>>GO;]_`_=OV`"`"`&PPZ<-FGU\_'O[>OIY^7CX=_=V
M]G7U=/1S\W+R<?%P\&_O;NYM[6SL:^MJZFGI:.AGYV;F9>5DY&/C8N)AX6#@
M7]]>WEW=7-Q;VUK:6=E8V%?75M95U5344]-2TE'14-!/ST[.3<U,S$O+2LI)
MR4C(1\=&QD7%1,1#PT+"0<%`P#_[WL?R%+A2U?J5"@,[&`%LT(W2-`0Z$+6!
M8#A$]N4M."'IR:`68`6S0C<(T!#H0M8%@.$3VW2TX(>FYH!9@!;-"-LC0$.A
M"U@6`X1/;5+3@AZ:F@%F`%LT(VB-`0Z$+6!8#A$UA]Z%,?GS*>SVE?X8*>=C
M4\-BG=.J=HXIZ?]R?M!(:PP')0(#"^L"!(`@(<NO9O&``P`)=&5S=#(N8FEN
M"@,"A/;"@`U:U`',\&<!$&1&92]7!7^22222222222222222222222222222
M222222222222222222222222222222223GY^RW,[??J[><7#G7SNUN[YG1F[
MO3O]%F,,Z?#,/6YOF>>GO;]_`_=OV`"`"`&IATX;-/KY^/?V]?3S\O'P[^[M
M[.OJZ>CGYN7DX^+AX-_>W=S;VMG8U];5U-/2T=#/SLW,R\K)R,?&Q<3#PL'`
MO[Z]O+NZN;BWMK6TL[*QL*^NK:RKJJFHIZ:EI*.BH:"?GIV<FYJ9F)>6E923
MDI&0CXZ-C(N*B8B'AH6$@X*!@'_WO8_D*7"EJ_4J%`9V,`+9H1ND:`AT(6L"
MP'")[<I:<$/3DT`LP`MFA&X1H"'0A:P+`<(GMNEIP0]-S0"S`"V:$;9&@(="
M%K`L!PB>VJ6G!#TU-`+,`+9H1M$:`AT(6L"P'")K#[T*8_/F4]GM*_PP4\[&
MIX;%.Z=4[1Q3T_[D_:#Z7*U;)0(#"_<"!(`@(-DCL9^``P`)=&5S=#,N8FEN
M"@,"A'#?@`U:U`'.YG,!$&1552]7!7XDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
MDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDG>\[SO-RUK/'AS>Z]>]72\[VUGX;
MSPS6]^._Z+,89X_&9MAOF??:->O/X'?K\@`@`@!LK,L+N/CW]O7T\_+Q\._N
M[>SKZNGHY^;EY./BX>#?WMW<V]K9V-?6U=33TM'0S\[-S,O*R<C'QL7$P\+!
MP+^^O;R[NKFXM[:UM+.RL;"OKJVLJZJIJ*>FI:2CHJ&@GYZ=G)N:F9B7EI64
MDY*1D(^.C8R+BHF(AX:%A(."@8!_?O_[[UOQB$^$)+[%!@ZJP@)I6!-DF59-
M,DTP85+::84MW9$H?1AV`=#$!-*P)L$RK!I@FF#"I;33"ENZ(E#Z,.@#H8@)
MI6!-<F57-#AI,`!MIIA2W<D2A]&'(!T,0$TK`FX)E7!H<-)@`-M-,*7RW][$
M+?7[(?3[2/T-$/>UH>G1#RK4/$L0^/_<7F@SHER0)0(#"_<"!(`@(-0^Q!"`
M`P`)=&5S=#0N8FEN"@,"`HP9@0U:U`'/YW,!$&1552]7!7XDDDDDDDDDDDDD
MDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDG.\[SG-RUK/'
MASFZ]>]72\[VUGX;SPS6]^._Z+,89X_&9MAOF??:->O/X'?K\@`@`@!L*,KK
M*_'O[>OIY^7CX=_=V]G7U=/1S\W+R<?%P\&_O;NYM[6SL:^MJZFGI:.AGYV;
MF9>5DY&/C8N)AX6#@7]]>WEW=7-Q;VUK:6=E8V%?75M95U5344]-2TE'14-!
M/ST[.3<U,S$O+2LI)R4C(1\=&QD7%1,1#PT+"0<%`P#^_?_WWJ?C$.>$.%]B
M@P=380$TG`FR3*LFF2;D&$RVFF%+=@B4/HPP`=#$!-)P)KDRJYI<FY!A,MII
MA2W=D2A]&'8!T,0$TG`FL3*K&APTY``;::84MW1$H?1AT`=#$!-)P)JDRJIH
M<-.0`&VFF%+Y3^]B%/K]D/I]I'Z&B'O:T/3HAY5J'B6(?'_N+S0M?'0I)0(#
M"X`#!(`@(/)5T;F``P`)=&5S=#4N8FEN"@,"*GQ(@0U:U`'([WP!$&1552]U
M;J2222222222222222222222222222222222222222222222222222222222
M222<[SO.\W+-:\><<W<O7O5TO.]MYF?9XZUO?CO]%F,,\?C,,TUW/OM&_7OX
M'GK\@`@`@!K.%UE5/CW]O7T\_+Q\._N[>SKZNGHY^;EY./BX>#?WMW<V]K9V
M-?6U=33TM'0S\[-S,O*R<C'QL7$P\+!P+^^O;R[NKFXM[:UM+.RL;"OKJVLJ
MZJIJ*>FI:2CHJ&@GYZ=G)N:F9B7EI64DY*1D(^.C8R+BHF(AX:%A(."@8!_?
MO_[[W'XXA.D)1LT$"OW!PR6LE*QQ<,847-+AIH@;:C`.CV[!$+6S=F"ILX9+
M62E8XL&,*+&E@TT0-M1@'1[=`B%K9NC!4V<,EK)2L<5#&%%32H::(&VHP#H]
MN01"ULW)@J;.&2UDI6.*!C"BAI0--$#;48!T?G'][B''U_9#Z?:1^AHA[VM#
MT\$/*RH>)D0^/_</F@#V;XCT)0(#"X`#!(`@(/](I#:``P`)=&5S=#8N8FEN
M"@,"%79G@0U:U`')[GP!$&1552]U;J222222222222222222222222222222
M2222222222222222222222222222222<[SO.\W+-:\><<W<O7O5TO.]MYF?9
MXZUO?CO]%F,,\?C,,TUW/OM&_7OX'GK\@`@`@!NG"ZRJGQ[^WKZ>?EX^'?W=
MO9U]73T<_-R\G'Q</!O[V[N;>UL[&OK:NIIZ6CH9^=FYF7E9.1CXV+B8>%@X
M%_?7MY=W5S<6]M:VEG96-A7UU;65=54U%/34M)1T5#03\].SDW-3,Q+RTK*2
M<E(R$?'1L9%Q43$0\-"PD'!0,`_OW_]][C\<0G2$HV:"!7[@X9+62E8XN&,*
M+FEPTT0-M1@'1[=@B%K9NS!4V<,EK)2L<6#&%%C2P::(&VHP#H]N@1"ULW1@
MJ;.&2UDI6.*AC"BII4--$#;48!T>W((A:V;DP5-G#):R4K'%`QA10TH&FB!M
KJ,`Z/SC^]Q#CZ_LA]/M(_0T0][6AZ>"'E94/$R(?'_N'S0`==U91`P4$````
`
end

View File

@ -0,0 +1,10 @@
begin 644 test_read_format_rar_ppmd_use_after_free.rar
M4F%R(1H'``1G=$Q26`!W````>U!+`P0R`'#_J7\`+@TU'`#]`0`7__]"0D)"
M+W5N<V5T"6=I9`UD#1T+``!"`````````&%R(1H'``1G>TQ26`!W=&@`[E!+
M`P0Q`'#_(````"`@(+<@!/T`("`@("`@("`@("`@("`@("`@("`@("`@("`@
M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@
M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@(`1G=$Q26`!W````
M>U!+`P0R`'#_J7\`+@TU'`#]`0`7__]"0D)"+W5N<V5T"6=I9`UD#1T+``!"
@`````````&%R(1H'``1G>TQ26`!W=&@`[E!+`P0Q`'``
`
end

View File

@ -36,6 +36,7 @@ DEFINE_TEST(test_read_format_raw)
const char *reffile1 = "test_read_format_raw.data";
const char *reffile2 = "test_read_format_raw.data.Z";
const char *reffile3 = "test_read_format_raw.bufr";
const char *reffile4 = "test_read_format_raw.data.gz";
/* First, try pulling data out of an uninterpretable file. */
extract_reference_file(reffile1);
@ -117,4 +118,30 @@ DEFINE_TEST(test_read_format_raw)
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
/* Fourth, try with gzip which has metadata. */
extract_reference_file(reffile4);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_raw(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
assertEqualIntA(a, ARCHIVE_OK,
archive_read_open_filename(a, reffile4, 1));
/* First (and only!) Entry */
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assertEqualString("test-file-name.data", archive_entry_pathname(ae));
assertEqualInt(archive_entry_is_encrypted(ae), 0);
assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
assert(archive_entry_mtime_is_set(ae));
assertEqualIntA(a, archive_entry_mtime(ae), 0x5cbafd25);
/* Most fields should be unset (unknown) */
assert(!archive_entry_size_is_set(ae));
assert(!archive_entry_atime_is_set(ae));
assert(!archive_entry_ctime_is_set(ae));
/* Test EOF */
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}

View File

@ -0,0 +1,4 @@
begin 644 test_read_format_raw.data.gz
L'XL(""7]NEP``W1E<W0M9FEL92UN86UE+F1A=&$`2\O/YP(`J&4R?@0`````
`
end

Some files were not shown because too many files have changed in this diff Show More