MFHead @348740
Sponsored by: The FreeBSD Foundation
This commit is contained in:
commit
0269ae4c19
9
Makefile
9
Makefile
@ -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
|
||||
|
@ -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}
|
||||
|
@ -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
|
||||
|
17
UPDATING
17
UPDATING
@ -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)
|
||||
|
@ -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; \
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
20
cddl/usr.sbin/dtrace/tests/amd64/arrays/Makefile
Normal file
20
cddl/usr.sbin/dtrace/tests/amd64/arrays/Makefile
Normal 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"
|
12
cddl/usr.sbin/dtrace/tests/i386/Makefile
Normal file
12
cddl/usr.sbin/dtrace/tests/i386/Makefile
Normal 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>
|
19
cddl/usr.sbin/dtrace/tests/i386/arrays/Makefile
Normal file
19
cddl/usr.sbin/dtrace/tests/i386/arrays/Makefile
Normal 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"
|
22
cddl/usr.sbin/dtrace/tests/i386/funcs/Makefile
Normal file
22
cddl/usr.sbin/dtrace/tests/i386/funcs/Makefile
Normal 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"
|
23
cddl/usr.sbin/dtrace/tests/i386/pid/Makefile
Normal file
23
cddl/usr.sbin/dtrace/tests/i386/pid/Makefile
Normal 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"
|
26
cddl/usr.sbin/dtrace/tests/i386/ustack/Makefile
Normal file
26
cddl/usr.sbin/dtrace/tests/i386/ustack/Makefile
Normal 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"
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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:
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -71,8 +71,13 @@ test_create(void)
|
||||
* #ifdef this section out. Most of the test below is
|
||||
* still valid. */
|
||||
memset(×, 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, ×));
|
||||
|
||||
/* Record whatever atime the file ended up with. */
|
||||
|
@ -85,7 +85,7 @@ DEFINE_TEST(test_option_c)
|
||||
|
||||
/* "symlink" */
|
||||
if (canSymlink()) {
|
||||
assertMakeSymlink("symlink", "file");
|
||||
assertMakeSymlink("symlink", "file", 0);
|
||||
fprintf(filelist, "symlink\n");
|
||||
}
|
||||
|
||||
|
@ -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 *,
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
62
contrib/libarchive/libarchive/archive_entry_misc.3
Normal file
62
contrib/libarchive/libarchive/archive_entry_misc.3
Normal 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
|
@ -176,6 +176,9 @@ struct archive_entry {
|
||||
|
||||
/* Miscellaneous. */
|
||||
char strmode[12];
|
||||
|
||||
/* Symlink type support */
|
||||
int ae_symlink_type;
|
||||
};
|
||||
|
||||
#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
/*
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 *);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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'",
|
||||
|
@ -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. */
|
||||
|
@ -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,
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
@ -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
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -1,68 +1,69 @@
|
||||
begin 644 test_read_format_rar5_win32.rar
|
||||
M4F%R(1H'`0#SX8+K"P$%!P`&`0&`@(``/^"F5B0"`POI`@2P"2#-<,I\@`4`
|
||||
M"'1E<W0N8FEN"@,"/.U\@0U:U`'*]&4!)V5@5!]5=EV_E))QR<]EEED,<-EE
|
||||
MDQC%DA.&0DDDX9"0DDDD)..222$(220A"220DDA"$A+-M6][?3,.@'T=`ZX_
|
||||
MGKJ?]T'^]]KWW7FO.E_H`$`!`,@@GY^/;U]/+Q[^[LZ^KIZ.?EY./BX>#?W=
|
||||
MS:V=?6U=33TM#/S<S*R<C'QL7$P\&_O;R[N;BWMK6TL[*QKZZMJZJIIZ6DHZ
|
||||
M*AH)^=G)N9EY:4DTLE(R$>A0'XZ,BHF'.G#9J&A(*`?GQ[>GAV='-R<6]M:V
|
||||
MEG96-A7UU;65=54R$W]?R/T"4^B4Y_A$ET6*,&>6%VHX*:8IE!?F0M%VG48R
|
||||
MPSC`J$?_H)3&:0I?95"L5E8+BP&1:#<N!W7A!L`/,02,@GF85C0+IJ&6V#>;
|
||||
MAX.`8'(/KF$3H*9V&`\#;>A[O8=7T(W\6$"-&#'G"AY-"8-B^.#F.APB!*GA
|
||||
MA18[8T/Y\5"`;"$-"(32,9R0+R4`8B?AZB4"`POG`@2`("#&LA-^@`4`"71E
|
||||
M<W0Q+F)I;@H#`A*5H8`-6M0!R/!C`1!D168O5P5_4DDDDDDDDDDDDDDDDDDD
|
||||
MDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD^_/D;F=O/:[?;Z2Z_N
|
||||
M[6[OF=&;N]._TF,S#.GS#C<WS/.'/XKG;\@`@`@!L,/'3AM\>_MZ^GGY>/AW
|
||||
M]W;V=?5T]'/S<O)Q\7#P;^]N[FWM;.QKZVKJ:>EHZ&?G9N9EY63D8^-BXF'A
|
||||
M8.!?WU[>7=U<W%O;6MI9V5C85]=6UE755-13TU+24=%0T$_/3LY-S4S,2\M*
|
||||
MRDG)2,A'QT;&1<5$Q$/#0L)!P4#`/[\^^]['VA2X4M7TE0H#.Q@!;-"-XC0$
|
||||
M.A"U@6`X1/;M+3@AZ=F@%F`%LT(W2-`0Z$+6!8#A$]N4M."'IR:`68`6S0C<
|
||||
M(T!#H0M8%@.$3VW2TX(>FYH!9@!;-"-LC0$.A"U@6`X1-8__0K^QS*_>TU/6
|
||||
MRJ_(8IKGE-.XIH6GK_HGV@`)6BG`)0(#"^8"!(`@(,NO9O&`!0`)=&5S=#(N
|
||||
M8FEN"@,"A/;"@`U:U`'/]F(!$&1%9B]7!7]2222222222222222222222222
|
||||
M2222222222222222222222222222222222223[\^1N9V\]KM]OI+K^[M;N^9
|
||||
MT9N[T[_28S,,Z?,.-S?,\X<_BN=OR`"`"`&IAXZ<-OCW]O7T\_+Q\._N[>SK
|
||||
MZNGHY^;EY./BX>#?WMW<V]K9V-?6U=33TM'0S\[-S,O*R<C'QL7$P\+!P+^^
|
||||
MO;R[NKFXM[:UM+.RL;"OKJVLJZJIJ*>FI:2CHJ&@GYZ=G)N:F9B7EI64DY*1
|
||||
MD(^.C8R+BHF(AX:%A(."@8!_?GWWO8^T*7"EJ^DJ%`9V,`+9H1O$:`AT(6L"
|
||||
MP'")[=I:<$/3LT`LP`MFA&Z1H"'0A:P+`<(GMREIP0].30"S`"V:$;A&@(="
|
||||
M%K`L!PB>VZ6G!#TW-`+,`+9H1MD:`AT(6L"P'")K'_Z%?V.97[VFIZV57Y#%
|
||||
M-<\IIW%-"T]?]$^TVMWAVR4"`POT`@2`("#9([&?@`4`"71E<W0S+F)I;@H#
|
||||
M`H1PWX`-6M0!RN%P`1!D554O5P5^))))))))))))))))))))))))))))))))
|
||||
M))))))))))))))))))))))))))))))SO.\[S<:UGCPYS=>O+LEY]]M9^&\\,
|
||||
MWO7CO^DQF89X_9MAKF??:-?Q7/7Y`!`!`#848765^/?V]?3S\O'P[^[M[.OJ
|
||||
MZ>CGYN7DX^+AX-_>W=S;VMG8U];5U-/2T=#/SLW,R\K)R,?&Q<3#PL'`O[Z]
|
||||
MO+NZN;BWMK6TL[*QL*^NK:RKJJFHIZ:EI*.BH:"?GIV<FYJ9F)>6E923DI&0
|
||||
MCXZ-C(N*B8B'AH6$@X*!@']^??=]3[8AOPALOH4&#J;"`FDX$V"95@TP3;@P
|
||||
MF6DRPI=O")0\&G@!T,0$TG`FN3*KFER;<&$RTF6%+MV1*'@T[`.AB`FDX$UB
|
||||
M958T/&FX`#:3+"EVZ(E#P:=`'0Q`32<":I,JJ:'C3<`!M)EA2^4__8C^QK(_
|
||||
M>\:'K=J/R*(<ZY#CV(<&IZ_]"_:`$R,0$"4"`POT`@2`("#4/L00@`4`"71E
|
||||
M<W0T+F)I;@H#`@*,&8$-6M0!R^!P`1!D554O5P5^I)))))))))))))))))))
|
||||
M))))))))))))))))))))))))))))))))))))))))))SO.\YS<:UGCPYS=>O+
|
||||
MLEY]]M9^&\\,WO7CO^DQF89X_9MAKF??:-?Q7/7Y`!`!`#7=,+*J?'O[>OIY
|
||||
M^7CX=_=V]G7U=/1S\W+R<?%P\&_O;NYM[6SL:^MJZFGI:.AGYV;F9>5DY&/C
|
||||
M8N)AX6#@7]]>WEW=7-Q;VUK:6=E8V%?75M95U5344]-2TE'14-!/ST[.3<U,
|
||||
MS$O+2LI)R4C(1\=&QD7%1,1#PT+"0<%`P#^_/ON^Z^V(;\(;+Z%!@ZFP@)I.
|
||||
M!-@F58-,$VX,)EI,L*7:Y$H>#2X!T,0$TG`FL3*K&EB;<&$RTF6%+MX1*'@T
|
||||
M\`.AB`FDX$U2954T/&FX`#:3+"EV[(E#P:=@'0Q`32<":A,JH:'C3<`!M)EA
|
||||
M2^=?_L1_8UD?O>-#UNU'Y%$.=<AQ[$.#4]?^A?M`Y!DD9R4"`PO\`@2`("#R
|
||||
M5=&Y@`4`"71E<W0U+F)I;@H#`BI\2($-6M0!S.]X`1!D554O=6ZDDDDDDDDD
|
||||
MDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDG.\[SO-Q
|
||||
MFM>/..;N7KV[)>??;>LS[/'-[UX[_28S,,\?L,TUS/OM&_Q7/7Y`!`!`#6<+
|
||||
MK*J?'O[>OIY^7CX=_=V]G7U=/1S\W+R<?%P\&_O;NYM[6SL:^MJZFGI:.AGY
|
||||
MV;F9>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#^_/ON^X^W$)PA)M
|
||||
MD@@5^H.&2UDI2.+AC"BYI<-/"!MIL`Z/;L$0M;)V8*FSADM9*4CBP8PHL:6#
|
||||
M3P@;:;`.CVZ!$+6R=&"ILX9+62E(XJ&,**FE0T\(&VFP#H]N01"ULG)@J;.&
|
||||
M2UDI2.*!C"BAI0-/"!MIL`Z/G'_[B/[&LC][QH>MVH_(HAYUR'CV(>#4]?^@
|
||||
M_:`_"MBZ)0(#"_P"!(`@(/](I#:`!0`)=&5S=#8N8FEN"@,"%79G@0U:U`'-
|
||||
M[G@!$&1552]U;J2222222222222222222222222222222222222222222222
|
||||
M222222222222222<[SO.\W&:UX\XYNY>O;LEY]]MZS/L\<WO7CO])C,PSQ^P
|
||||
MS37,^^T;_%<]?D`$`$`-TX7654^/?V]?3S\O'P[^[M[.OJZ>CGYN7DX^+AX-
|
||||
M_>W=S;VMG8U];5U-/2T=#/SLW,R\K)R,?&Q<3#PL'`O[Z]O+NZN;BWMK6TL[
|
||||
M*QL*^NK:RKJJFHIZ:EI*.BH:"?GIV<FYJ9F)>6E923DI&0CXZ-C(N*B8B'AH
|
||||
M6$@X*!@']^??=]Q]N(3A"3;)!`K]0<,EK)2D<7#&%%S2X:>$#;38!T>W8(A:
|
||||
MV3LP5-G#):R4I'%@QA18TL&GA`VTV`='MT"(6MDZ,%39PR6LE*1Q4,845-*A
|
||||
MIX0-M-@'1[<@B%K9.3!4V<,EK)2D<4#&%%#2@:>$#;38!T?./_W$?V-9'[WC
|
||||
;0];M1^11#SKD/'L0\&IZ_]!^T!UW5E$#!00`
|
||||
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
|
||||
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
|
||||
|
@ -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
|
@ -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));
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user