Compare commits

...
183 Commits
Author SHA1 Message Date
Mark Johnston 833d39bd2e Add UPDATING entries and bump version
Approved by:	so
2026-06-30 02:32:02 +00:00
Mark Johnston 32f296b695 iconv: Fix a stack buffer overflow in _ISO2022_sputwchar()
In the ISO2022-CN encoding, characters may require at least seven bytes,
and MB_LEN_MAX==6 is insufficient.  From code inspection,
_ISO2022_sputwchar() can emit 10 bytes in the worst case, so use that to
size buffers.

Add a regression test.

Approved by:	so
Security:	FreeBSD-SA-26:49.iconv
Security:	CVE-2026-58082
Reviewed by:	kevans
Differential Revision:	https://reviews.freebsd.org/D57950
2026-06-30 02:32:02 +00:00
Mark Johnston 0b49a3af87 iconv: Fix a buffer overflow in the HZ encoding
wcrtomb may store up to 2 2-byte escape sequences to the state buffer in
addition to the character itself.  In the worst case, a 3-byte heap
overflow is possible.

Approved by:	so
Security:	FreeBSD-SA-26:49.iconv
Security:	CVE-2026-58081
Reviewed by:	kevans
Differential Revision:	https://reviews.freebsd.org/D57949
2026-06-30 02:32:02 +00:00
Taylor R Campbell 01738cff03 iconv(3): Draft some automatic tests.
Based on a report by Nick Wellnhofer.

Approved by:	so
Security:	FreeBSD-SA-26:49.iconv
Reviewed by:	markj, kevans
Differential Revision:	https://reviews.freebsd.org/D57948
2026-06-30 02:32:02 +00:00
Taylor R Campbell 2329d94e49 iconv(3): Fix problems in various encodings
Fix null pointer dereference with HZ8 encoding.

Fix output buffer overrun in UTF-7, VIQR, ZW encodings.

Approved by:	so
Security:	FreeBSD-SA-26:49.iconv
Security:	CVE-2026-58081
Reviewed by:	markj, kevans
Differential Revision:	https://reviews.freebsd.org/D57947
2026-06-30 02:32:02 +00:00
Ed Maste 495ee4943c compat32: Zero struct to avoid stack disclosure
Approved by:	so
Security:	FreeBSD-SA-26:48.compat32
Security:	CVE-2026-49425
Reported by:	Adam Crosser, Praetorian
Reviewed by:	philip
Sponsored by:	The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D55811

(cherry picked from commit 097cb4e9f0)
(cherry picked from commit 4551ea3b3f)
(cherry picked from commit 6a808cd753)
2026-06-30 02:32:02 +00:00
Ed Maste 6d04386937 compat/linux: Avoid waitid() kernel stack disclosure
Approved by:	so
Security:	FreeBSD-SA-26:47.linux
Security:	CVE-2026-49424
Reported by:	Adam Crosser, Praetorian
Reviewed by:	philip
Sponsored by:	The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D55812

(cherry picked from commit 9a9f93bcf1)
(cherry picked from commit 9f8db9cc67)
(cherry picked from commit a347e6e20e)
2026-06-30 02:32:02 +00:00
John Baldwin f769a69b2d ktls CBC decrypt: Only increment iovec index when an entry is used
If an mbuf in the chain was skipped because it only contained bytes
from the header, the iovec index ('i') was incremented even though the
entry was not populated.  Only increment 'i' when an iovec entry is
consumed.

Add a new type of KTLS receive test which writes a single TLS record
via two separate write(2) calls over a TCP_NODELAY socket to trigger
a split in the mbuf chain in the kernel.  Test various split locations
including after the "plain" TLS header (5 bytes), after the full TLS
header, in the middle of the data payload, just before the start of
the trailer, and in the middle of the trailer.  These tests are also
run against all supported ciphers, not just CBC.  The 'header' test
for CBC ciphersuites was able to trigger the bug.

Approved by:	so
Security:	FreeBSD-SA-26:46.ktls
Security:	CVE-2026-49423
Sponsored by:	Chelsio Communications
2026-06-30 02:32:02 +00:00
Kyle Evans 8b11e7df3a kern: fix auditing of ptrace(2) syscall requests
`error` here is the return value of syscall_thread_enter() rather than
the syscall itself, so the committed audit records do not reflect
reality.  This is less harmful than them recording an error when the
operation actually succeeded, but it could still possibly be used to
throw off IDS techniques with things like bsmtrace.

Approved by:	so
Security:	FreeBSD-SA-26:45.audit
Security:	CVE-2026-49426
Reviewed by:	des, kib, markj, csjp
Differential Revision:	https://reviews.freebsd.org/D57847
2026-06-30 02:32:02 +00:00
Mark Johnston 5272af9201 posixshm: Fix handling of sendfile() with largepage objects
sendfile(2) can transmit POSIX shared memory objects.  Typically it will
look up and wire each page before sending it to a socket; once
transmission is complete, the page is unwired and typically released
back into the page queues.  sendfile() has an advisory flag, SF_NOCACHE,
which means, "try to free the page once transmission is complete."  This
is implemented in vm_page_release(), which expects to operate on managed
pages.

Pages belonging a largepage object are de-facto wired not explicitly so.
Thus, vm_page_release() will unwire and, having found no additional
references, free the page.  Because mappings of largepage objects are
unmanaged, userspace can still access the now freed page.

Fix the problem by explicitly wiring largepage pages.  Make the VM
object destructor responsible for unwiring and freeing them.

Add a regression test.

Approved by:	so
Security:	FreeBSD-SA-26:44.posixshm
Security:	CVE-2026-49427
Reported by:	Chris Jarrett-Davies <[email protected]>
Reviewed by:	kib
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D57832
2026-06-30 02:32:01 +00:00
Mark Johnston d6e382c176 posixshm: Disallow truncation of largepage objects
We correctly handled ftruncate(), but not open(O_TRUNC).

Add a regression test.

Approved by:	so
Security:	FreeBSD-SA-26:44.posixshm
Security:	CVE-2026-49428
Reported by:	Chris Jarrett-Davies <[email protected]>
Reviewed by:	kib
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D57831
2026-06-30 02:32:01 +00:00
Mark Johnston 25f7efc533 posixshm: Disallow fspacectl() on largepage objects
As with truncation, the operation isn't supported, but nothing prevented
it.

Add a regression test.

Approved by:	so
Security:	FreeBSD-SA-26:44.posixshm
Security:	CVE-2026-49428
Reported by:	Chris Jarrett-Davies <[email protected]>
Reviewed by:	kib
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D57830
2026-06-30 02:32:01 +00:00
Mark Johnston 8845978fec rack: Reload the TCP stack PCB after reacquiring the inpcb lock
Malicious userspace might switch TCP stacks twice while the inpcb lock
is dropped.  If it does so, the validation of tp->t_fb might succeed,
but the saved pointer to the stack PCB might be invalid.  Reload it to
avoid this problem, as BBR already does.

Approved by:	so
Security:	FreeBSD-SA-26:43.tcp
Security:	CVE-2026-49422
Reported by:	Maik Münch
Reviewed by:	tuexen
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D57791
2026-06-30 02:32:01 +00:00
Mark Johnston acfff8b35b unlinkat: Pass flags down to the work functions
The unlinkat(2) and funlinkat(2) system calls were ignoring
AT_RESOLVE_BENEATH.

Also pass pathseg through instead of assuming it's UIO_USERSPACE.

Add some tests which make sure that AT_RESOLVE_BENEATH is handled
properly by various system calls.

Approved by:	so
Security:	FreeBSD-SA-26:42.unlinkat
Security:	CVE-2026-49421
Reported by:	Yuxiang Yang, Yizhou Zhao, Ao Wang, Xuewei Feng, Qi Li, and Ke Xu from Tsinghua University using GLM-5.1 from Z.ai
Reviewed by:	kib
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D57790
2026-06-30 02:32:01 +00:00
Mark Johnston 935a96aa77 tests/libalias: Add a regression test for an alias_smedia bug
Approved by:	so
Security:	FreeBSD-SA-26:41.libalias
Security:	CVE-2026-49420
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D57747
2026-06-30 02:32:01 +00:00
Dag-Erling Smørgrav 28cf6170ea libalias: Fix buffer overflow in RTSP aliasing
In alias_rtsp_out(), we construct a new packet in a fixed-length buffer
before copying it back into the original buffer.  We never checked if
the data we were writing to this temporary buffer fit in it, nor if the
result fit in the original buffer.

* Use a dynamically sized allocated buffer instead of a fixed-length
  stack buffer.

* Check for overflow before appending to our temporary buffer.

* Check for overflow before copying the data back to the packet buffer.

* While here, use size_t for sizes and bool for booleans.

Approved by:	so
Security:	FreeBSD-SA-26:41.libalias
Security:	CVE-2026-49420
MFC after:	1 week
Reviewed by:	markj
Differential Revision:	https://reviews.freebsd.org/D57753
2026-06-30 02:32:01 +00:00
Mark Johnston 6503d56e7c zfs: Roll up several upstream commits
This commit squashes the following upstream commits:
  #18604 63a0ff6cd nvpair: Check for un-terminated strings in packed nvlist
  #18617 38cd6adcb Extend dataset zfs_ioc_set_prop() secpolicy
  #18615 738791027 Fix the integer type in zfs_ioc_userspace_many()
  #18623 06d8cfedb Add additional verification of size fields and strings

Approved by:	so
Security:	FreeBSD-SA-26:40.zfs
Security:	CVE-2026-49429
Security:	CVE-2026-49430
Security:	CVE-2026-49431
2026-06-30 02:32:01 +00:00
Konstantin Belousov 6772a8ece2 execve_block(): a mechanism for mutual exclusion with execve() on the process
(cherry picked from commit e1a84b7708)
(cherry picked from commit dc94d15a71)

proc: Allow to make proc_rwmem() operate on a consistent address space

(cherry picked from commit e1b0d051bb)
(cherry picked from commit e7578e37d8)

kern_proc.c: ensure stability of the vmspace we read the strings from

(cherry picked from commit a22c044cce)
(cherry picked from commit 1f062247ef)

kern_proc.c: ensure stability of the vmspace for sysctl kern.proc.vmmap

(cherry picked from commit 5fe6e08d2d)
(cherry picked from commit e856c10a4d)

kern_proc.c: ensure stability of the vmspace for sysctl kern.proc.vm_layout

(cherry picked from commit 31fa677e4a)
(cherry picked from commit da1398dd69)

kern_proc.c: make kern.proc.osrel atomic

(cherry picked from commit 80626f34ee)
(cherry picked from commit b3f99ce653)

kern_proc.c: disallow execve around sysctl kern.proc.kstacks

(cherry picked from commit 8b5abd9027)
(cherry picked from commit 197f367cdd)

kern_proc.c: disallow execve around sysctl kern.proc.rlimit

(cherry picked from commit 5a91fa5a76)
(cherry picked from commit 35b95beb06)

kern_event: block the target process from execing for sysctl kern.proc.kqueue

(cherry picked from commit 79b384bd8f)
(cherry picked from commit adb14791b7)

kern_resource.c: disallow execve around sysctl kern.proc.rlimitusage

(cherry picked from commit 8367498170)
(cherry picked from commit 190d6677b1)

kern_procctl(PROC_WX_MAPPINGS_PERMIT): ensure stability of the target vmspace

(cherry picked from commit 6a572920f2)
(cherry picked from commit 23ebf0c97a)

linux_prlimit(): block execve for the target

(cherry picked from commit e41c28e67f)
(cherry picked from commit a11c4f036c)

pfs_readdir(): block the target process from execing

(cherry picked from commit 4c0a0909f9)
(cherry picked from commit caa2e5cf7c)

pseudofs: ensure that the target process vmspace is stable for VOP_READ/WRITE

(cherry picked from commit a4993bac41)
(cherry picked from commit ec0d7d01d6)

procfs, linprocfs: ensure target process vmspace stability

(cherry picked from commit 5db31f1b47)
(cherry picked from commit d7d5337291)

sys_set*id(9): wait for the execblocks to pass

(cherry picked from commit d0384f50da)
(cherry picked from commit 34b95f53e7)

kern_exec.c: explicitly include sys/limits.h for UINT_MAX

(cherry picked from commit f5fce0bcc3)
(cherry picked from commit bb1154f3ea)

Approved by:	so
Security:	FreeBSD-SA-26:39.execve
Security:	CVE-2026-49415
2026-06-30 02:32:01 +00:00
Mark Johnston 78bd098b9f device_pager: Avoid double-insertion of pages into the pager list
Unmanaged device pager objects maintain a linked list of pages that were
returned from the fault handler.  Initially, such pages are valid, but
msync(MS_INVALIDATE) can mark them invalid (and clean).  They are not
removed from page tables (since they are unmanaged), but a subsequent
mlock() call can trigger a page fault that is handled by the pager.
dev_pager_getpages() then re-inserts the page into the linked list even
though it's already present there.

This patch fixes the problem by removing the linked list.  OBJ_PG_DTOR
is set, so vm_object_terminate_pages() does nothing, and
dev_pager_dealloc() instead handles cleanup of the object.

Add a regression test case which triggers a queue.h assertion failure in
unpatched kernels.

Note, in stable branches we should avoid changing the layout of struct
vm_object.

Approved by:	so
Security:	FreeBSD-SA-26:37.vm
Security:	CVE-2026-49418
Reported by:	slidybat
Reviewed by:	kib
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D57743
2026-06-30 02:32:01 +00:00
Piotr Kubaj e96d0e1fcc sys/arm64: fix return values of freebsd32_{set,swap}context()
This patch aligns the return values of freebsd32_{set,swap}context()
with their counterparts on amd64 and powerpc64, fixing the setcontext()
and swapcontext() calls in armv7 applications running on aarch64.

In particular, this fixes random crashes in armv7 Ruby applications
running on aarch64 hosts.

Approved by:	so
Security:	FreeBSD-EN-26:16.arm64
Tested by:	fuz
MFC after:	1 week

(cherry picked from commit 92ae21e8a1)
(cherry picked from commit 58a15fe75c)
2026-06-30 02:31:57 +00:00
Mark Johnston 0b1dfc9478 Add UPDATING entries and bump version
Approved by:	so
2026-06-08 15:24:16 +00:00
Gordon Tetlow f61d7fc2ba ldns: Fix query response validation
Approved by:	so
Security:	FreeBSD-SA-26:36.ldns
Security:	CVE-2026-10846
2026-06-07 17:48:17 +00:00
Gordon Tetlow dd3096b4ef openssl: Fix multiple vulnerabilities
This is a rollup commit from upstream to fix:
  Reject oversized inputs in ASN1_mbstring_ncopy()
  cms: kek_unwrap_key: Fix out-of-bounds read in check-byte validation
  cms: kek_unwrap_key: test for fix out-of-bounds read in check-byte validation
  Avoid length truncation in ASN1_STRING_set
  Reject potentially forged encrypted CMS AuthEnvelopedData messages
  Fix potential NULL dereference processing CMS PasswordRecipientInfo
  Match the local q DHX parameter against the peer's q
  Apply the buffered IV on the AES-OCB EVP_Cipher() path
  Fix handling of empty-ciphertext messages in AES-GCM-SIV and AES-SIV
  Fix possible use-after-free in OpenSSL PKCS7_verify()

Approved by:	so
Obtained from:	OpenSSL
Security:	FreeBSD-SA-26:35.openssl
Security:	CVE-2026-7383
Security:	CVE-2026-9076
Security:	CVE-2026-34180
Security:	CVE-2026-34182
Security:	CVE-2026-42766
Security:	CVE-2026-42770
Security:	CVE-2026-45445
Security:	CVE-2026-45446
Security:	CVE-2026-45447
2026-06-07 17:48:17 +00:00
Ed Maste 9cba21c2de vt: Avoid integer overflow in CONS_HISTORY ioctl
Approved by:	so
Security:	FreeBSD-SA-26:34.vt
Security:	CVE-2026-49416
Reviewed by:	markj, vexeduxr
Sponsored by:	The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D57250

(cherry picked from commit 0ae946e722)
(cherry picked from commit deaaddf1d3)
(cherry picked from commit b5a4f4bfbc)
2026-06-07 17:48:17 +00:00
Dag-Erling Smørgrav a68c183e0a unbound: Apply upstream patches
- Use the same EDE removal logic when encoding errors as when encoding
  replies.
- Fix CVE-2026-33278, Possible remote code execution during DNSSEC
  validation. Thanks to Qifan Zhang, Palo Alto Networks, for the report.
- Fix CVE-2026-42944, Heap overflow and crash with multiple nsid,
  cookie, padding EDNS options. Thanks to Qifan Zhang, Palo Alto
  Networks, for the report.
- Fix CVE-2026-42959, Crash during DNSSEC validation of malicious
  content. Thanks to Qifan Zhang, Palo Alto Networks, for the report.
- Fix CVE-2026-32792, Packet of death with DNSCrypt. Thanks to Andrew
  Griffiths from 'calif.io' for the report.
- Fix CVE-2026-40622, "Ghost domain name" variant. Thanks to Qifan
  Zhang, Palo Alto Networks, for the report.
- Fix CVE-2026-41292, Parsing a long list of incoming EDNS options
  degrades performance. Thanks to GitHub user 'N0zoM1z0', also Qifan
  Zhang from Palo Alto Networks, for the report.
- Fix CVE-2026-42534, Jostle logic bypass degrades resolution
  performance. Thanks to Qifan Zhang, Palo Alto Networks, for the
  report.
- Fix CVE-2026-42923, Degradation of service with unbounded NSEC3 hash
  calculations. Thanks to Qifan Zhang, Palo Alto Networks, for the
  report.
- Fix CVE-2026-42960, Possible cache poisoning attack while following
  delegation. Thanks to TaoFei Guo from Peking University, Yang Luo and
  JianJun Chen, Tsinghua University, for the report.
- Fix CVE-2026-44390, Unbounded name compression in certain cases causes
  degradation of service. Thanks to Qifan Zhang, Palo Alto Networks, for
  the report.
- Fix CVE-2026-44608, Use after free and crash in RPZ code. Thanks to
  Qifan Zhang, Palo Alto Networks, for the report.

Approved by:	so
Security:	FreeBSD-SA-26:33.unbound
Security:	CVE-2026-33278
Security:	CVE-2026-42944
Security:	CVE-2026-42959
Security:	CVE-2026-32792
Security:	CVE-2026-40622
Security:	CVE-2026-41292
Security:	CVE-2026-42534
Security:	CVE-2026-42923
Security:	CVE-2026-42960
Security:	CVE-2026-44390
Security:	CVE-2026-44608
2026-06-07 17:48:17 +00:00
Mark Johnston 744f62ccbf imgact_elf: Clear no-ASLR and -WXORX flags earlier for setugid images
Otherwise an unprivileged user can disable randomization of the base
address for PIEs even if they are setugid.

Add a regression test.

Approved by:	so
Security:	FreeBSD-SA-26:32.elf
Security:	CVE-2026-49414
Reported by:	David Berard
Reviewed by:	kib
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D57397
2026-06-07 17:48:17 +00:00
Andrew Turner 61d0cea4c0 arm64: Workaround the following errata
- ARM C1-Premium erratum 4193780
 - ARM C1-Ultra erratum 4193780
 - ARM Cortex-A76 erratum 4193800
 - ARM Cortex-A76AE erratum 4193801
 - ARM Cortex-A77 erratum 4193798
 - ARM Cortex-A78 erratum 4193791
 - ARM Cortex-A78AE erratum 4193793
 - ARM Cortex-A78C erratum 4193794
 - ARM Cortex-A710 erratum 4193788
 - ARM Cortex-X1 erratum 4193791
 - ARM Cortex-X1C erratum 4193792
 - ARM Cortex-X2 erratum 4193788
 - ARM Cortex-X3 erratum 4193786
 - ARM Cortex-X4 erratum 4118414
 - ARM Cortex-X925 erratum 4193781
 - ARM Neoverse-N1 erratum 4193800
 - ARM Neoverse-N2 erratum 4193789
 - ARM Neoverse-V1 erratum 4193790
 - ARM Neoverse-V2 erratum 4193787
 - ARM Neoverse-V3 erratum 4193784
 - ARM Neoverse-V3AE erratum 4193784

These are all variants on an erratum where TLBI+DSB instructions on
one CPU may incorrectly complete early leading to stores to an updated
address using an incorrect translation on another CPU.

In all cases the workaround is to add a second TLBI+DSB.

Sponsored by:	Arm Ltd

arm64: Add more CPU MIDR values

Found in Linux and https://github.com/arm-software/data

Sponsored by:	Arm Ltd
Differential Revision:	https://reviews.freebsd.org/D50726

(cherry picked from commit 124b5dbf5c)
(cherry picked from commit 935f00c4dd)

arm64: Add the new C1 CPU IDs

Add the Arm C1-Nano, C1-Pro, C1-Premium, and C1-Ultra CPUs from their
Technical Reference Manuals.

Sponsored by:	Arm Ltd

(cherry picked from commit 8fee6b9ecc)
(cherry picked from commit 25ff471f0b)

Approved by:	so
Security:	FreeBSD-SA-26:31.arm64
Security:	CVE-2025-10263
2026-06-07 17:48:17 +00:00
Mark Johnston 0dcf9bba4b linux: Correct the issetugid check in copyout_auxargs
The runtime linker in glibc relies on the AT_SECURE auxv entry to know
whether the executable is set-ugid, if so then various dangerous
functionality such as LD_PRELOAD is disabled.

The check added in commit 669414e4fb failed to take into account the
fact that during execve, P_SUGID may not yet be set for a set-ugid
process.  Correct the test.

Approved by:	so
Security:	FreeBSD-SA-26:30.linux
Security:	CVE-2026-49413
Reported by:	Minseong Kim
Fixes:		669414e4fb ("Implement AT_SECURE properly.")
Reviewed by:	kib
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D57350
2026-06-07 17:48:17 +00:00
Mark Johnston e6859453de in6_mcast: Fix a race in in6p_set_source_filter()
We drop the inpcb lock in order to copy in the source list, but this
leaves a window where the multicast filter structure might be freed.
This can be exploited to obtain root privileges.

In the v4 code this race is mitigated by holding the global multicast
lock across the gap.

Restructure the code to copy in filters before doing anything else, so
that there's no need to drop the inpcb lock and reason about the
correctness of doing so.  Do the same in the v4 code for consistency.

Approved by:	so
Security:	FreeBSD-SA-26:29.ip6_multicast
Security:	CVE-2026-49412
Reported by:	Andrew Griffiths <[email protected]>
Reported by:	Maik Münch <[email protected]>
Reviewed by:	glebius
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D57347
2026-06-07 17:48:17 +00:00
Ed Maste f56e8cb94d sigqueue: In capability mode, only allow signalling self
This is copied from the check in kern_kill.

Approved by:	so
Security:	FreeBSD-SA-26:28.capsicum
Security:	CVE-2026-45259
Reviewed by:	markj, oshogbo
Sponsored by:	The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D57244

(cherry picked from commit b9d16b7fd2)
(cherry picked from commit defd9b86ef)
(cherry picked from commit d11ff01b3a)
2026-06-07 17:48:17 +00:00
Mark Johnston de5fd56985 sound: Fix software buffer lifetime issues
The channel buffer mapped by dsp_mmap_single() may be freed when the
device handle is closed, but the mapping persists beyond that, allowing
userspace to read or write memory owned by a different consumer.

Fix the problem by adding a reference counter to the sound buffer.
Define pager ops for the VM object returned by dsp_mmap_single() and use
them to manage the extra reference.

Add a regression test.

Approved by:	so
Security:	FreeBSD-SA-26:27.sound
Security:	CVE-2026-49417
Reported by:	Lexpl0it, 75Acol, Liyw979, Rob1n
Reviewed by	kib
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D57393
2026-06-07 17:48:04 +00:00
Christos Margiolis 644ce0e7df sound: Check for offset overflow in dsp_mmap_single()
Approved by:	so
Security:	FreeBSD-SA-26:27.sound
Security:	CVE-2026-45258
Reviewed by:	markj
Sponsored by:	The FreeBSD Foundation
2026-06-07 17:23:12 +00:00
John Baldwin af3398862a ktls: Don't attempt to modify non-anonymous mbufs on the receive path
Normally, data processed on the KTLS receive path is contained in
anonymous mbufs that can be modified in place.  Either the data
originates in receive buffers from a NIC driver, or for loopback
connections the data is anonymous-backed mbufs created when writing to
a socket.  One potential source of non-anonymous mbufs are mbufs
created by sendfile(2) which borrow the pages of the underlying file,
either via M_EXTPG or EXT_SFBUF that are sent over a loopback
connection.  For a well-formed loopback TLS session, the sender should
only use sendfile(2) if KTLS is enabled.  If TLS is fully handled in
userspace, the sender must use write(2) or send(2) which allocate
anonymous mbufs.  If KTLS transmit is enabled, then sendfile(2) on a
loopback connection will always use crypto via OCF and will allocate
anonymous pages to hold the encrypted data.

However, if sendfile(2) is used to send file-backed data directly over
a loopback connection where KTLS is not enabled on the sender side,
the KTLS receive path can modify the file-backed pages in place
overwriting the file's data.  One potential fix would be to replace
non-anonymous mbufs in a received TLS record with anonymous mbufs
(e.g. via m_dup()) before passing the record to OCF.  However, there
is no legitimate use case for using sendfile(2) over a loopback TLS
connection without using KTLS on the sender side, so instead simply
fail decryption requests and close the connection if non-anonymous
mbufs are encountered in the RX decryption path.

Add a test for this that verifies that the original data backing the
file descriptor used as the source for sendfile() is unchanged after
being processed.

Approved by:	so
Security:	FreeBSD-SA-26:26.ktls
Security:	CVE-2026-45257
Co-authored-by:	Drew Gallatin <[email protected]>
Sponsored by:	Chelsio Communications
Sponsored by:	Netflix
2026-06-07 15:53:09 +00:00
Mark Johnston fa5581c379 thr_kill2: Respect p_cansignal()
Approved by:	so
Security:	FreeBSD-SA-26:25.thr
Security:	CVE-2026-45256
Reported by:	Igor Gabriel Sousa e Souza
Reported by:	Yuxiang Yang, Yizhou Zhao, Ao Wang, Xuewei Feng, Qi Li, and Ke Xu from Tsinghua University using GLM-5.1 from Z.ai
Reviewed by:	emaste, kib
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D57237
2026-06-07 15:53:09 +00:00
Enji Cooper d95a8c20f3 crypto/openssl: Update to 3.0.20
This particular change contains all functional and security fixes made
between 3.0.16 and 3.0.20.

OSSL_HTTP_get(): Reset redirection_url in each iteration
(cherry picked from commit 4b286fc6d5)

crypto/openssl: make vendor imports easier/less error prone
(cherry picked from commit d03be8cf33)

crypto/openssl: apply polish to new vendor import process
(cherry picked from commit 79f62601c7)

crypto/openssl: fix importing new versions from pristine trees
(cherry picked from commit 026e3d12ba)

crypto/openssl: remove autogenerated files
(cherry picked from commit 913d1916e3)

OpenSSL: update build artifacts to match 3.0.16 release
(cherry picked from commit aed5a47b3a)

OpenSSL: install .pc files from the exporters subdir
(cherry picked from commit 9a64f277bf)

crypto/openssl: update from 3.0.16 to 3.0.20
(cherry picked from commit 27ac9d336f)

Approved by:	so
Security:	FreeBSD-EN-26:15.openssl
Security:	CVE-2026-2673
Security:	CVE-2026-28387
Security:	CVE-2026-28388
Security:	CVE-2026-28389
Security:	CVE-2026-31789
Security:	CVE-2026-31790
2026-06-07 15:53:08 +00:00
Mark Johnston 6281466c32 Add UPDATING entries and bump version
Approved by:	so
2026-05-20 02:12:20 +00:00
Mariusz Zaborski b3baecf084 cap_net: do not allow new limits to drop keys from the old ones
If the old limit had family/hosts/sockaddr set, the new limit must
have them too. Before, a missing key in the new limit was treated as
"allow any", which let a caller silently extend their limits.

Approved by:	so
Security:	FreeBSD-SA-26:24.cap_net
Security:	CVE-2026-45254
Reported by:	Joshua Rogers of AISLE Research Team
Reviewed by:	markj
MFC after:	1 day
Differential Revision:	https://reviews.freebsd.org/D56991

(cherry picked from commit d705a51952)
(cherry picked from commit b79faca1c5)
2026-05-20 02:12:20 +00:00
Mark Johnston 9cb0be8381 bsdconfig: Make sure that SSID names are properly escaped
The f_menu_wpa_scan_results() function returns a list of networks
discovered by a scan.  The untrusted network names are evaluated in
f_dialog_menu_wireless_edit.  The quoting applied in
f_menu_wpa_scan_results() protects against evaluation of something like
"$(whoami)" but one can add single quotes to defeat that.

Pass the SSID names through f_shell_escape to work around this.  Escape
single quotes in f_dialog_wireless_edit() and f_menu_wireless_configs()
too for consistency.

I note that this module doesn't seem to actually work, see e.g.,
bugzilla PR 229883.

Approved by:	so
Security:	FreeBSD-SA-26:23.bsdinstall
Security:	CVE-2026-45255
Reported by:	Austin Ralls
Reviewed by:	dteske, des
Differential Revision:	https://reviews.freebsd.org/D56974
2026-05-20 02:12:20 +00:00
Renato Botelho 7b80739d12 bsdinstall: Avoid invoking eval on the wlan SSID list
The wlanconfig utility is not careful about handling untrusted network
names, which can contain shell metacharacters.  Factor network selection
into a subroutine and use the `set -- "$@"` trick to build up a list of
positional parameters for bsddialog without evaluating them.

Approved by:	so
Security:	FreeBSD-SA-26:23.bsdinstall
Security:	CVE-2026-45255
Reported by:	Austin Ralls
Reviewed by:	dteske, des, asiciliano
Differential Revision:	https://reviews.freebsd.org/D56973
2026-05-20 02:12:20 +00:00
Mariusz Zaborski cbec318381 libcasper: switch from select(2) to poll(2)
The previous implementation used FD_SET() on a stack-allocated fd_set,
which is an out-of-bounds write whenever the socket fd is >= FD_SETSIZE
(1024).

poll(2) takes an array indexed by slot rather than by fd value, so it
has no FD_SETSIZE limit.

Approved by:	so
Security:	FreeBSD-SA-26:22.libcasper
Security:	CVE-2026-39461
Reported by:    Joshua Rogers
Reviewed by:	markj
Differential Revision:	https://reviews.freebsd.org/D56695
2026-05-20 02:12:20 +00:00
Mark Johnston 45bd421661 ptrace: Fix validation of PT_SC_REMOTE arguments
- Fix an off-by-one in the system call number check.  A value of
  SYS_MAXSYSCALL was permitted.
- Validate the system call number after we've dealt with
  syscall(2)/__syscall(2), since they pass the syscall number as an
  argument.
- When the syscall number is for syscall(2) or __syscall(2), we must
  make sure that nargs > 0 to avoid an underflow when shifting arguments
  down.

Add regression tests.

Approved by:	so
Security:	FreeBSD-SA-26:21.ptrace
Security:	CVE-2026-45253
Fixes:		140ceb5d95 ("ptrace(2): add PT_SC_REMOTE remote syscall request")
Reported by:	Yuxiang Yang, Yizhou Zhao, Ao Wang, Xuewei Feng, Qi Li, and Ke Xu from Tsinghua University using GLM-5.1 from Z.ai
Reviewed by:	kib, emaste
Differential Revision:	https://reviews.freebsd.org/D56978
2026-05-20 02:12:20 +00:00
Alan Somers 53f3bf4ee1 fusefs: Handle buggy servers' LISTXATTR response
The fuse protocol requires server to respond to LISTXATTR with a
NUL-terminated string.  If they don't, report an error rather than
attempt to scan through uninitialized memory for a NUL.

Approved by:	so
Security:	FreeBSD-SA-26:20.fusefs
Security:	CVE-2026-45252
admbugs:	1039
Reported by:	Joshua Rogers
Sponsored by:	ConnectWise
2026-05-20 02:12:20 +00:00
Mark Johnston 659818009d netmap: Drain selinfo sleepers in nm_os_selinfo_uninit()
Approved by:	so
Security:	FreeBSD-SA-26:19.file
Security:	CVE-2026-45251
2026-05-19 23:48:36 +00:00
Mark Johnston c20b3d4a83 procdesc: Make sure to drain selinfo sleepers in procdesc_free()
Otherwise they are left on a freed list after procdesc_free() is called.
This can be exploited to elevate privileges.

Remove the PDF_SELECTED micro-optimization.  doselwakeup() is a no-op if
no one ever called selrecord() on the file description, so I see no
reason to complicate the code to avoid the call.

Add some regression tests.

Approved by:	so
Security:	FreeBSD-SA-26:19.file
Security:	CVE-2026-45251
Reported by:	75Acol, Lexpl0it, fcgboy, and robinzeng2015
Reviewed by:	kib, oshogbo
Fixes:		cfb5f76865 ("Add experimental support for process descriptors")
Differential Revision:	https://reviews.freebsd.org/D56887
2026-05-19 23:48:36 +00:00
Dag-Erling Smørgrav bfff5c1801 setcred: Fix buffer overflow
Since groups is a pointer to a pointer to an array of gid_t, we should
use sizeof(**groups) or sizeof(gid_t) when calculating how much to
allocate and copy in.  We were using sizeof(*groups) instead, which
meant that on 64-bit platforms, we would allocate and copy in twice as
much as we should.  Unfortunately, in the smallgroups case, we copy
into a preallocated buffer which has the correct size, which means that
if sc_supp_groups_nb >= CRED_SMALLGROUPS_NB / 2, we overflow smallgroups.

This is a direct commit to stable/14.

Approved by:	so
Security:	FreeBSD-SA-26:18.setcred
Reported by:	Ryan of Calif.io
Fixes:		ddb3eb4efe ("New setcred() system call and associated MAC hooks")
2026-05-19 23:48:36 +00:00
Dag-Erling Smørgrav a1b3818746 freebsd-update: Skip /etc/ssl/cert.pem
We already run `certctl rehash` at the end, there is no point in asking
users upgrading from 15.0 to 15.1 to manually merge the trust store.

Approved by:	so
Security:	FreeBSD-EN-26:13.freebsd-update
MFC after:	3 days
Reviewed by:	cperciva
Differential Revision:	https://reviews.freebsd.org/D57028

(cherry picked from commit 2509ddee9b)
(cherry picked from commit 7d9c1d3895)
2026-05-19 23:48:36 +00:00
Mark Johnston 4f4b48e8a5 Add UPDATING entries and bump version
Approved by:	so
2026-04-30 21:21:34 +00:00
Dag-Erling Smørgrav 5bad905eb3 dhclient: Improve server and filename validation
* Don't iterate over each string three times; once is enough.

* Reject control characters (anything below space) in addition to the
  double quote and backslash.

* If an unsafe character is encountered, discard the string instead of
  rejecting the entire lease.

* If backslashes are encountered in the file name option, convert them
  to forward slashes instead of rejecting the option.

* Tweak the warning messages a bit.  Looking through the rest of the
  code, it seems to me that notes generally end with a period while
  warnings generally don't.

Approved by:	so
Security:	FreeBSD-EN-26:11.dhclient
Fixes:		8008e4b88d ("dhclient: Check for unexpected characters in some DHCP server options")
PR:		294886
MFC after:	1 week
Reviewed by:	brooks, markj
Differential Revision:	https://reviews.freebsd.org/D56740

(cherry picked from commit 873a195ba6)
(cherry picked from commit 2f9478ad42)
2026-04-30 21:21:27 +00:00
Mark Johnston 31900fbe28 Add UPDATING entries and bump version
Approved by:	so
2026-04-28 20:33:05 +00:00
Mariusz Zaborski aa15809f85 libnv: fix heap overflow in nvlist_recv()
nvlist_check_header() validated nvlh_size for overflow before
performing conversion. An mallicous user can set
NV_FLAG_BIG_ENDIAN in the header and craft nvlh_size so that
the orginall value passes the check, but after the conversion the
sizeof(nvlist_header) + size can overflow.
This can lead to a heap buffer overflow.

Approved by:	so
Security:	FreeBSD-SA-26:17.libnv
Security:	CVE-2026-35547
Fixes:		36fa90dbde
Reviewed by:	markj
Differential Revision:	https://reviews.freebsd.org/D56342
2026-04-28 20:33:04 +00:00
Mariusz Zaborski a872c32f38 libnv: switch fd_wait() from select(2) to poll(2)
The previous implementation used FD_SET() on a stack-allocated fd_set,
which is an out-of-bounds write whenever the socket fd is >= FD_SETSIZE
(1024).

Approved by:	so
Security:	FreeBSD-SA-26:16.libnv
Security:	CVE-2026-39457
Reported by:	Joshua Rogers of AISLE Research Team (https://aisle.com/)
Reviewed by:	markj
Differential Revision:	https://reviews.freebsd.org/D56689
2026-04-28 20:33:04 +00:00
Mariusz Zaborski 0963be1dbf libnv: add tests to verify potential overflow issues
Approved by:	so
Differential Revision:  https://reviews.freebsd.org/D46131

(cherry picked from commit 241a7ddd71)
2026-04-28 20:33:04 +00:00
Mariusz Zaborski bba29d772b libnv: add test to verify null termination of string in array
Approved by:	so
Differential Revision:  https://reviews.freebsd.org/D46138

(cherry picked from commit 2981431e04)
2026-04-28 20:33:04 +00:00
Mark Johnston 76734958a0 dhclient: Fix reallocation of dhclient script environments
When the number of DHCP options exceeds a threshold, script_set_env()
will reallocate the environment, stored as an array of pointers.  The
calculation of the array size failed to multiply by the pointer size,
resulting in a smaller than expected buffer which admits out-of-bounds
writes.

Approved by:	so
Security:	FreeBSD-SA-26:15.dhclient
Security:	CVE-2026-42511
Reported by:	Joshua Rogers of AISLE Research Team (https://aisle.com/)
2026-04-28 20:33:04 +00:00
Mark Johnston dda71167a1 dhclient: Check for unexpected characters in some DHCP server options
Some options are written directly to the lease file, which may be parsed
by subsequent dhclient invocations.  We must make sure that a malicious
server can't control the "medium" field of a lease definition, otherwise
they can achieve RCE by injecting one into the lease file, whereupon it
will be passed to dhclient-script, which passes it through eval.

Approved by:	so
Security:	FreeBSD-SA-26:12.dhclient
Security:	CVE-2026-42511
Reported by:	Joshua Rogers of AISLE Research Team (https://aisle.com/)
2026-04-28 20:33:04 +00:00
Mark Johnston f04c40607b execve: Fix an operator precedence bug
The buggy version allowed userspace to overflow the copy into adjacent
execve KVA regions, which enables, among other things, injecting
environment variables into privileged processes.

Approved by:	so
Security:	FreeBSD-SA-26:13.exec
Security:	CVE-2026-7270
Reported by:	Ryan Austin of Calif.io
Reviewed by:	brooks, kib
Fixes:		f373437a01 ("Add helper functions to copy strings into struct image_args.")
Differential Revision:	https://reviews.freebsd.org/D56665
2026-04-28 20:33:04 +00:00
Kristof Provost 63495b09cc pf: improve SCTP validation
As per RFC5061 "4.2.  New Parameter Types" the add/delete IP address
parameters (0xc001, 0xc002) may not be present in an INIT or INIT-ACK
chunk. They are only allowed to be present in an ASCONF chunk.

This also prevents unbounded recursion while parsing an SCTP packet.

Approved by:	so
Security:	FreeBSD-SA-26:14.pf
Security:	CVE-2026-7164
PR:		294799
Reported by:	Igor Gabriel Sousa e Souza
Sponsored by:	Orange Business Services
2026-04-28 20:33:04 +00:00
Kyle Evans 3b1365cb81 amd64: fix INVLPGB range invalidation
AMD64 Architecture Programmer's Manual Volume 3 says the following:

> ECX[15:0] contains a count of the number of sequential pages to
> invalidate in addition to the original virtual address, starting from
> the virtual address specified in rAX. A count of 0 invalidates a
> single page. ECX[31]=0 indicates to increment the virtual address at
> the 4K boundary. ECX[31]=1 indicates to increment the virtual address
> at the 2M boundary. The maximum count supported is reported in
> CPUID function 8000_0008h, EDX[15:0].

ECX[31] being what we call INVLPGB_2M_CNT, signaling to increment the
VA by 2M.

> This instruction invalidates the TLB entry or entries, regardless of
> the page size (4 Kbytes, 2 Mbytes, 4 Mbytes, or 1 Gbyte). [...]

Combined with this, my interpretation of the current code is: if
<va> is aligned on a PDE boundary, we'll use INVLPGB_2M_CNT to try and
invalidate <cnt> PDEs with a single call, but that only works if <va> is
the start of at least <cnt> 2M pages.  Otherwise, if <va> or any of the
subsequent PDEs isn't actually a superpage, then we would actually only
invalidate the *first* page within the PDE before skipping to the next
PDE, leaving the remainder of the 4K pages in between as they were.

The implication would seem to be that we would need to inspect the range
that we're trying to invalidate if we're planning on using
INVLPGB_2M_CNT at all, so this patch just simplifies it to a series of
4K invalidations.  My gut feeling is that we likely still come out on
top vs. the TLB shootdown we're avoiding.

This seems to explain some issues we've seen lately with fdgrowtable()
and kqueue on recent Zen4/Zen5 EPYC hardware, where we'd experience
corruption that we can't explain.

Approved by:	so
Security:	FreeBSD-EN-26:10.amd64
PR:		293382
Reviewed by:	alc, kib, markj

(cherry picked from commit 1b8e5c02f5)
(cherry picked from commit ff11ae166c)
2026-04-28 20:33:04 +00:00
Philip Paeps 1d3ca32f88 contrib/tzdata: import tzdata 2025c, 2026a and 2026b
Changes: https://github.com/eggert/tz/blob/2025c/NEWS
Changes: https://github.com/eggert/tz/blob/2026a/NEWS
Changes: https://github.com/eggert/tz/blob/2026b/NEWS

Approved by:	so
Security:	FreeBSD-EN-26:09.tzdata

(cherry picked from commit a86dc94b84)
(cherry picked from commit 68e2f4cc5e)
(cherry picked from commit 6becc3dff9)
(cherry picked from commit 4830cb713e)
(cherry picked from commit 9b95cab0a2)
(cherry picked from commit 30eb33424e)
2026-04-28 20:33:04 +00:00
Mark Johnston 0224acf7f7 Add UPDATING entries and bump version
Approved by:	so
2026-04-21 15:45:50 +00:00
Mark Johnston 979e645dd2 pkru: Fix handling of 1GB largepage mappings
pmap_pkru_update_range() did not handle the case where a PDPE has PG_PS
set.  More generally, the SET_PKRU and CLEAR_PKRU sysarch
implementations did not check whether the request covers a "boundary" vm
map entry.  Fix this, add the missing PG_PS test, and add some tests.

Approved by:	so
Security:	FreeBSD-SA-26:11.amd64
Security:	CVE-2026-6386
Reported by:	Nicholas Carlini <[email protected]>
Reviewed by:	kib, alc
Differential Revision:	https://reviews.freebsd.org/D56184
2026-04-21 15:45:50 +00:00
Mark Johnston 44077c07f1 tty: Avoid leaving dangling pointers in tty_drop_ctty()
The TIOCNOTTY handler detaches the calling process from its controlling
terminal.  It clears the link from the session to the tty, but not the
pointers from the tty to the session and process group.  This means that
sess_release() doesn't call tty_rel_sess(), and that pgdelete() doesn't
call tty_rel_pgrp(), so the pointers are left dangling.

Fix this by clearing pointers in tty_drop_ctty().  Add a standalone
regression test.

Approved by:	so
Security:	FreeBSD-SA-26:10.tty
Security:	CVE-2026-5398
Reported by:	Nicholas Carlini <[email protected]>
Reviewed by:	kib, kevans
Fixes:		1b50b999f9 ("tty: implement TIOCNOTTY")
Differential Revision:	https://reviews.freebsd.org/D56046
2026-04-21 15:45:50 +00:00
Jake Freeland f37c6e3a13 timerfd: Fix interval callout scheduling
When a timerfd interval callout misses its scheduled activation time, a
differential is calculated based on the actual activation time and the
scheduled activation time. This differential is divided by the timerfd's
interval time and the quotient is added to the timerfd's counter.

Before this change, the next callout was scheduled to activate at:
scheduled activation time + timerfd interval.

This change fixes the scheduling of the next callout to activate at:
actual activation time + timerfd interval - remainder.

Security:		FreeBSD-26:06.timerfd
Approved by:		so
Reviewed by:		markj
Differential Revision:	https://reviews.freebsd.org/D55790
MFC after:		2 weeks

(cherry picked from commit 85c0f1a87d)
(cherry picked from commit 3c00f603a2)
2026-04-21 15:45:50 +00:00
Mark Johnston 4d22b3925d vm_fault: Reset m_needs_zeroing properly
- When allocating a page, we should only consider the PG_ZERO flag when
  handling the top-level page.
- Unconditionally reset the flag when restarting the fault handler.
  Previously, vm_fault_busy_sleep() would fail to reset it.

Approved by:	so
Security:	FreeBSD-EN-26:05.vm
PR:		294039
Reviewed by:	kib
Tested by:	Peter Much <[email protected]>
MFC after:	3 days
Fixes:		cff67bc43d ("vm_fault: only rely on PG_ZERO when the page was newly allocated")
Differential Revision:	https://reviews.freebsd.org/D56234

(cherry picked from commit 04132e0100)
(cherry picked from commit 9b7c0f4f81)
2026-04-21 15:45:46 +00:00
Philip Paeps 2321f541c3 Add UPDATING entries and bump version
Approved by:	so
2026-03-26 00:13:44 +08:00
Kristof Provost c03577d99d pf: include all elements when hashing rules
Approved by:	so
Security:	FreeBSD-SA-26:09.pf
Security:	CVE-2026-4748
Sponsored by:	Rubicon Communications, LLC ("Netgate")

(cherry picked from commit c6bcf6e6fd)
(cherry picked from commit e3b801edde)
2026-03-26 00:13:40 +08:00
Kristof Provost 926ee630b7 pfctl: always warn if a duplicate rule was detected
Approved by:	so
Security:	FreeBSD-SA-26:09.pf
Security:	CVE-2026-4748
Sponsored by:	Rubicon Communications, LLC ("Netgate")

(cherry picked from commit 66d66dd0f6)
(cherry picked from commit e79818ec36)
2026-03-26 00:13:37 +08:00
Kristof Provost 89ab511c1c pf tests: verify that we handle address range rules correctly
There's been a problem where rules which differed only in address ranges
were considered duplicates and not added. Test for this.

Approved by:	so
Security:	FreeBSD-SA-26:09.pf
Security:	CVE-2026-4748
Sponsored by:	Rubicon Communications, LLC ("Netgate")

(cherry picked from commit ab74151e8d)
(cherry picked from commit 958dbc87e9)
2026-03-26 00:13:33 +08:00
Michael Gmelin d3c0dff16c pf: Fix hashing of IP address ranges
This corrects the false detection of duplicate rules.

Approved by:	so
Security:	FreeBSD-SA-26:09.pf
Security:	CVE-2026-4748
Reviewed by:	kp

(cherry picked from commit 1fa873c93c)
(cherry picked from commit ac6bb58a71)
2026-03-26 00:13:06 +08:00
Mark Johnston b6ce88ab9a rpcsec_gss: Fix a stack overflow in svc_rpc_gss_validate()
svc_rpc_gss_validate() copies the input message into a stack buffer
without ensuring that the buffer is large enough.  Sure enough,
oa_length may be up to 400 bytes, much larger than the provided space.
This enables an unauthenticated user to trigger an overflow and obtain
remote code execution.

Add a runtime check which verifies that the copy won't overflow.

Approved by:	so
Security:	FreeBSD-SA-26:08.rpcsec_gss
Security:	CVE-2026-4747
Reported by:	Nicholas Carlini <[email protected]>
Reviewed by:	rmacklem
Fixes:		a9148abd9d
2026-03-25 14:56:34 +08:00
Michael Tuexen a9cba53210 tcp: plug an mbuf leak
When a challenge ACK should be sent via tcp_send_challenge_ack(),
but the rate limiter suppresses the sending, free the mbuf chain.
The caller of tcp_send_challenge_ack() expects this similar to the
callers of tcp_respond().

Approved by:	so
Security:	FreeBSD-SA-26:06.tcp
Security:       CVE-2026-4247
Reviewed by:	lstewart
Tested by:	lstewart
Sponsored by:	Netflix, Inc.
2026-03-25 14:56:19 +08:00
Mark Johnston 24c55170ce Add UPDATING entries and bump version
Approved by:	so
2026-02-24 15:56:57 +00:00
Mark Johnston d521badafd rtsock: Fix stack overflow
Approved by:	so
Security:	FreeBSD-SA-26:05.route
Security:	CVE-2026-3038
Fixes:		92be2847e8 ("rtsock: Avoid copying uninitialized padding bytes")

(cherry picked from commit cd00cd9f6ed4b6f6e6bb8ae168f2537968991b53)
(cherry picked from commit f44d771c2c6c80f3fabd11d335964e1efdf50a21)
2026-02-23 16:39:30 +00:00
Mark Johnston 3a495a08e9 amd64/conf: Remove a config committed by accident
Approved by:	so
Reported by:	kib, kp
Fixes:		350ba9672a ("unix: Set O_RESOLVE_BENEATH on fds transferred between jails")

(cherry picked from commit 3ef39f58e5)
(cherry picked from commit 302120bcb9)
2026-02-23 16:00:13 +00:00
Mark Johnston 32ff24bd70 unix/tests: Add a regression test for fd transfer across jails
Approved by:	so
MFC after:	3 weeks

(cherry picked from commit 5843b8ee02)
(cherry picked from commit ac2279ea57)
2026-02-23 16:00:13 +00:00
Mark Johnston fbc35b3e66 unix: Set O_RESOLVE_BENEATH on fds transferred between jails
If a pair of jails with different filesystem roots is able to exchange
SCM_RIGHTS messages (e.g., using a unix socket in a shared nullfs
mount), a process in one jail can open a directory outside of the root
of the second jail and then pass the fd to that second jail, allowing
the receiving process to escape the jail chroot.

Address this using the new FD_RESOLVE_BENEATH flag.  When externalizing
an SCM_RIGHTS message into the receiving process, automatically set this
flag on all new fds where a jail boundary is crossed.  This ensures that
the receiver cannot do more than access files underneath the directory;
in particular, the received fd cannot be used to access vnodes not
accessible by the sender.

Approved by:	so
Security:	FreeBSD-SA-26:04.jail
Security:	CVE-2025-15576
PR:		262179
Reviewed by:	kib
MFC after:	3 weeks
Differential Revision:	https://reviews.freebsd.org/D50371

(cherry picked from commit 350ba9672a)
(cherry picked from commit 3ad3ab5f9b)
2026-02-23 16:00:13 +00:00
Mark Johnston c52fe2c45e file: Fix the !CAPABILITIES build
Approved by:	so
Reported by:	Ian FREISLICH <[email protected]>
Fixes:	f35525ff20 ("file: Add a fd flag with O_RESOLVE_BENEATH semantics")

(cherry picked from commit 6783dfb106)
(cherry picked from commit 8f6769b82a)
2026-02-23 16:00:13 +00:00
Mark Johnston aaa0c2247f file: Add a fd flag with O_RESOLVE_BENEATH semantics
The O_RESOLVE_BENEATH openat(2) flag restricts name lookups such that
they remain under the directory referenced by the dirfd.  This commit
introduces an implicit version of the flag, FD_RESOLVE_BENEATH, stored
in the file descriptor entry.  When the flag is set, any lookup relative
to that fd automatically has O_RESOLVE_BENEATH semantics.  Furthermore,
the flag is sticky, meaning that it cannot be cleared, and it is copied
by dup() and openat().

File descriptors with FD_RESOLVE_BENEATH set may not be passed to
fchdir(2) or fchroot(2).  Various fd lookup routines are modified to
return fd flags to the caller.

This flag will be used to address a case where jails with different root
directories and the ability to pass SCM_RIGHTS messages across the jail
boundary can transfer directory fds in such as way as to allow a
filesystem escape.

Approved by:	so
PR:		262180
Reviewed by:	kib
MFC after:	3 weeks
Differential Revision:	https://reviews.freebsd.org/D50371

(cherry picked from commit f35525ff20)
(cherry picked from commit 10b3f21385)
2026-02-23 16:00:13 +00:00
Mark Johnston fa55264588 file: Qualify pointers to capsicum rights as const
File descriptor lookup routines typically take a set of capsicum rights
as input to the lookup, so that the fd's rights can be atomically
checked.  This set should be qualified with const.

No functional change intended.

Approved by:	so
Reviewed by:	olce, oshogbo, brooks, kib
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D50419

(cherry picked from commit 5319cb2161)
(cherry picked from commit 2060337c09)
2026-02-09 22:01:24 +00:00
Mark Johnston 2e63e671a9 Add UPDATING entries and bump patch version
Approved by:	so
2026-01-26 20:41:17 +00:00
Gordon Tetlow 65c1295c6b openssl: Fix multiple vulnerabilities
This is a rollup commit from upstream to fix:
  Stack buffer overflow in CMS AuthEnvelopedData parsing (CVE-2025-15467)
  Heap out-of-bounds write in BIO_f_linebuffer on short writes (CVE-2025-68160)
  Unauthenticated/unencrypted trailing bytes with low-level OCB function calls (CVE-2025-69418)
  Out of bounds write in PKCS12_get_friendlyname() UTF-8 conversion (CVE-2025-69419)
  Missing ASN1_TYPE validation in TS_RESP_verify_response() function (CVE-2025-69420)
  NULL Pointer Dereference in PKCS12_item_decrypt_d2i_ex function (CVE-2025-69421)
  Missing ASN1_TYPE validation in PKCS#12 parsing (CVE-2026-22795)
  ASN1_TYPE Type Confusion in the PKCS7_digest_from_attributes() function (CVE-2026-22796)

See https://openssl-library.org/news/secadv/ for additional details.

Approved by:	so
Obtained from:	OpenSSL
Security:	FreeBSD-SA-26:01.openssl
Security:	CVE-2025-15467
Security:	CVE-2025-68160
Security:	CVE-2025-69418
Security:	CVE-2025-69419
Security:	CVE-2025-69420
Security:	CVE-2025-69421
Security:	CVE-2026-22795
Security:	CVE-2026-22796
2026-01-26 19:00:43 +00:00
Mark Johnston 403702f9ce tests: Add a regression test for commit 7587f6d484
Approved by:	so
Reviewed by:	kib
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D50533

(cherry picked from commit a5dac34f6e)
(cherry picked from commit f56b66f126)
2026-01-26 16:49:29 +00:00
Konstantin Belousov 59b6d076b4 namei: clear internal flags in NDREINIT()
same as it is done for NDRESTART()

Approved by:	so
Fixes:  e05e33041c
Reported and tested by:	pho
Reviewed by:	markj
Sponsored by:	The FreeBSD Foundation

(cherry picked from commit 58b2bd33af)
(cherry picked from commit 53963866f7)
2026-01-26 16:49:29 +00:00
Mark Johnston e89e04ee27 vfs: Don't clobber namei flags in vn_open_cred()
Otherwise NAMEILOOKUP is cleared.  More generally it seems quite
surprising that the flags set by vn_open_cred() callers are not
automatically preserved.  Modify open2nameif() such that it takes
already-set namei flags into account.

Approved by:	so
Reviewed by:	olce, kib
Fixes:		7587f6d484 ("namei: Make stackable filesystems check harder for jail roots")
Differential Revision:	https://reviews.freebsd.org/D50531

(cherry picked from commit e05e33041c)
(cherry picked from commit a667678446)
2026-01-26 16:49:29 +00:00
Mark Johnston 0316d0a247 vfs cache: Add NAMEILOOKUP to the whitelist of fastpath lookup flags
Otherwise the lockless name lookup path is inadvertently disabled since
NAMEILOOKUP isn't recognized.

Approved by:	so
Reviewed by:	olce, kib
Fixes:		7587f6d484 ("namei: Make stackable filesystems check harder for jail roots")
Differential Revision:	https://reviews.freebsd.org/D50532

(cherry picked from commit f415895300)
(cherry picked from commit 031cd54877)
2026-01-26 16:49:29 +00:00
Mark Johnston 24628cf3df namei: Remove a now-unused variable
Approved by:	so
Reported by:	bapt
Fixes:		7587f6d484 ("namei: Make stackable filesystems check harder for jail roots")

(cherry picked from commit 14ec281a09)
(cherry picked from commit 3f4efe392b)
2026-01-26 16:49:29 +00:00
Mark Johnston 193ae464aa namei: Make stackable filesystems check harder for jail roots
Suppose a process has its cwd pointing to a nullfs directory, where the
lower directory is also visible in the jail's filesystem namespace.
Suppose that the lower directory vnode is moved out from under the
nullfs mount.  The nullfs vnode still shadows the lower vnode, and
dotdot lookups relative to that directory will instantiate new nullfs
vnodes outside of the nullfs mountpoint, effectively shadowing the lower
filesystem.

This phenomenon can be abused to escape a chroot, since the nullfs
vnodes instantiated by these dotdot lookups defeat the root vnode check
in vfs_lookup(), which uses vnode pointer equality to test for the
process root.

Fix this by extending nullfs and unionfs to perform the same check,
exploiting the fact that the passed componentname is embedded in a
nameidata structure to avoid changing the VOP_LOOKUP interface.  That
is, add a flag to indicate that containerof can be used to get the full
nameidata structure, and perform the root vnode check on the lower vnode
when performing a dotdot lookup.

Approved by:	so
Security:	FreeBSD-SA-26:02.jail
Security:	CVE-2025-15547
PR:		262180
Reviewed by:	olce, kib
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D50418

(cherry picked from commit 7587f6d484)
(cherry picked from commit 3feafab4a3)
2026-01-26 16:49:29 +00:00
Konstantin Belousov 5970c36e60 nullfs lookup: cn_flags is 64bit
Approved by:	so

(cherry picked from commit 89549c2348)
(cherry picked from commit 2013ad7490)
2026-01-26 16:49:29 +00:00
Konstantin Belousov 2bbc6677c6 vm_fault: only rely on PG_ZERO when the page was newly allocated
Approved by:	so
Security:	FreeBSD-EN-26:03.vm

(cherry picked from commit cff67bc43d)
(cherry picked from commit 99f641267d)
2026-01-26 16:49:26 +00:00
Konstantin Belousov de311ee39b vm_object_page_remove(): clear pager even if there is no resident pages
Approved by:	so
Security:	FreeBSD-EN-26:03.vm

(cherry picked from commit 72a447d0bc)
(cherry picked from commit feac4c32a5)
2026-01-26 16:49:23 +00:00
Andrew Turner 3ba856f715 arm64: Correctly align the SVE signal context
The SVE signal context needs to be correctly aligned. Fix this by
creating a new macro to calculate the needed size to provide this
alignment, and use it when setting and checking the saved SVE signal
context.

Approved by:	so
Security:	FreeBSD-EN-26:02.arm64
Reported by:	cperciva
Reviewed by:	cperciva, markj
Sponsored by:	Arm Ltd
Differential Revision:	https://reviews.freebsd.org/D54396

(cherry picked from commit a9e77eb701)
(cherry picked from commit bcd6bb8067)
2026-01-26 16:47:27 +00:00
Mark Johnston 8b2a912a8a Add UPDATING entries and bump version.
Approved by:	so
2025-12-16 23:41:08 +00:00
Mark Johnston 3c54b204bf rtsold: Validate entries in domain search lists
Reported by:	Kevin Day <[email protected]>
Approved by:	so
Security:	FreeBSD-SA-25:12.rtsold
Security:	CVE-2025-14558
2025-12-16 23:41:02 +00:00
Kyle Evans c0cb68169b ipfw: pmod: avoid further rule processing after tcp-mod failures
m_pullup() here will have freed the mbuf chain, but we pass back an
IP_FW_DENY without any signal that the outer loop should finish.  Thus,
rule processing continues without an mbuf and there's a chance that we
conclude that the packet may pass (but there's no mbuf remaining)
depending on the rules that follow it.

PR:		284606
Reviewed by:	ae
Approved by:	so
Security:	FreeBSD-SA-25:11.ipfw
Security:	CVE-2025-14769

(cherry picked from commit c0382512bf)
(cherry picked from commit deb684f9d1)
2025-12-16 13:57:34 +00:00
Gordon Tetlow 476b20984a Add UPDATING entries and bump version.
Approved by:	so
2025-11-26 08:12:27 -08:00
Gordon Tetlow 18c4eb2cc6 Add a fix to scrub unsolicited NS RRSets to prevent cache poisoning.
Approved by:	so
Obtained from:	NLnet Labs
Security:	FreeBSD-SA-25:10.unbound
Security:	CVE-2025-11411
2025-11-26 08:08:04 -08:00
Mark Johnston 382f54740e Add UPDATING entries and bump version
Approved by:	so
2025-10-22 15:51:48 +00:00
Mark Johnston 65f6f823c5 so_reuseport_lb_test: Add a test case for connected UDP sockets
Approved by:	so

(cherry picked from commit 1dd66c6ac2)
(cherry picked from commit 7272e2d029)
2025-10-22 15:51:38 +00:00
Mark Johnston 058bcb57cd inpcb: Ignore SO_REUSEPORT_LB on connected sockets
While TCP disallows connect()ing a socket with SO_REUSEPORT_LB, UDP does
not.  As a result, a connected UDP socket can be placed in the lbgroup
hash and thus receive datagrams from sources other than the connected
host.

Reported by:	Amit Klein <[email protected]>
Reported by:	Omer Ben Simhon <[email protected]>
Reviewed by:	glebius
Approved by:	so
Security:	FreeBSD-SA-25:09.netinet
Security:	CVE-2025-24934

(cherry picked from commit 320ad3dec5)
(cherry picked from commit e276759b36)
2025-10-22 15:50:47 +00:00
Gordon Tetlow 7f1785f09f Add UPDATING entries and bump version.
Approved by:	so
2025-09-30 08:35:49 -07:00
Gordon Tetlow 75d258af9f Fix multiple security issues in OpenSSL.
Out-of-bounds read & write in RFC 3211 KEK Unwrap (CVE-2025-9230)
Out-of-bounds read in HTTP client no_proxy handling (CVE-2025-9232)

Obtained from:	OpenSSL
Approved by:	so
Security:	FreeBSD-SA-25:08.openssl
Security:	CVE-2025-9230
Security:	CVE-2025-9232

(cherry picked from commit 270158508d)
2025-09-30 08:31:43 -07:00
Colin Percival 978e04ff5b freebsd-update: Library ordering
Upgrading from 14.x to 15.x with freebsd-update broke because libc
depends on the new libsys library; freebsd-update installed the new
libc before creating libsys, and every step after that failed because
all the tools (including gunzip and install) are dynamically linked
and need a working libc.

Enforce ordering when installing shared objects: First libsys, then
libc, then libthr, and then all the rest of the shared object files.

This is a candidate for an Errata Notice since the issue this fixes
breaks upgrades.

PR:		289769
Reported by:	Graham Perrin
Reviewed by:	kib
MFC after:	3 days
Sponsored by:	https://www.patreon.com/cperciva
Differential Revision:	https://reviews.freebsd.org/D52688
Approved by:	so
Security:	FreeBSD-EN-25:18.freebsd-update

(cherry picked from commit 7ece602e00)
(cherry picked from commit e26928669f)
2025-09-29 21:57:23 -07:00
Gordon Tetlow 30ad842dd9 Correct release patch information.
Pointy hat to:	gordon
Approved by:	so
2025-09-16 16:10:20 -07:00
Gordon Tetlow ed55d0f2bc Add UPDATING entries and bump version.
Approved by:    so
2025-09-16 09:28:47 -07:00
Kevin Bowling c07b1838f9 bnxt: Fix BASE-T, 40G AOC, 1G-CX, autoneg and unknown media lists
This was broken in c63d67e137, the early returns prevent building the
media lists as expected.

The BASE-T parts of the patch were suggested by "[email protected]", while I
am adding the additional 40G AOC, 1CX, autoneg and unknown PHY fixes
based on code inspection.  There may be additional work left here for
Broadcom but this is certainly better than the returns.

PR:		287395

Reported by:	[email protected], [email protected]
Tested by:	Einar Bjarni Halldórsson <[email protected]>
Approved by:	so
Security:	FreeBSD-EN-25:17.bnxt

(cherry picked from commit 5e6e4f7528)
(cherry picked from commit 33f65f12eb)
2025-09-13 17:24:43 -07:00
Rick Macklem d1e981cbf3 vfs_syscalls.c: Fix handling of offset args for copy_file_range
Commit 197997a broke handling of the offset
arguments to copy_file_range() when specified non-NULL.
The code fails to update the offsets and, as such, a loop like:

do {

   len = copy_file_range(infd, &inpos, outfd, &outpos,
      SSIZE_MAX, 0);
} while (len > 0);

becomes an infinite loop, just doing the same copy over and
over again.

This patch fixes it.

The clause "(foffsets_locked || foffsets_set)" in the if is not
actually needed for correctness, but I thought it made the code
a little more readable and might avoid some static
analyzer from throwing a "used before being set" for
the savinoff and savoutoff variables.

Approved by:	so
Security:	FreeBSD-EN-25:16.vfs

(cherry picked from commit 4046ad6bb0)
(cherry picked from commit 2fd0083fcc)
2025-09-13 17:23:36 -07:00
John-Mark Gurney 99012995b4 arm64: prevent panic when using syscall mux + large arg call (mmap)
if the syscall muxes are used, up to two additional arguments
may be required.  This means that the 8 required for mmap increases
up to 10 (for __syscall).

Sponsored by:   Juniper Networks, Inc.
Approved by:	so
Security:	FreeBSD-EN-25:15.arm64

(cherry picked from commit 740b879c6a)
(cherry picked from commit 17d87881a3)
2025-09-13 17:20:46 -07:00
Gordon Tetlow 5982521fe3 Add UPDATING entries and bump version.
Approved by:	so
2025-08-07 17:15:39 -07:00
Martin Matuska fb780a82df libarchive: merge from vendor branch
libarchive 3.8.1

New features:
 #2088 7-zip reader: improve self-extracting archive detection
 #2137 zip writer: added XZ, LZMA, ZSTD and BZIP2 support
 #2403 zip writer: added LZMA + RISCV BCJ filter
 #2601 bsdtar: support --mtime and --clamp-mtime
 #2602 libarchive: mbedtls 3.x compatibility

Security fixes:
 #2422 tar reader: Handle truncation in the middle of a GNU long linkname
       (CVE-2024-57970)
 #2532 tar reader: fix unchecked return value in list_item_verbose()
       (CVE-2025-25724)
 #2532 unzip: fix null pointer dereference (CVE-2025-1632)
 #2568 warc: prevent signed integer overflow (CVE-2025-5916)
 #2584 rar: do not skip past EOF while reading (CVE-2025-5918)
 #2588 tar: fix overflow in build_ustar_entry (CVE-2025-5917)
 #2598 rar: fix double free with over 4 billion nodes (CVE-2025-5914)
 #2599 rar: fix heap-buffer-overflow (CVE-2025-5915)

Important bugfixes:
 #2399 7-zip reader: add SPARC filter support for non-LZMA compressors
 #2405 tar reader: ignore ustar size when pax size is present
 #2435 tar writer: fix bug when -s/a/b/ used more than once with b flag
 #2459 7-zip reader: add POWERPC filter support for non-LZMA compressors
 #2519 libarchive: handle ARCHIVE_FILTER_LZOP in archive_read_append_filter
 #2539 libarchive: add missing seeker function to archive_read_open_FILE()
 #2544 gzip: allow setting the original filename for gzip compressed files
 #2564 libarchive: improve lseek handling
 #2582 rar: support large headers on 32 bit systems
 #2587 bsdtar: don't hardlink negative inode files together
 #2596 rar: support large headers on 32 bit systems
 #2606 libarchive: support @-prefixed Unix epoch timestamps as date strings
 #2634 tar: Support negative time values with pax
 #2637 tar: Keep block alignment after pax error
 #2642 libarchive: fix FILE_skip regression
 #2643 tar: Handle extra bytes after sparse entries
 #2649 compress: Prevent call stack overflow
 #2651 iso9660: always check archive_string_ensure return value

CVE:		CVE-2024-57970, CVE-2025-1632, CVE-2025-25724,
		CVE-2025-5914, CVE-2025-5915, CVE-2025-5916,
		CVE-2025-5917, CVE-2025-5918
PR:		286944 (exp-run, main, libarchive 3.8.0)
Approved by:	so
Security:	FreeBSD-SA-25:07.libarchive

(cherry picked from commit 2e113ef824)
(cherry picked from commit 6dad4525a2)
2025-08-07 16:57:20 -07:00
Oleg Streejak 97f34921d7 route: fix route -n monitor when its output is redirected
This is a small oversight in the transition to netlink; the non-netlink
implementation would explicitly flush its stdout as necessary to avoid
apparent long stalls in output when we end up fully-buffered.  Adjust
the netlink implementation to do the same.  This was noticed while
trying to triage failures in the wg-quick script.

Commit message by kevans, patch by author.

PR:		278265
Fixes:		091fec1188 ("route: switch transport protocol [...]")
Approved by:	so
Security:	FreeBSD-EN-25:14.route

(cherry picked from commit 97b61b22ed)
(cherry picked from commit dd695839ef)
2025-08-07 16:22:27 -07:00
Adrian Chadd a3bd81ddfe net80211: fix TKIP trailer trimming w/ no rx parameters given
Previous work made trimming the TKIP trailer an optional thing
based on what the driver indicated it did with the received
frame.  However, for drivers that aren't populating an RX frame
with an rx status - notably iwn(4) - exposed this bug.

If the driver doesn't expose any RX status then just restore
the previous behaviour.

This matches what was done in the CCMP code in ccmp_decap().

Locally tested:

* iwn(4), STA mode, CCMP + TKIP groupwise network

Differential Revision:	https://reviews.freebsd.org/D50638
Fixes:	731ff40069
Reviewed by:	bz
Approved by:	so
Security:	FreeBSD-EN-25:13.wlan_tkip

(cherry picked from commit 36fcd52c2b)
(cherry picked from commit 950343a170)
2025-08-07 16:21:08 -07:00
Ahmad Khalifa ce4fe4c4bf Add a new sysctl in order to diffrentiate UEFI architectures
With the new 32-bit UEFI loader, it's convenient to have a sysctl to
figure out how we booted. Can be accessed at machdep.efi_arch

Reviewed by: imp
Pull Request: https://github.com/freebsd/freebsd-src/pull/1098

(cherry picked from commit b538d49110)
(cherry picked from commit 0e8890a425)

Approved by:	so
Security:	FreeBSD-EN-25:12.efi
2025-08-07 16:10:00 -07:00
Gordon Tetlow 2ea99b8ed1 Add UPDATING entries and bump version.
Approved by:	so
2025-07-01 23:04:23 -07:00
Gordon Tetlow cb24a62cd7 Fix corruption in ZFS replication streams from encrypted datasets.
From the upstream pull request merges:
 #17340 b144b160b Fix 2 bugs in non-raw send with encryption

Obtained from:	OpenZFS
Approved by:	so
Security:	FreeBSD-EN-25:10.zfs
2025-07-01 22:51:38 -07:00
Colin Percival 8c9ce319fe Update in preparation for 14.3-RELEASE
- Bump BRANCH to RELEASE
- Add the anticipated RELEASE announcement date
- Set a static __FreeBSD_version

Approved by:	re (implicit)
Sponsored by:	Amazon
2025-06-06 00:00:00 +00:00
Tom Hukins ffacf114e1 Fix incorrect version introduced in manual pages
Several manual pages for releng/14.3 incorrectly claim that features
were first introduced in FreeBSD 15.0.

I discovered these by running:

  git checkout origin/releng/14.3
  git grep -F '.Fx 15.0'

Approved by:    re (cperciva)
MFC After: 3 days
Reviewed by: imp, ziaee
Pull Request: https://github.com/freebsd/freebsd-src/pull/1685

(cherry picked from commit 5b9660caff)
(cherry picked from commit ef4014882e)
2025-06-03 17:47:57 -06:00
Kenneth Raplee cd46420a61 ure.4: add a HARDWARE section + add RTL8156BG as a compatible controller
While here, rename all instances of "RealTek" to "Realtek" for
authenticity.

Approved by:	re (cperciva)
Reviewed by: imp, lwshu, zaiee
Pull Request: https://github.com/freebsd/freebsd-src/pull/1649

(cherry picked from commit 76ed6f2db3)
(cherry picked from commit f336a04960)
2025-06-03 11:35:21 -07:00
Alexander Ziaee 6fe425b4c4 ure.4: description consistencies + tag spdx
+ consistent document description languague with other USB-BaseT drivers
+ mention newly added adapters from 6ea4d9
+ attempt to mention rgephy(4) phys feed into ure interfaces

Approved by:	re (cperciva)
Fixes:		6ea4d9 (Move RTL8156 from cdce(4) to ure(4))
MFC after:	3 days

Reviewed by: imp
Pull Request: https://github.com/freebsd/freebsd-src/pull/1384

(cherry picked from commit 4c72525953)
(cherry picked from commit b529a06d1d)
2025-06-03 11:35:11 -07:00
Kenneth Raplee 9efdb081e8 puc.4: Add a HARDWARE section based off device data from pucdata.c
While here, change applicable uses of "ports" to "adapters" to be more
precise and improve searchability.

This is a 14.3 candate since it affects (positively) the release notes
generated from the hardware secionts.

Approved by:	re (cperciva)
MFC After: 3 days
Reviewed by: imp
Pull Request: https://github.com/freebsd/freebsd-src/pull/1663

(cherry picked from commit 794ee43e75)
(cherry picked from commit 827153d212)
2025-06-03 11:35:01 -07:00
Colin Percival a7a4742156 Reapply "14.3: Update to RC1"
Second attempt at making 14.3-RC1 happen, now that a critical
last-minute MFC has landed.

This reverts commit c5db8f6562.

Approved by:	re (cperciva)
2025-05-30 09:02:53 -07:00
Dag-Erling Smørgrav fb33dd91ae certctl: Split certificate bundles before processing.
This allows 'certctl rehash' to do the right thing when ca_root_nss is
installed, instead of linking the entire bundle to the hash of the
first certificate it contains.

MFC after:	3 days
Reviewed by:	allanjude
Differential Revision:	https://reviews.freebsd.org/D42087

(cherry picked from commit a401c8cb26)

certctl: Fix recent regressions.

- If an untrusted certificate is also found in the list of trusted
  certificate, issue a warning and skip it, but don't fail.
- Split on -+BEGIN CERTIFICATE-+ instead of "Certificate:" since
  that's what we're really looking for.

Also fix a long-standing bug: .crl files are not certificates, so we
should not include them when searching for certificates.

Reported by:	madpilot, netchild, tijl
Reviewed by:	netchild, allanjude
Differential Revision:	https://reviews.freebsd.org/D42276

(cherry picked from commit 87945a0829)

certctl: Convert line endings before inspecting files.

This ensures that certificate files or bundles with DOS or Mac line
endings are recognized as such and handled identically to those with
Unix line endings.

PR:		274952
Reviewed by:	allanjude
Differential Revision:	https://reviews.freebsd.org/D42490

(cherry picked from commit f7d16a627e)

certctl: Revert to symlinks.

Unfortunately tar will not be able to extract base.txz to a system where
/etc and /usr are not on the same filesystem if the certificates are
hard links.

PR:		277828
Reviewed by:	mp
Differential Revision:	https://reviews.freebsd.org/D44496

(cherry picked from commit 3fed4f0db5)
(cherry picked from commit 9c34a6876a)

Approved by:	re (cperciva)
2025-05-30 17:59:32 +02:00
Colin Percival c5db8f6562 Revert "14.3: Update to RC1"
Postponing RC1 slightly to allow one more critical bug fix.

This reverts commit 3383279318.

Approved by:	re (cperciva)
2025-05-30 08:53:21 -07:00
Colin Percival 3383279318 14.3: Update to RC1
Approved by:	re (implicit)
Sponsored by:	Amazon
2025-05-29 15:54:06 -07:00
Christos Margiolis 99b8be414c sound: Terminate stream properly when closing vchans
When a channel is closed, dsp_close() either calls vchan_destroy() on vchans,
or chn_abort()/chn_flush() on primary channels. However, the problem with this
is that, when closing a vchan, we end up not terminating the stream properly.

The call sequence we are interested in is the following:

	vchan_destroy(vchan) -> chn_kill(vchan) -> chn_trigger(vchan) ->
	vchan_trigger(vchan) -> chn_notify(parent)

Even though chn_notify() contains codepaths which call chn_abort(parent),
apparently we do not execute any of those codepaths in this case, so the
DMA remains unterminated, hence why we keep seeing the primary
channel(s) being interrupted even once the application has exited:

root@freebsd:~ # sndctl interrupts
dsp0.play.0.interrupts=1139
dsp0.record.0.interrupts=0
root@freebsd:~ # sndctl interrupts
dsp0.play.0.interrupts=1277
dsp0.record.0.interrupts=0
root@freebsd:~ # sndctl interrupts
dsp0.play.0.interrupts=1394
dsp0.record.0.interrupts=0

The only applications that do not have this issue are those (e.g., mpv) that
manually call ioctls which end up calling chn_abort(), like SNDCTL_DSP_HALT, to
abort the channel(s) during shutdown. For all other applications that do not
manually abort the channel(s), we can confirm that chn_abort()/chn_flush(), or
even chn_trigger(PCMTRIG_ABORT) on the parent, doesn't happen during shutdown.

root@freebsd:~ # dtrace -n 'fbt::chn_abort:entry,fbt::chn_flush:entry { printf("%s", args[0]->name); stack(); }'
dtrace: description 'fbt::chn_abort:entry,fbt::chn_flush:entry ' matched 2 probes
dtrace: buffer size lowered to 1m
^C

[...]

root@freebsd:~ # dtrace -n 'fbt::chn_trigger:entry /args[1] == -1/ { printf("%s", args[0]->name); stack(); }'
dtrace: description 'fbt::chn_trigger:entry ' matched 1 probe
dtrace: buffer size lowered to 1m
CPU     ID                    FUNCTION:NAME
  0  68037                chn_trigger:entry dsp0.virtual_play.0
	      sound.ko`chn_kill+0x134
	      sound.ko`vchan_destroy+0x94
	      sound.ko`dsp_close+0x39b
	      kernel`devfs_destroy_cdevpriv+0xab
	      kernel`devfs_close_f+0x63
	      kernel`_fdrop+0x1a
	      kernel`closef+0x1e3
	      kernel`closefp_impl+0x76
	      kernel`amd64_syscall+0x151
	      kernel`0xffffffff8103841b1

To fix this, modify dsp_close() to execute the primary channel case on both
primary and virtual channels. While what we really care about are the
chn_abort()/chn_flush() calls, it shouldn't hurt to call the rest of the
functions on the vchans as well, to avoid complicating things; they get deleted
right below, anyway.

With the patch applied:

root@freebsd:~ # dtrace -n 'fbt::chn_trigger:entry /args[1] == -1/ { printf("%s", args[0]->name); stack(); }'
dtrace: description 'fbt::chn_trigger:entry ' matched 1 probe
dtrace: buffer size lowered to 1m
CPU     ID                    FUNCTION:NAME
  1  68037                chn_trigger:entry dsp0.virtual_play.0
              sound.ko`chn_flush+0x2a
              sound.ko`dsp_close+0x330
              kernel`devfs_destroy_cdevpriv+0xab
              kernel`devfs_close_f+0x63
              kernel`_fdrop+0x1a
              kernel`closef+0x1e3
              kernel`closefp_impl+0x76
              kernel`amd64_syscall+0x151
              kernel`0xffffffff8103841b

  0  68037                chn_trigger:entry dsp0.play.0
              sound.ko`chn_notify+0x4ce
              sound.ko`vchan_trigger+0x105
              sound.ko`chn_trigger+0xb4
              sound.ko`chn_flush+0x2a
              sound.ko`dsp_close+0x330
              kernel`devfs_destroy_cdevpriv+0xab
              kernel`devfs_close_f+0x63
              kernel`_fdrop+0x1a
              kernel`closef+0x1e3
              kernel`closefp_impl+0x76
              kernel`amd64_syscall+0x151
              kernel`0xffffffff8103841b

Above we can see a chn_trigger(PCMTRIG_ABORT) on the parent (dsp0.play.0),
which is coming from the chn_abort() (inlined) in chn_notify():

root@freebsd:~ # dtrace -n 'kinst::chn_abort:entry { stack(); }'
dtrace: description 'kinst::chn_abort:entry ' matched 5 probes
dtrace: buffer size lowered to 1m
CPU     ID                    FUNCTION:NAME
  1  72580                  chn_notify:1192
              sound.ko`0xffffffff8296cab4
              sound.ko`vchan_trigger+0x105
              sound.ko`chn_trigger+0xb4
              sound.ko`chn_flush+0x2a
              sound.ko`dsp_close+0x330
              kernel`devfs_destroy_cdevpriv+0xab
              kernel`devfs_close_f+0x63
              kernel`_fdrop+0x1a
              kernel`closef+0x1e3
              kernel`closefp_impl+0x76
              kernel`amd64_syscall+0x151
              kernel`0xffffffff8103841b

We can also confirm the primary channel(s) are not interrupted anymore:

root@freebsd:/mnt/src # sndctl interrupts
dsp0.play.0.interrupts=0
dsp0.record.0.interrupts=0

In collaboration with:	adrian
Tested by:		adrian, christos, thj
Sponsored by:		The FreeBSD Foundation
MFC after:		2 days
Reviewed by:		thj, adrian, emaste
Differential Revision:	https://reviews.freebsd.org/D50488

(cherry picked from commit f6430bc61d)
(cherry picked from commit 0c6aa445ec)

Approved by:		re (cperciva)
2025-05-30 00:51:30 +02:00
Colin Percival 85739bcbce 14.3: Switch from "quarterly" to "release" pkgs
Approved by:	re (implicit)
Sponsored by:	Amazon
2025-05-29 15:18:34 -07:00
Colin Percival a47542f715 pkg.conf: Use kmod repositories
The kmod repositories were added shortly after 14.2-RELEASE.  Point at
them here so that users don't need to manually add the configuration
in order to get e.g. working graphics.

Approved by:	re (cperciva)
MFC after:	1 minute
Sponsored by:	Amazon
Differential Revision:	https://reviews.freebsd.org/D50583

(cherry picked from commit 29f076ae0c)
(cherry picked from commit 8a2ce9f9dd)
2025-05-29 12:58:46 -07:00
Jordan Gordeev a0d22d7934 libc++: fix compiling <locale> with -fmodules
In /usr/include/c++/v1/__locale_dir/locale_base_api.h, xlocale.h is
included without first including stdio.h and stdlib.h, which causes
functions like strtoll_l() or sscanf_l() to not be declared.

When compiling with -fmodules, locale_base_api.h is processed separately
due to a declaration in /usr/include/c++/v1/module.modulemap, and this
will cause errors due to the above undeclared symbols.

Meanwhile, upstream has substantially reorganized this part of libc++'s
headers, so apply a minimalistic workaround: specifically when compiling
with -fmodules, add includes of stdio.h and stdlib.h.

PR:		286342
Approved by:	re (cperciva)
MFC after:	1 week

(cherry picked from commit c809b0184d)
(cherry picked from commit cab029073d)
2025-05-28 18:26:27 +02:00
Alexander Motin 93839cddbd systat/top: Update ZFS sysctl names
Some of ARC statistic sysctls changed years ago, but those tools
are still using legacy shims, that are going to be removed.

Approved by:    re (cperciva)

(cherry picked from commit 8aad1e6148)
(cherry picked from commit f23326ff2c)
2025-05-27 22:20:01 -04:00
Bjoern A. Zeeb 4d66e0f884 LinuxKPI: 802.11: mark struct ieee80211_ht_cap __packed
In lkpi_sta_sync_ht_from_ni() we are casting the information element (IE)
data to this struct as net80211 does not save the mcs/rx_mask.
Not marking the structs packed results in the mcs information not being
copied correctly and rx_nss calculations possibly being off.  Even worse,
at a later stage iwlwifi mvm/rs.c would extract the mcs values from the
same field to pass to the firmware which will than crash in an assert
as we would want to do HT with an empty MCS set.

Sponsored by:	The FreeBSD Foundation
Discovered:	while testing other features on arm64.
Approved by:	re (cperciva)

(cherry picked from commit 6cbf8a04b1)
(cherry picked from commit 9ccf7aeaa5)
2025-05-27 22:44:20 +00:00
Olivier Certner adc6f56e81 MAC/do: Fix a too stringent debug assertion for a target of 'uid=*'
MDF_HAS_PRIMARY_CLAUSE only concerns groups, not users, and is thus not
set in the latter case.

This change only has an effect on INVARIANTS builds.

PR:             287057
MFC after:      10 minutes
Sponsored by:   The FreeBSD Foundation

(cherry picked from commit b5c9889e36)
(cherry picked from commit 30f092c40a)

Approved by:    re (cperciva)
2025-05-27 23:01:54 +02:00
Philip Paeps a48dc9b03b zoneinfo: don't install version
The commit teaching the build to install tzdata.zi for libcxx also
instals version.  It turns out this makes at least one piece of third
party software cry: rubygem-tzinfo expects any file in zoneinfo to be at
least 44 bytes long.  Clearly this is a bug in rubygem-tzinfo but since
nothing actually uses version, we may as well not install it ... as we
did previously.

Reported by:	delphij
Fixes:		91506dba7f zoneinfo: also install tzdata.zi and version
MFC after:	1 day
Approved by:	re (cperciva)

(cherry picked from commit 23a0c88b03)
(cherry picked from commit 16ad4d7712)
2025-05-24 11:33:02 +06:00
Colin Percival c4c9907816 14.3: Update to BETA4
Approved by:	re (implicit)
Sponsored by:	Amazon
2025-05-22 17:04:19 -07:00
Lexi Winter 6e27b15e6a package: fix dependency generation
A bug in release/packages/generate-ucl.sh causes package dependencies
(other than shlib depends) to not be generated correctly, meaning
packages are missing their dependencies.

generate-ucl.sh creates the UCL file by:

1. copying ${uclsource} (template.ucl) to ${uclfile}
2. appending dependencies to ${uclfile}
3. calling generate-ucl.lua on ${uclsource} to create ${uclfile}

This breaks because the dependencies added in step 2 are overwritten in
step 3.

Fix this by calling generate-ucl.lua with ${uclfile} as both the input
and output file, so anything we added to ${uclfile} is preserved.

PR:	286551
Reviewed by:	des, imp
Approved by:	re (cperciva)
Approved by:	kevans (mentor, stable/14 mfc)
Pull Request:	https://github.com/freebsd/freebsd-src/pull/1203

(cherry picked from commit e05b6502f9)
(cherry picked from commit fb6b1a7973)
2025-05-22 17:04:12 -07:00
Alexander Ziaee 5af0942052 mtkswitch.4: Initial manual page
Add a stub manual only saying what it is, how to include it, what is
supported, and since when. This plugs the mtkswitch driver into the
manual subsystem and the release hardware notes.

MFC to:			14.3
MFC after:		3 days
Reviewed by:		adrian, carlavilla
Approved by:		carlavilla (mentor)
Approved by:		re (cperciva)
Differential Revision:	https://reviews.freebsd.org/D50412

(cherry picked from commit 37f00bc257)
(cherry picked from commit f31ac06711)
2025-05-21 23:01:36 -04:00
Alexander Ziaee dc8ade18cf ip17x.4: Initial manual page
Add a stub manual only saying what it is, how to include it, what is
supported, and since when. This plugs the ip17x driver into the manual
subsystem and the release hardware notes.

MFC to:			14.3
MFC after:		3 days
Reviewed by:		adrian, carlavilla
Approved by:		carlavilla (mentor)
Approved by:		re (cperciva)
Differential Revision:	https://reviews.freebsd.org/D50411

(cherry picked from commit f750a114d2)
(cherry picked from commit ded154a1df)
2025-05-21 23:01:22 -04:00
Alexander Ziaee 86b04d37f0 qat.4: Cleanup
+ copyright symbols do not belong in Nd's (apropos results)
+ move hardware to HARDWARE for inclusion in the hw release notes
+ improve sysctls
+ lines which say nothing removed
+ links moved to see also
+ spacing and markup corrections

MFC after:		3 days
Reviewed by:		markj, mhorne
Approved by:		mhorne (mentor)
Approved by:		re (cperciva)
Differential Revision:	https://reviews.freebsd.org/D50381

(cherry picked from commit c1d9b2c9b0)
(cherry picked from commit 802edf2307)
2025-05-21 23:00:56 -04:00
Alexander Ziaee b7fc3fbe32 e6000sw.4: Add HISTORY
MFC after:		3 days
Reviewed by:		mhorne
Approved by:		mhorne (mentor)
Approved by:		re (cperciva)
Differential Revision:	https://reviews.freebsd.org/D50358

(cherry picked from commit c808bee35b)
(cherry picked from commit 6426b01310)
2025-05-21 23:00:39 -04:00
Alexander Ziaee ee743b40ac e6060sw.4: Improve title and add HARDWARE
For visibility in apropos and inclusion in the hardware release notes.

MFC after:		3 days
Reviewed by:		adrian, mhorne
Approved by:		mhorne (mentor)
Approved by:		re (cperciva)
Differential Revision:	https://reviews.freebsd.org/D50321

(cherry picked from commit bef89c155e)
(cherry picked from commit 5e0e046d95)
2025-05-21 23:00:26 -04:00
Alexander Ziaee fddd2c4d37 ar40xx.4: Initial manual page
For inclusion in apropos and the hardware release notes. While here,
add xrefs to this page and the previous e6000sw in etherswitch.4.

MFC after:		3 days (but adjusted for 14.3)
Reported by:		adrian
Reviewed by:		adrian, mhorne
Approved by:		mhorne (mentor)
Approved by:		re (cperciva)
Differential Revision:	https://reviews.freebsd.org/D50324

(cherry picked from commit 91c9751c39)
(cherry picked from commit 17e9eb1e0e)
2025-05-21 23:00:12 -04:00
Alexander Ziaee 5dbcb9bfd0 arswitch.4: Improve title and add HARDWARE
For visibility in apropos and inclusion in the hardware release notes.

MFC after:		3 days
Reviewed by:		adrian (previous), mhorne
Approved by:		mhorne (mentor)
Approved by:		re (cperciva)
Differential Revision:	https://reviews.freebsd.org/D50322

(cherry picked from commit 9692d5e15e)
(cherry picked from commit 1343a5b616)
2025-05-21 22:58:47 -04:00
Alexander Ziaee f50ca9a01b stand/lua manuals: Describe better
The lua boot loader module manuals were getting pulled into search
results for FreeBSD, but not for "boot" or "loader". Reword them to
increase clarity for boot or loader searches, as well as the FreeBSD
search term which we've been scoping to system topic overview manuals.

MFC after:	3 days
Reviewed by:	imp, mhorne
Approved by:	mhorne (mentor)
Approved by:	re (cperciva)
Pull Request:	https://github.com/freebsd/freebsd-src/pulls/1628

(cherry picked from commit 5d59c1b4f1)
(cherry picked from commit 651102873e)
2025-05-21 22:58:35 -04:00
Alexander Ziaee 5d9e62e1cd cdboot.8: Initial manual page
Add cdboot to the reference manual, fixing an undocumented bug where it
is undocumented. There's almost nothing here, but that's better than
"only imp and jhb know what this is".

MFC after:		3 days
Reported by:		jhb, imp
Reviewed by:		mhorne
Approved by:		mhorne (mentor)
Approved by:		re (cperciva)
Differential Revision:	https://reviews.freebsd.org/D50274

(cherry picked from commit ecdb0b79bf)
(cherry picked from commit d659366cc6)
2025-05-21 22:58:21 -04:00
Alexander Ziaee 66a6607089 e6000sw.4: Initial manual page
For inclusion in the HW relnotes.

MFC after:		3 days, note removed entries which didn't mfc
Reviewed by:		adrian, ivy, mhorne
Approved by:		mhorne (mentor)
Approved by:		re (cperciva)
Differential Revision:	https://reviews.freebsd.org/D50293

(cherry picked from commit 6da793a8ca)
(cherry picked from commit d0e29f92f7)
2025-05-21 22:56:59 -04:00
Tijl Coosemans adf77cb48e snd_hda: Add shutdown method
Power down the device on shutdown similar to what is done in the case
of suspend. The device may fail to attach on next boot without this.

PR:		286385
Reviewed by:	christos, adrian
Differential Revision:	https://reviews.freebsd.org/D50306

(cherry picked from commit d9900b9ea2)
(cherry picked from commit 77521692f4)

Approved by:    re (cperciva)
2025-05-22 01:21:42 +02:00
Dag-Erling Smørgrav 747efc2aee namei: Update documentation.
This should have been done 2+ years ago when the td argument was dropped
from NDINIT() and the NDFREE() macro and the SAVENAME and SAVESTART
flags were retired.

Approved by:	re (cperciva)
MFC after:	3 days
Fixes:		7e1d3eefd4 ("vfs: remove the unused thread argument from NDINIT*")
Fixes:		269c564b90 ("vfs: retire NDFREE")
Sponsored by:	NetApp, Inc.
Reviewed by:	markj
Differential Revision:	https://reviews.freebsd.org/D50375

(cherry picked from commit ee84b4e2fd)
(cherry picked from commit 68bc635cc9)
2025-05-21 19:37:10 +02:00
Dag-Erling Smørgrav 84b971c918 man: Exit cleanly on SIGPIPE.
The first attempt at addressing this simply suppressed SIGPIPE, which
resulted in mandoc printing out error messages instead.  This was then
reverted, but the pipefail was (correctly) left in, so man still
returned a nonzero exit code if you quit a page before the end.

Approved by:	re (cperciva)
PR:		223516, 279542
Fixes:		14a5c1068d, a85d870007
MFC after:	1 week
Reviewed by:	ziaee, kevans
Differential Revision:	https://reviews.freebsd.org/D50302

(cherry picked from commit fbaba7aa43)
(cherry picked from commit 2f99190a92)
2025-05-21 19:36:41 +02:00
Olivier Certner 6b6d6448fe vfs: vntblinit(): Raise default 'kern.maxvnodes' higher than 'kern.maxfiles'
Having 'kern.maxvnodes' higher than 'kern.maxfiles' mitigates a scenario
where some processes can eat up all vnodes in the system, causing
a deadlock, as long as the kernel itself does not create too many vnodes
without creating some file descriptor in some process' FD table.  A very
small percentage (~0.6%) of excess vnodes at infinity, coupled with
a large difference near the origin, should cover basic cases more than
enough.  Note however that this measure can be defeated, e.g., by using
nullfs mounts with non-trivial file hierarchies.

MFC after:      5 days
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D50314

(cherry picked from commit e9baf472a6)
(cherry picked from commit a6b05a35ce)

Approved by:    re (cperciva)
2025-05-21 12:07:52 +02:00
Olivier Certner 0b4d5c560a vfs: vntblinit(): Rework comments on the computation of 'kern.maxvnodes'
Remove the parts that describe what is already in the code formula.  Add
hints about which of 'physvnodes'/'virtvnodes' takes precedence, and
when 'desiredvnodes' becomes smaller than 'maxfiles'.  These were both
computed analytically and verified experimentally.

Reviewed by:    kib (older version)
MFC after:      3 days
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D50310

(cherry picked from commit bf8890c84b)
(cherry picked from commit 5b07152f3e)

Approved by:    re (cperciva)
2025-05-21 12:07:45 +02:00
Olivier Certner fbc73f17ba Compute 'maxproc'/'maxfiles' from memory amount; Expand/fix comments
Change the formulae so that 'maxproc' and 'maxfiles' are computed based
on the physical memory amount, and not the corresponding number of
pages.  Make sure that the practical results are unchanged for all
architectures (which is possible since all have 4096 as their
PAGE_SIZE).  Despite this, we do this change to make it clearer how many
units of these values are computed per MB, which is easier on readers.

Change the comments accordingly and expand them to indicate which parts
of the computations are actually not used by default.  In passing, fix the
comments about default values and limits for 'maxfiles' (they were off).

No functional change (intended).

MFC after:      3 days
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D50124

(cherry picked from commit 73f9251c0b)
(cherry picked from commit e7d4e52eaf)

Approved by:    re (cperciva)
2025-05-21 12:07:36 +02:00
Olivier Certner 7a9ea03e4b vfs: vn_alloc(): Stop always calling vn_alloc_hard() and direct reclaiming
Commit ab05a1cf32 intended to revert commit 8733bc277a
("vfs: don't provoke recycling non-free vnodes without a good reason"),
but due to intervening changes in commit 054f45e026 ("vfs: further
speed up continuous free vnode recycle"), it also had to revert part of
it.  In particular, while removing the whole 'if (vn_alloc_cyclecount !=
0)' block, it inadvertantly removed the code block resetting
'vn_alloc_cyclecount' to 0 and skipping direct vnode reclamation (done
further below through vnlru_free_locked_direct()), which had been
outside the 'if' before the intervening commit.

Removing this block instead of reinstating it in practice causes
'vn_alloc_cyclecount' to (almost) never be 0, making vn_alloc() always
call vn_alloc_hard(), which takes the 'vnode_list_mtx' mutex.  In other
words, this disables the fast path.  [The reverted commit, which
introduced the 'if (vn_alloc_cyclecount != 0)' guarding this block,
actually never executed it because it also had the bug that
'vn_alloc_cyclecount' would always stay at 0, hiding its usefulness.]

Additionally, not skipping direct vnode reclamation even when there are
less vnodes than 'kern.maxvnodes' not only causes unnecessary contention
but also plain livelocks as vnlru_free_locked_direct() does not itself
check whether there are actually "free" (not referenced) vnodes to be
deallocated, and will blindly browse all the vnode list until it finds
one (which it may not, or only a few ones at the end).  As the fast path
was disabled, all threads in the system would soon be competing for the
vnode list lock, outpacing the vnlru process that could never actually
recycle vnodes in a more agressive manner (i.e., even if they have
a non-zero hold count).  And we could more easily get into this
situation, as each vnode allocation was reducing the count of "free"
vnodes, even if entirely new vnodes could be allocated instead.  This
part was mitigated by the vnlru process (before the tipping point
described above), which explains why the mechanism would not always
livelock.

Not skipping direct vnode reclamation was arguably a bug introduced by
the intervening commit (054f45e026), but was mitigated by
vn_alloc_hard() not being called in the fast path.  The revert commit,
by disabling the fast path, made it significantly annoying (to the point
of getting a few livelocks a week in some of my workloads).

Restore the reset of 'vn_alloc_cyclecount' to 0 and skip direct
reclamation when the current number of vnodes is below the
'kern.maxvnodes' limit, indicating we can start allocating a new 'struct
vnode' right away.  While here, fix the comparison with the limit when
'bumped' is true.

Reviewed by:    kib (older version), avg
Tested by:      avg, olce
Fixes:          ab05a1cf32 (revert of "vfs: don't provoke recycling non-free vnodes without a good reason")
Fixes:          054f45e026 ("vfs: further speed up continuous free vnode recycle")
MFC after:      5 days
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D50338

(cherry picked from commit d90c9c24e2)
(cherry picked from commit ce6b7a5919)

Approved by:    re (cperciva)
2025-05-21 12:07:15 +02:00
Bjoern A. Zeeb 361a8fdefa iwlwifi.4: Update modes for recent 802.11ac
By:			ziaee
Reported by:		Pat Maddox <[email protected]>
Reviewed by:		bz (previous version), emaste, mhorne
Differential Revision:	https://reviews.freebsd.org/D49937

iwlwifi: update man pages for generations, firmware. and 11n/11ac

Put Intel's iwlwifi better in context to iwm, iwx and iwn.
Document the important tunables so users know where to go.
Document the port/package for firmware where firmware is now
maintained.
Adjust wording and table for the firmware and a flavor column.
Update History sections for 11n/11ac support as well as firmware
module removal from base.

Sponsored by:	The FreeBSD Foundation
Reviewed by:	ziaee, emaste (comments)
Differential Revision: https://reviews.freebsd.org/D50319

Approved by:	re (cperciva)

(cherry picked from commit c33945a112)
(cherry picked from commit a7e183c0c9)
(cherry picked from commit 4ae64bd33f)
2025-05-19 19:28:40 +00:00
Roger Pau Monné a7277b98b8 xen: improve man (4) page
Update the xen(4) man page to reflect the current support status.

Approved by: re (cperciva)
Reported by: kevans
Reviewed by: bcr kevans imp
Differential revision: https://reviews.freebsd.org/D43373

(cherry picked from commit 82126ef92f)
(cherry picked from commit 7dc0a9fa76)
2025-05-19 10:01:30 -07:00
Colin Percival a2ebf641da 14.3: Update to BETA3
Approved by:	re (implicit)
Sponsored by:	Amazon
2025-05-16 00:00:00 +00:00
Colin Percival 29d6968fd3 EC2: Remove old broken_txfifo workaround
Early versions of Xen, including those used in the early days of EC2,
had a bug in their UART emulation whereby the TX FIFO wouldn't send the
expected interrupt when emptying; as a result, FreeBSD would write 16
characters to the serial console and then stop because we thought the
FIFO was forever full.

In 2013 (1c60b24baa) I added a loader tunable "hw.broken_txfifo"
which spinwaits for the FIFO TX rather than relying on the interrupt,
and enabled this in loader.conf in EC2 images.

A decade later, this workaround is almost certainly no longer needed in
EC2 -- most instances don't run Xen, and the bug was long since fixed
in Xen anyway -- but we've been holding on to the workaround "just in
case".  Unfortunately, the spinwait behaviour is causing latency spikes
and triggering warnings from the ena(4) driver.

This commit removes the hw.broken_txfifo setting from loader.conf in
EC2 images, but leaves the loader tunable and associated code, since it
has been necessary in some other environments.  (It seems that the TX
FIFO missing-interrupts bug has been independently written at least
three times!)

Approved by:	re (cperciva)
MFC after:	1 minute
Sponsored by:	Amazon

(cherry picked from commit 9a685c09f0)
(cherry picked from commit eadda156a5)
2025-05-15 15:22:44 -07:00
Bjoern A. Zeeb 36174c38f9 LinuxKPI: 802.11: make sure AUTH frames are not being sent if BSS changed
iwlwifi keeps logging 'Invalid TXQ id' even after previous changes to
catch the BSS changed.  The reason for this is that we do not error in
the SCAN -> AUTH path as otherwise we would not have the state machine
get us back to SCAN to clear up firmware state before auth/assoc to the
new BSS.

If we are not in synch as net80211 just swapped the iv_bss from under us,
disable the TX queue for the (old) lsta to prevent the AUTH frame sent
from sta_newstate() reaching the driver.  After all we are not trying to
authenticate to that node (sta) anymore.

Sponsored by:	The FreeBSD Foundation
PR:		274382
Approved by:	re (cperciva)

(cherry picked from commit 16d987fe78)
(cherry picked from commit e0692e7bb6)
2025-05-15 19:13:58 +00:00
Justin Hibbits ac1943f97c powerpc: Always use BE tag in nexus_map_resource
7b5a5e4e replaced nexus_activate_resource() with the bus generic
equivalent, which uses bus_map_resource().  However, though not intended
to have a functional change, nexus_map_resource() uses the bus tag of
the build (BE vs LE), while nexus_activate_resource() always explicitly
set a big-endian tag, leading to failures on powerpc64le now.  Using BE
unless otherwise explicitly specified with the RF_LITTLEENDIAN fixes LE
on bare metal, and doesn't hurt in a VM, which nexus_map_resource() was
added for.

Reported by:	pkubaj
Tested by:	pkubaj
Fixes:		7b5a5e4e("powerpc nexus: Use bus_generic_rman_*")
MFC after:	1 day
Approved by:	re(cperciva)

(cherry picked from commit c4921a0faa)
(cherry picked from commit 45d585ab7f)
2025-05-15 09:06:51 -04:00
Dag-Erling Smørgrav 95223d920a bsdinstall: Use a login shell for final configuration.
If the user accepts our offer of a shell to perform final configuration
tasks before rebooting, start a login shell.  This ensures it will have
the correct PATH and be able to install packages without issues.

Approved by:	re (cperciva)
PR:		286722
MFC after:	3 days
Reviewed by:	jrtc27, allanjude, emaste
Differential Revision:	https://reviews.freebsd.org/D50297

(cherry picked from commit 5870d6a1ef)
(cherry picked from commit 242b52ba3c)
2025-05-14 20:08:15 +02:00
Christos Margiolis aff92a9f3c sound: Call PCM_RELEASE() if pcm_addchan() fails
Fixes:		fd906e47b1 ("sound: Simplify locking during device creation")
Sponsored by:	The FreeBSD Foundation
MFC after:	1 day
Reviewed by:	markj
Differential Revision:	https://reviews.freebsd.org/D50337

(cherry picked from commit dbfe79bbe5)
(cherry picked from commit 3de66f369c)

Approved by:    re (cperciva)
2025-05-14 16:23:53 +02:00
Olivier Certner 10944406be queue(3): Install *_SPLIT_AFTER() links to the main manual page
Completes commit "queue(3): New *_SPLIT_AFTER(), *_ASSERT_EMPTY(),
*_ASSERT_NONEMPTY()" (c028802339).

MFC after:      1 day
Sponsored by:   The FreeBSD Foundation

(cherry picked from commit c071616b06)
(cherry picked from commit eca0ce8afb)

Approved by:    re (cperciva)
2025-05-13 14:41:33 +02:00
Olivier Certner d156cabc0f sysctl.9: Constant integer example: Do not promote 'debug.sizeof'
Replace it with another one, selected from current in-tree uses.

MFC after:      1 day
Sponsored by:   The FreeBSD Foundation

(cherry picked from commit 129a6cf886)
(cherry picked from commit 1ca993dd45)

Approved by:    re (implicit)
2025-05-13 14:41:33 +02:00
Olivier Certner de6a4418ee sysctl(9): Ease exporting struct sizes; Discourage doing that
Introduce two helpers, the more general SYSCTL_SIZEOF() and
a struct-specific one SYSCTL_SIZEOF_STRUCT() which prepends 'struct' in
the description and in the use of sizeof() but uses the raw structure
name as the knob's name.  The size of the object/structure is exported
under 'debug.sizeof'.

Existing knobs under 'debug.sizeof' were all converted to use the
helpers.

Add a note before the helpers discouraging the introduction of new
leaves for ad-hoc reasons.  List alternative means for developers to
obtain the size of arbitrary kernel structures easily (thanks to markj@
for providing these).

No functional change (intended).

Reviewed by:    kib, markj
MFC after:      3 days
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D50121

(cherry picked from commit 713abc9880)
(cherry picked from commit efce9f8a51)

Approved by:    re (cperciva)
2025-05-13 14:41:33 +02:00
Olivier Certner f7fa53cead stress2: exlock2.sh: Fix impact of previous '-U' removal
In commit "stress2: exlock2.sh: Preserve behavior after ps(1)'s '-U'
change" (1265d3b07e), I forgot that '-U' also has the side-effect of
implying '-x' by default.  Now that '-U' has been removed, make '-x'
explicit.

Fixes:          1265d3b07e ("stress2: exlock2.sh: Preserve behavior after ps(1)'s '-U' change")
MFC after:      1 hour
Sponsored by:   The FreeBSD Foundation

(cherry picked from commit f6e8268917)
(cherry picked from commit da6b04cd40)

Approved by:    re (implicit)
2025-05-13 14:41:33 +02:00
Olivier Certner 10e6bac460 stress2: exlock2.sh: Preserve behavior after ps(1)'s '-U' change
Remove '-Uroot', as now '-U' selects processes based on their real user
IDs, and since the program using them was launched as 'root', the
equivalent now is just to remove it, as now ps(1) by default selects
processes based on its effective UID (root) and their effective UIDs.

It seems that matching on effective or real UID does not really matter
in this test, but at least this change simplifies the command-line.

MFC after:      1 day
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D50200

(cherry picked from commit 1265d3b07e)
(cherry picked from commit 5af18707c1)

Approved by:    re (cperciva)
2025-05-13 14:41:32 +02:00
Olivier Certner 2d5e13c86a rc/tests: Fix process flags checks using ps(1)
These checks use ps(1) with both the '-p' and '-a' flags, which worked
so far as ps(1)'s '-a' option was buggy.  Since the fix in commit
"ps(1): Make '-a' and '-A' always show all processes"
(93a94ce731), such a command-line always selects all processes,
making the specified '-p' useless and the test wrong.  Remove the
useless '-a'.

While here, remove the redundant '-x', as '-p' implies '-x' by default.

MFC after:      1 day
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D50201

(cherry picked from commit 6463754087)
(cherry picked from commit a69fe62604)

Approved by:    re (cperciva)
2025-05-13 14:41:32 +02:00
Olivier Certner d5fff1aad5 ps.1: Remove ambiguity in description of option '-J'
As stated in the previous commit, option '-J' was introduced by commit
"Add -J to filter by matching jail IDs and names."
(13767130c7, r265229), which unfortunately talked about '-J'
being a filter while actually implementing it as a regular selection
option which adds to the processes to display.

The manual page's formulation hinted more at '-J' being a filter, which
it is not, or could be just considered ambiguous, because of the
presence of the "only" word.  Consequently, remove it and reformulate.

Reviewed by:    ziaee, dch
MFC after:      1 day
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D50194

(cherry picked from commit cbda1aea65)
(cherry picked from commit 1586fd84fb)

Approved by:    re (cperciva)
2025-05-13 14:41:32 +02:00
Olivier Certner eed005b578 RELNOTES: ps(1): Document change in behavior for '-a'/'-A'
Document the practical consequence of change "ps(1): Make '-a' and '-A'
always show all processes" (93a94ce731) that specifying '-a'/'-A'
leads to printing all processes regardless of the presence of other
process selection options (except for '-x'/'-X', which command
a filter).

While here, mention a possible practical issue with '-J', as reported by
dch@.  This option was introduced by commit "Add -J to filter by
matching jail IDs and names." (13767130c7, r265229), which
unfortunately talked about '-J' being a filter while actually
implementing it as a regular selection option which adds to the
processes to display.

Reviewed by:    dch
MFC after:      1 day
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D50193

(cherry picked from commit 428200d2f0)

Commit hash edited on MFC.

(cherry picked from commit f18a49a747)

Approved by:    re (cperciva)
2025-05-13 14:41:26 +02:00
Warner Losh e79a3515c2 mpi3mr: Remove -g
This -g was introduce when I didn't review all the cahnges to mpi3mr I
was MFCing. Remove it. This is a direct commit.

PR: 249068
Fixes: 80b069913d
Sponsored by:		Netflix
Approved by:  re (cperciva)
(cherry picked from commit 22ebbdea3f)
2025-05-12 16:45:35 -06:00
Colin Percival 0e771ca261 release: Don't put drm-kmod package onto DVD
The X.Y-RELEASE DVDs use a quarterly package set which was built on
X.(Y-1)-RELEASE, and those kernel modules are never going to be
useful.

Approved by:	re (cperciva)
MFC after:	30 seconds
Sponsored by:	Amazon

(cherry picked from commit 94e44a074e)
(cherry picked from commit 1ecfdc0091)
2025-05-11 15:23:21 -07:00
Colin Percival a1874e9adf pkg-stage.sh: kde5 -> kde
The "kde5" package no longer exists; KDE goes to 6.

Note: Depending on the size of 13.5-BETA3 DVD images, KDE might end
up being removed from this list in the near future.

Approved by:	re (cperciva)
With hat:	re@
MFC after:	30 seconds
Sponsored by:	Amazon

(cherry picked from commit 0d7b98c06c)
(cherry picked from commit 1c2e947d27)
2025-05-11 15:23:14 -07:00
Colin Percival 0e80651662 14.3: Update to BETA2
Approved by:	re (implicit)
Sponsored by:	Amazon
2025-05-09 00:00:00 +00:00
Bjoern A. Zeeb 8d6b758199 net80211: fix a race between ieee80211_sta_join and scan entries
We were seeing panics during ieee80211_sta_join() which seemed that
the ni->ni_chan was not valid anymore, which was true.
We also saw errors indicating data put into ni_ies became inalid.

The problem was that the ieee80211_scan_entry passed into
ieee80211_sta_join() (in the observed case from setmlme_assoc_sta())
became invalid during ieee80211_alloc_node().
As a result for the ni_chan case the the rateset and len in rates[1]
became invalid.  Similarly for the IEs.

Make a (deep)copy of the scan entry in setmlme_assoc_sta() and return
the copy as once we leave ieee80211_scan_iterate() we can no longer
rely on the scan entry to be valid.

Sponsored by:	The FreeBSD Foundation
Reported by:	rm, ziaee, bz
Tested by:	rm, ziaee, bz
PR:		286063
Approved by:	re (cperciva)
Reviewed by:	adrian (,emaste)
Differential Revision: https://reviews.freebsd.org/D49865

(cherry picked from commit aff56b4f0b)
(cherry picked from commit 34cd369186)
2025-05-08 21:22:59 +00:00
Bjoern A. Zeeb 873c0ea648 LinuxKPI: 802.11: header updates for mt76
Add more structs, fields, flags, defines.

Sponsored by:	The FreeBSD Foundation
Approved by:	re (cperciva)

(cherry picked from commit 675e6b1c68)
(cherry picked from commit 6a0dbc0a12)
2025-05-08 21:22:53 +00:00
Bjoern A. Zeeb 71946313d4 LinuxKPI: 802.11: fix wiphy_info[_once]
The dev field in wiphy is a pointer already; no need for &.

Sponsored by:	The FreeBSD Foundation
Fixes:		ac1d519c01
Approved by:	re (cperciva)

(cherry picked from commit 845b81cf90)
(cherry picked from commit a21addc7a0)
2025-05-08 21:22:35 +00:00
Xin LI 9679eedea9 MFV: xz 5.8.1.
PR:		bin/286252
Approved by:	re (cperciva)

(cherry picked from commit 128836d304)
(cherry picked from commit 5cf27a49a2)
2025-05-08 09:24:51 -07:00
Baptiste Daroussin b64d3fc884 nuageinit: implement chpasswd
Add support for chpasswd, with all possible syntaxes, including
deprecated one: chpasswd.list as a list or as a multiline string
as some providers are still only providing this deprecated form

Approved by:	 re (cperciva)
Sponsored by:	OVHCloud
MFC After:	1 week
Reviewed by:	kevans, jlduran
Differential Revision: 	https://reviews.freebsd.org/D50021

(cherry picked from commit c201a1198a)
(cherry picked from commit 6c91247003)
2025-05-08 15:08:55 +02:00
Mark Johnston f30669ba97 bpf: Make bpf.h self-contained
PR:		286539
MFC after:	3 days
Approved by:	re (cperciva)

(cherry picked from commit 981af1192c)
(cherry picked from commit 48881a2680)
2025-05-07 12:05:08 +00:00
Mark Johnston 399bc0c182 netinet: Make in_systm.h self-contained
PR:		286539
MFC after:	3 days
Approved by:	re (cperciva)

(cherry picked from commit 75d173a848)
(cherry picked from commit 02dde7c43f)
2025-05-07 12:04:59 +00:00
Michael Tuexen 976aa65e3e tcp: improve KASSERT in limited retransmit
When doing a limited retransmit, allow up to 2 * MSS - 1 if the
Nagle algorithm has been disabled.

PR:			282605
Approved by:		re (cperciva)
Reviewed by:		cc, Peter Lei
Sponsored by:		Netflix, Inc.
Differential Revision:	https://reviews.freebsd.org/D49922

(cherry picked from commit 934caaec3a)
(cherry picked from commit 0906658c34)
2025-05-06 21:18:24 +02:00
Michal Meloun c3ecee5b38 arm: remove accidentally added -Map switch to linker
Approved by:	re (cperciva)
Fixes:	ba045ba49d

(cherry picked from commit 0283eebb4a)
(cherry picked from commit 0aca1d4e7c)
2025-05-05 00:02:29 -07:00
Michal Meloun 95d87d5f56 arm: Improve the creation of kernel.bin
Instead of relinking the kernel without elf headers, replace them with
a binary blob of the same length starting with a jump to the kernel's start
address. This ensures that all symbols stay at the same offsets as in
the original kernel, so kernel.debug remains valid also for kernel.bin.

Also ensure that the awk script used runs with  the neutral locale defined.
Awk 'write' is a locale compilant, and  script is used to write binary data
to a file, so it needs to ensure that  bytes > 127 are written unchanged.

While I'm on, set the neutral locale also for arm64, where the same script is
used to generate the kernel booti image.

Reviewed by:	emaste, imp
Approved by:	re (cperciva)
Differential Revision:	https://reviews.freebsd.org/D47488

(cherry picked from commit ba045ba49d)
(cherry picked from commit bec5167645)
2025-05-05 00:01:44 -07:00
Rick Macklem 2773c07181 mountd: Fix updating the network/host(s) for an exports line
Mountd reloads the exports(5) file(s) when it receives a SIGHUP
and then compares the old and new exports, updating any ones that
have changed in the kernel.

Without this patch, mountd failed to recognize that a network/host(s)
had changed, if there was no other change to the exports line.
As such, the change of network/hosts(s) did not take effect until
the mountd daemon was (re)started.

This patch fixes the code so that it checks for changes in
the network/host(s) list for an exports line.

PR:	286260
Approved by:	re (cperciva)

(cherry picked from commit 68daa781c1)
(cherry picked from commit 37abcf06f2)
2025-05-04 12:13:49 -07:00
Mark Johnston 97a057f168 vm_pageout: Disallow invalid values for act_scan_laundry_weight
PR:		234167
MFC after:	2 weeks
Approved by:	re (cperciva)

(cherry picked from commit d8b03c5904)
(cherry picked from commit 098e4ecd65)
2025-05-03 20:22:08 +00:00
Colin Percival 3ce28e0624 14.3: create releng/14.3 branch
Update from PRERELEASE to BETA1
Switch pkg(8) configuration to use the quarterly repository
Bump __FreeBSD_version

Approved by:	re (implicit)
Sponsored by:	Amazon
2025-05-02 00:00:00 +00:00
3275 changed files with 240343 additions and 230571 deletions

No files matched your search

+6
View File
@@ -51,6 +51,12 @@
# xargs -n1 | sort | uniq -d;
# done
# 20250524: don't install zoneinfo version
OLD_FILES+=usr/share/zoneinfo/version
# 20250521: NDFREE(9) -> NDFREE_PNBUF(9)
OLD_FILES+=usr/share/man/man9/NDFREE.9.gz
# 20250419: removal of iwlwifi firmware files
OLD_FILES+=usr/share/doc/legal/intel_iwlwifi_firmware.LICENCE
+17
View File
@@ -10,6 +10,23 @@ newline. Entries should be separated by a newline.
Changes to this file should not be MFCed.
1ee62f354ab0:
ps(1)'s options '-a' and '-A', when combined with any other one
affecting the selection of processes except for '-X' and '-x', would
have no effect, in contradiction with the rule that one process is
listed as soon as any of the specified options selects it (inclusive
OR), which is both mandated by POSIX and arguably a natural expectation.
This bug has been fixed.
As a practical consequence, specifying '-a'/'-A' now causes all
processes to be listed regardless of other selection options (except for
'-X' and '-x', which still apply). In particular, to list only
processes from specific jails, one must not use '-a' with '-J'. Option
'-J', contrary to its apparent initial intent, never worked as a filter
in practice (except by accident with '-a' due to the bug), but instead
as any other selection options (e.g., '-U', '-p', '-G', etc.) subject to
the "inclusive OR" rule.
a2132d91739d:
ps(1)'s '-U' option has been changed to select processes by their real
user IDs instead of their effective one, in accordance with POSIX and
+245
View File
@@ -12,6 +12,251 @@ Items affecting the ports and packages system can be found in
/usr/ports/UPDATING. Please read that file before updating system packages
and/or ports.
20260630:
14.3-RELEASE-p16 EN-26:16.arm64
SA-26:37.vm
SA-26:39.execve
SA-26:40.zfs
SA-26:41.libalias
SA-26:42.unlinkat
SA-26:43.tcp
SA-26:44.posixshm
SA-26:45.audit
SA-26:46.ktls
SA-26:47.linux
SA-26:48.compat32
SA-26:49.iconv
32-bit setcontext(2) and swapcontext(2) fail on arm64. [EN-26:16.arm64]
Use-after-free in device pager page list. [SA-26:37.vm]
Local privilege escalation via execve(2) TOCTOU race. [SA-26:39.execve]
Multiple vulnerabilities in OpenZFS. [SA-26:40.zfs]
Buffer overflow in libalias RTSP handler. [SA-26:41.libalias]
unlinkat(2) ignores AT_RESOLVE_BENEATH flag. [SA-26:42.unlinkat]
Use-after-free in TCP RACK stack option handler. [SA-26:43.tcp]
Incorrect audit records for ptrace(2) syscall requests. [SA-26:45.audit]
Remote DOS via uninitialized memory access in KTLS receive. [SA-26:46.ktls]
Kernel stack disclosure in Linux compatibility layer. [SA-26:47.linux]
Kernel stack disclosure in 32-bit compatibility support. [SA-26:48.compat32]
Multiple vulnerabilities in iconv(3). [SA-26:49.iconv]
20260609:
14.3-RELEASE-p15 EN-26:15.openssl
SA-26:25.thr
SA-26:26.ktls
SA-26:27.sound
SA-26:28.capsicum
SA-26:29.ip6_multicast
SA-26:30.linux
SA-26:31.arm64
SA-26:32.elf
SA-26:33.unbound
SA-26:34.vt
SA-26:35.openssl
SA-26:36.ldns
Update OpenSSL to 3.0.20 and 3.5.6. [EN-26:15.openssl]
Missing permission check in thr_kill2(2). [SA-26:25.thr]
Arbitrary file overwrite via the KTLS receive path. [SA-26:26.ktls]
Multiple vulnerabilities in the sound(4) mmap path. [SA-26:27.sound]
sigqueue(2) missing capability mode restriction. [SA-26:28.capsicum]
Use-after-free bug in the IPV6_MSFILTER socket option handler. [SA-26:29.ip6_multicast]
Flaw in Linuxulator execution of setugid binaries. [SA-26:30.linux]
Arm CPU errata may bypass page table permission changes. [SA-26:31.arm64]
ASLR bypass for setuid executables via procctl(2). [SA-26:32.elf]
Multiple vulnerabilities in unbound. [SA-26:33.unbound]
Integer overflow in vt(4) CONS_HISTORY ioctl. [SA-26:34.vt]
Multiple vulnerabilities in OpenSSL. [SA-26:35.openssl]
Insufficient response validation in the ldns stub resolver. [SA-26:36.ldns]
20260520:
14.3-RELEASE-p14 SA-26:18.setcred
SA-26:19.file
SA-26:20.fusefs
SA-26:21.ptrace
SA-26:22.libcasper
SA-26:23.bsdinstall
SA-26:24.cap_net
EN-26:13.freebsd-update
Stack buffer overflow via setcred(2). [SA-26:18.setcred]
Kernel use-after-free via file descriptor syscalls. [SA-26:19.file]
Heap overflow in FUSE_LISTXATTR. [SA-26:20.fusefs]
Missing validation in ptrace(PT_SC_REMOTE). [SA-26:21.ptrace]
Stack overflow via select() file descriptor set overflow. [SA-26:22.libcasper]
Remote code execution via Wi-Fi access point scans. [SA-26:23.bsdinstall]
Incorrect libcap_net limitation list manipulation. [SA-26:24.cap_net]
freebsd-update attempts to merge a generated file. [EN-26:13.freebsd-update]
20260430:
14.3-RELEASE-p13 EN-26:11.dhclient
dhclient(8) lease validation is too strict. [EN-26:11.dhclient]
20260429:
14.3-RELEASE-p12 SA-26:12.dhclient
SA-26:13.exec
SA-26:14.pf
SA-26:15.dhclient
SA-26:16.libnv
SA-26:17.libnv
EN-26:09.tzdata
EN-26:10.amd64
Remote code execution via malicious DHCP options. [SA-26:12.dhclient]
Local privilege escalation via execve(). [SA-26:13.exec]
pf can overflow the stack parsing crafted SCTP packets. [SA-26:14.pf]
Remotely triggerable out-of-bounds heap write in dhclient. [SA-26:15.dhclient]
Stack overflow via select() file descriptor set overflow. [SA-26:16.libnv]
Heap overflow in libnv. [SA-26:17.libnv]
Timezone database information update. [EN-26:09.tzdata]
TLB invalidation bug on AMD systems with INVLPGB. [EN-26:10.amd64]
20260421:
14.3-RELEASE-p11 SA-26:10.tty
SA-26:11.amd64
EN-26:05.vm
EN-26:06.timerfd
Kernel use-after-free bug in the TIOCNOTTY handler. [SA-26:10.tty]
Missing large page handling in pmap_pkru_update_range(). [SA-26:11.amd64]
The page fault handler fails to zero memory. [EN-26:05.vm]
Periodic timerfd(2) timers may produce incorrect results. [EN-26:06.timerfd]
20260325:
14.3-RELEASE-p10 SA-26:06.tcp
SA-26:08.rpcsec_gss
SA-26:09.pf
TCP: remotely exploitable DoS vector (mbuf leak). [SA-26:06.tcp]
Remote code execution via RPCSEC_GSS packet validation. [SA-26:08.rpcsec_gss]
pf silently ignores certain rules. [SA-26:09.pf]
20250224:
14.3-RELEASE-p9 SA-26:04.jail
SA-26:05.route
Jail chroot escape via fd exchange with a different jail. [SA-26:04.jail]
Local DoS and possible privilege escalation via routing sockets. [SA-26:05.route]
20250127:
14.3-RELEASE-p8 SA-26:01.openssl
SA-26:02.jail
EN-26:02.arm64
EN-26:03.vm
Fix multiple vulnerabilities in OpenSSL. [SA-26:01.openssl]
Jail escape by a privileged user via nullfs. [SA-26:02.jail]
arm64 SVE signal context misalignment. [EN-26:02.arm64]
The page fault handler fails to zero memory. [EN-26:03.vm]
20251216:
14.3-RELEASE-p7 SA-25:11.ipfw
SA-25:12.rtsold
ipfw denial of service. [SA-25:11.ipfw]
Remote code execution via ND6 Router Advertisements. [SA-25:12.rtsold]
20251126:
14.3-RELEASE-p6 SA-25:10.unbound
Fix cache poison in local-unbound service. [SA-25:10.unbound]
20251022:
14.3-RELEASE-p5 SA-25:09.netinet
SO_REUSEPORT_LB breaks connect(2) for UDP sockets. [SA-25:09.netinet]
20250930:
14.3-RELEASE-p4 EN-25:18.freebsd-update
SA-25:08.openssl
Fix freebsd-update(8) installing libraries in incorrect order. [EN-25:18.freebsd-update]
Fix multiple vulnerabilities in OpenSSL. [SA-25:08.openssl]
20250916:
14.3-RELEASE-p3 EN-25:15.arm64
EN-25:16.vfs
EN-25:17.bnxt
Fix arm64 syscall(2) allows unprivileged user to panic kernel. [EN-25:15.arm64]
Fix copy_file_range(2) failing to set output parameters. [EN-25:16.vfs]
Fix bnxt(4) failing to set media type in some cases. [EN-25:17.bnxt]
20250808:
14.3-RELEASE-p2 EN-25:12.efi
EN-25:13.wlan_tkip
EN-25:14.route
SA-25:07.libarchive
Fix bsdinstall(8) not copying the correct loader on systems with IA32 UEFI
firmware. [EN-25:12.efi]
Fix net80211 TKIP crypto support failing for some drivers. [EN-25:13.wlan_tkip]
Fix route(8) monitor buffering too much when redirected to a file. [EN-25:14.route]
Update libarchive to 3.8.1 to fix integer overflow leading to double
free. [SA-25:07.libarchive]
20250702:
14.3-RELEASE-p1 EN-25:10.zfs
Fix corruption in ZFS replication streams from encrypted datasets [EN-25:10.zfs]
20250610:
14.3-RELEASE.
20250419:
LinuxKPI alloc routines were changed to return physically contiguous
memory where expected. These changes may require out-of-tree drivers
+2 -2
View File
@@ -35,7 +35,7 @@
.\"
.\" @(#)ps.1 8.3 (Berkeley) 4/18/94
.\"
.Dd April 28, 2025
.Dd May 06, 2025
.Dt PS 1
.Os
.Sh NAME
@@ -285,7 +285,7 @@ of the jail.
Use
.Fl J
.Sy 0
to display only host processes.
to request display of host processes.
Implies
.Fl x
by default.
+9 -3
View File
@@ -747,8 +747,8 @@ FORK_TEST(Capmode, NewThread) {
close(thread_pipe[1]);
}
static volatile sig_atomic_t had_signal = 0;
static void handle_signal(int) { had_signal = 1; }
static volatile sig_atomic_t signal_cnt = 0;
static void handle_signal(int) { signal_cnt++; }
FORK_TEST(Capmode, SelfKill) {
pid_t me = getpid();
@@ -766,7 +766,13 @@ FORK_TEST(Capmode, SelfKill) {
// Can only kill(2) to own pid.
EXPECT_CAPMODE(kill(child, SIGUSR1));
EXPECT_OK(kill(me, SIGUSR1));
EXPECT_EQ(1, had_signal);
EXPECT_EQ(1, signal_cnt);
union sigval sv;
sv.sival_int = 0x1234;
EXPECT_CAPMODE(sigqueue(child, SIGUSR1, sv));
EXPECT_OK(sigqueue(me, SIGUSR1, sv));
EXPECT_EQ(2, signal_cnt);
signal(SIGUSR1, original);
}
+13
View File
@@ -184,6 +184,19 @@ ldns_lookup_table ldns_error_str[] = {
{ LDNS_STATUS_INVALID_SVCPARAM_VALUE,
"Invalid wireformat of a value "
"in the ServiceParam rdata field of SVCB or HTTPS RR" },
{ LDNS_STATUS_NOT_EDE,
"The EDNS option is not an extended error code" },
{ LDNS_STATUS_EDE_OPTION_MALFORMED,
"The extended error code option is malformed, expected "
"at least 2 bytes of option data" },
{ LDNS_STATUS_EQUAL_RR,
"An identical RR already existed in the zone" },
{ LDNS_STATUS_ID_DID_NOT_MATCH,
"Response ID did not match the query ID" },
{ LDNS_STATUS_QDCOUNT_MUST_BE_ONE,
"The query section MUST contain exactly one question" },
{ LDNS_STATUS_QUERY_DID_NOT_MATCH,
"The question in the response did not match the query" },
{ 0, NULL }
};
+7 -1
View File
@@ -141,7 +141,13 @@ enum ldns_enum_status {
LDNS_STATUS_RESERVED_SVCPARAM_KEY,
LDNS_STATUS_NO_SVCPARAM_VALUE_EXPECTED,
LDNS_STATUS_SVCPARAM_KEY_MORE_THAN_ONCE,
LDNS_STATUS_INVALID_SVCPARAM_VALUE
LDNS_STATUS_INVALID_SVCPARAM_VALUE,
LDNS_STATUS_NOT_EDE,
LDNS_STATUS_EDE_OPTION_MALFORMED,
LDNS_STATUS_EQUAL_RR,
LDNS_STATUS_ID_DID_NOT_MATCH,
LDNS_STATUS_QDCOUNT_MUST_BE_ONE,
LDNS_STATUS_QUERY_DID_NOT_MATCH
};
typedef enum ldns_enum_status ldns_status;
+90 -2
View File
@@ -441,6 +441,50 @@ ldns_udp_bgsend2(ldns_buffer *qbin,
return ldns_udp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
}
/** helper sockaddr compare function. returns -1, 0 or 1. */
static int
ldns_sockaddr_cmp(const struct sockaddr_storage* addr1, socklen_t len1,
const struct sockaddr_storage* addr2, socklen_t len2)
{
struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1;
struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2;
struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1;
struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2;
if(len1 < len2)
return -1;
if(len1 > len2)
return 1;
assert(len1 == len2);
if( p1_in->sin_family < p2_in->sin_family)
return -1;
if( p1_in->sin_family > p2_in->sin_family)
return 1;
assert( p1_in->sin_family == p2_in->sin_family );
/* compare ip4 */
if( p1_in->sin_family == AF_INET ) {
/* just order it, ntohs not required */
if(p1_in->sin_port < p2_in->sin_port)
return -1;
if(p1_in->sin_port > p2_in->sin_port)
return 1;
assert(p1_in->sin_port == p2_in->sin_port);
return memcmp(&p1_in->sin_addr, &p2_in->sin_addr,
sizeof(p1_in->sin_addr));
} else if (p1_in6->sin6_family == AF_INET6) {
/* just order it, ntohs not required */
if(p1_in6->sin6_port < p2_in6->sin6_port)
return -1;
if(p1_in6->sin6_port > p2_in6->sin6_port)
return 1;
assert(p1_in6->sin6_port == p2_in6->sin6_port);
return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
sizeof(p1_in6->sin6_addr));
} else {
/* eek unknown type, perform this comparison for sanity. */
return memcmp(addr1, addr2, len1);
}
}
static ldns_status
ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin,
const struct sockaddr_storage *to , socklen_t tolen,
@@ -449,6 +493,8 @@ ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin,
{
int sockfd;
uint8_t *answer;
struct sockaddr_storage reply_addr;
socklen_t reply_addr_len;
sockfd = ldns_udp_bgsend_from(qbin, to, tolen, from, fromlen, timeout);
@@ -467,13 +513,21 @@ ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin,
* but returns a 'NETWORK_ERROR' much like a timeout. */
ldns_sock_nonblock(sockfd);
answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL);
reply_addr_len = sizeof(reply_addr);
memset(&reply_addr, 0, reply_addr_len);
answer = ldns_udp_read_wire(sockfd, answer_size, &reply_addr,
&reply_addr_len);
close_socket(sockfd);
if (!answer) {
/* oops */
return LDNS_STATUS_NETWORK_ERR;
}
/* Check that the reply came from the to addr. */
if(ldns_sockaddr_cmp(to, tolen, &reply_addr, reply_addr_len) != 0) {
free(answer);
return LDNS_STATUS_NETWORK_ERR;
}
*result = answer;
return LDNS_STATUS_OK;
@@ -512,6 +566,10 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf
assert(r != NULL);
/* The query should at least have one question */
if(ldns_buffer_limit(qb) < 6 || ldns_buffer_read_u16_at(qb, 4) != 1)
return LDNS_STATUS_QDCOUNT_MUST_BE_ONE;
status = LDNS_STATUS_OK;
rtt = ldns_resolver_rtt(r);
ns_array = ldns_resolver_nameservers(r);
@@ -599,6 +657,16 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf
ldns_resolver_set_nameserver_rtt(r, i, LDNS_RESOLV_RTT_INF);
status = send_status;
}
if(reply_bytes && ldns_buffer_limit(qb) >= 2) {
uint16_t txid = ldns_buffer_read_u16_at(qb, 0);
if(reply_size < 2 ||
ldns_read_uint16(reply_bytes) != txid) {
status = LDNS_STATUS_ID_DID_NOT_MATCH;
LDNS_FREE(reply_bytes);
reply_bytes = NULL;
reply_size = 0;
}
}
/* obey the fail directive */
if (!reply_bytes) {
@@ -608,7 +676,7 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf
LDNS_FREE(src);
}
LDNS_FREE(ns);
return LDNS_STATUS_ERR;
return status ? status : LDNS_STATUS_ERR;
} else {
LDNS_FREE(ns);
continue;
@@ -670,6 +738,26 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf
#endif /* HAVE_SSL */
LDNS_FREE(reply_bytes);
if (reply) {
ldns_pkt *query = NULL;
if(ldns_pkt_qdcount(reply) != 1) {
status = LDNS_STATUS_QDCOUNT_MUST_BE_ONE;
ldns_pkt_free(reply);
reply = NULL;
} else if(ldns_wire2pkt(&query
, ldns_buffer_begin(qb)
, ldns_buffer_position(qb)) != LDNS_STATUS_OK
|| ldns_pkt_qdcount(query) != 1
|| ldns_rr_compare(ldns_rr_list_rr(ldns_pkt_question(query),0)
,ldns_rr_list_rr(ldns_pkt_question(reply),0))){
status = LDNS_STATUS_QUERY_DID_NOT_MATCH;
ldns_pkt_free(reply);
reply = NULL;
}
ldns_pkt_free(query);
}
if (result) {
*result = reply;
}
+1 -1
View File
@@ -20,7 +20,7 @@ the actual statements in the files are controlling.
libarchive/mtree.5
* The following source files are in the public domain:
libarchive/archive_getdate.c
libarchive/archive_parse_date.c
* The following source files are triple-licensed with the ability to choose
from CC0 1.0 Universal, OpenSSL or Apache 2.0 licenses:
+8
View File
@@ -1,3 +1,11 @@
Jun 01, 2026: libarchive 3.8.1 released
May 20, 2025: libarchive 3.8.0 released
Mar 30, 2025: libarchive 3.7.9 released
Mar 20, 2025: libarchive 3.7.8 released
Oct 13, 2024: libarchive 3.7.7 released
Sep 23, 2024: libarchive 3.7.6 released
+6 -3
View File
@@ -85,13 +85,14 @@ Currently, the library automatically detects and reads the following formats:
* PWB binary cpio
* ISO9660 CD-ROM images (with optional Rockridge or Joliet extensions)
* ZIP archives (with uncompressed or "deflate" compressed entries, including support for encrypted Zip archives)
* ZIPX archives (with support for bzip2, ppmd8, lzma and xz compressed entries)
* ZIPX archives (with support for bzip2, zstd, ppmd8, lzma and xz compressed entries)
* GNU and BSD 'ar' archives
* 'mtree' format
* 7-Zip archives (including archives that use zstandard compression)
* Microsoft CAB format
* LHA and LZH archives
* RAR and RAR 5.0 archives (with some limitations due to RAR's proprietary status)
* WARC archives
* XAR archives
The library also detects and handles any of the following before evaluating the archive:
@@ -120,15 +121,18 @@ The library can create archives in any of the following formats:
* PWB binary cpio
* shar archives
* ZIP archives (with uncompressed or "deflate" compressed entries)
* ZIPX archives (with bzip2, zstd, lzma or xz compressed entries)
* GNU and BSD 'ar' archives
* 'mtree' format
* ISO9660 format
* 7-Zip archives
* 7-Zip archives (including archives that use zstandard compression)
* WARC archives
* XAR archives
When creating archives, the result can be filtered with any of the following:
* uuencode
* base64
* gzip compression
* bzip2 compression
* compress/LZW compression
@@ -241,4 +245,3 @@ questions we are asked about libarchive:
appropriate. It has many advantages over other tar formats
(including the legacy GNU tar format) and is widely supported by
current tar implementations.
@@ -0,0 +1,19 @@
#!/bin/sh
set -eux
# Uncommenting these adds a full minute to the CI time
#brew update > /dev/null
#brew upgrade > /dev/null
# This does an upgrade if the package is already installed
brew install \
autoconf \
automake \
libtool \
pkg-config \
cmake \
xz \
lz4 \
zstd \
libxml2 \
openssl
+1 -1
View File
@@ -1206,7 +1206,7 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
else
strcpy(date, "invalid mtime");
fprintf(out, "%s%3d %-8s %-8s %8s %12s %s",
fprintf(out, "%s%3u %-8s %-8s %8s %12s %s",
archive_entry_strmode(entry),
archive_entry_nlink(entry),
uname, gname, size, date,
@@ -189,10 +189,10 @@ DEFINE_TEST(test_format_newc)
gid = from_hex(e + 30, 8); /* gid */
assertEqualMem(e + 38, "00000003", 8); /* nlink */
t = from_hex(e + 46, 8); /* mtime */
failure("t=%#08jx now=%#08jx=%jd", (intmax_t)t, (intmax_t)now,
failure("t=%#08jx now=%#08jx=%jd", (uintmax_t)t, (uintmax_t)now,
(intmax_t)now);
assert(t <= now); /* File wasn't created in future. */
failure("t=%#08jx now - 2=%#08jx=%jd", (intmax_t)t, (intmax_t)now - 2,
failure("t=%#08jx now - 2=%#08jx=%jd", (uintmax_t)t, (uintmax_t)now - 2,
(intmax_t)now - 2);
assert(t >= now - 2); /* File was created w/in last 2 secs. */
failure("newc format stores body only with last appearance of a link\n"
@@ -219,7 +219,7 @@ 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)
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Mode: Group members bits and others bits do not work. */
assertEqualInt(0xa180, from_hex(e + 14, 8) & 0xffc0);
#else
@@ -230,7 +230,7 @@ DEFINE_TEST(test_format_newc)
assertEqualMem(e + 38, "00000001", 8); /* nlink */
t2 = from_hex(e + 46, 8); /* mtime */
failure("First entry created at t=%#08jx this entry created"
" at t2=%#08jx", (intmax_t)t, (intmax_t)t2);
" at t2=%#08jx", (uintmax_t)t, (uintmax_t)t2);
assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */
assertEqualMem(e + 54, "00000005", 8); /* File size */
fs = (uint64_t)from_hex(e + 54, 8);
@@ -266,7 +266,7 @@ DEFINE_TEST(test_format_newc)
#endif
t2 = from_hex(e + 46, 8); /* mtime */
failure("First entry created at t=%#08jx this entry created at"
"t2=%#08jx", (intmax_t)t, (intmax_t)t2);
"t2=%#08jx", (uintmax_t)t, (uintmax_t)t2);
assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */
assertEqualMem(e + 54, "00000000", 8); /* File size */
fs = (uint64_t)from_hex(e + 54, 8);
@@ -300,7 +300,7 @@ DEFINE_TEST(test_format_newc)
assertEqualMem(e + 38, "00000003", 8); /* nlink */
t2 = from_hex(e + 46, 8); /* mtime */
failure("First entry created at t=%#08jx this entry created at"
"t2=%#08jx", (intmax_t)t, (intmax_t)t2);
"t2=%#08jx", (uintmax_t)t, (uintmax_t)t2);
assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */
assertEqualInt(10, from_hex(e + 54, 8)); /* File size */
fs = (uint64_t)from_hex(e + 54, 8);
+1 -1
View File
@@ -52,7 +52,7 @@ test_create(void)
* #ifdef this section out. Most of the test below is
* still valid. */
memset(&times, 0, sizeof(times));
#if defined(_WIN32) && !defined(CYGWIN)
#if defined(_WIN32) && !defined(__CYGWIN__)
times.actime = 86400;
times.modtime = 86400;
#else
+4 -4
View File
@@ -18,7 +18,7 @@ is_octal(const char *p, size_t l)
return (1);
}
static long long int
static unsigned long long int
from_octal(const char *p, size_t l)
{
long long int r = 0;
@@ -117,7 +117,7 @@ DEFINE_TEST(test_option_c)
gid = (int)from_octal(e + 30, 6);
assertEqualMem(e + 36, "000001", 6); /* nlink */
failure("file entries should not have rdev set (dev field was 0%o)",
dev);
(unsigned int)dev);
assertEqualMem(e + 42, "000000", 6); /* rdev */
t = from_octal(e + 48, 11); /* mtime */
assert(t <= now); /* File wasn't created in future. */
@@ -133,7 +133,7 @@ DEFINE_TEST(test_option_c)
assert(is_octal(e, 76)); /* Entire header is octal digits. */
assertEqualMem(e + 0, "070707", 6); /* Magic */
assertEqualInt(dev, from_octal(e + 6, 6)); /* dev */
assert(ino != from_octal(e + 12, 6)); /* ino */
assert(ino != (int)from_octal(e + 12, 6)); /* ino */
#if !defined(_WIN32) || defined(__CYGWIN__)
/* On Windows, symbolic link and group members bits and
* others bits do not work. */
@@ -163,7 +163,7 @@ DEFINE_TEST(test_option_c)
assertEqualInt(dev, from_octal(e + 6, 6));
/* Ino must be different from first entry. */
assert(is_octal(e + 12, 6)); /* ino */
assert(ino != from_octal(e + 12, 6));
assert(ino != (int)from_octal(e + 12, 6));
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Group members bits and others bits do not work. */
assertEqualMem(e + 18, "040777", 6); /* Mode */
+54 -3
View File
@@ -34,12 +34,15 @@
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
#define ARCHIVE_VERSION_NUMBER 3007007
#define ARCHIVE_VERSION_NUMBER 3008001
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
#include <stdio.h> /* For FILE * */
#if ARCHIVE_VERSION_NUMBER < 4000000
/* time_t is slated to be removed from public includes in 4.0 */
#include <time.h> /* For time_t */
#endif
/*
* Note: archive.h is for use outside of libarchive; the configuration
@@ -63,12 +66,15 @@
#define __LA_INT64_T_DEFINED
# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
typedef __int64 la_int64_t;
typedef unsigned __int64 la_uint64_t;
# else
# include <unistd.h> /* ssize_t */
# if defined(_SCO_DS) || defined(__osf__)
typedef long long la_int64_t;
typedef unsigned long long la_uint64_t;
# else
typedef int64_t la_int64_t;
typedef uint64_t la_uint64_t;
# endif
# endif
#endif
@@ -94,6 +100,22 @@ typedef ssize_t la_ssize_t;
# endif
#endif
#if ARCHIVE_VERSION_NUMBER < 4000000
/* Use the platform types for time_t */
#define __LA_TIME_T time_t
#else
/* Use 64-bits integer types for time_t */
#define __LA_TIME_T la_int64_t
#endif
#if ARCHIVE_VERSION_NUMBER < 4000000
/* Use the platform types for dev_t */
#define __LA_DEV_T dev_t
#else
/* Use 64-bits integer types for dev_t */
#define __LA_DEV_T la_int64_t
#endif
/* Large file support for Android */
#if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__)
#include "android_lf.h"
@@ -132,7 +154,7 @@ typedef ssize_t la_ssize_t;
#define __LA_PRINTF(fmtarg, firstvararg) /* nothing */
#endif
#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1
#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
# define __LA_DEPRECATED __attribute__((deprecated))
#else
# define __LA_DEPRECATED
@@ -155,7 +177,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
#define ARCHIVE_VERSION_ONLY_STRING "3.7.7"
#define ARCHIVE_VERSION_ONLY_STRING "3.8.1"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
@@ -178,6 +200,23 @@ __LA_DECL const char * archive_liblzma_version(void);
__LA_DECL const char * archive_bzlib_version(void);
__LA_DECL const char * archive_liblz4_version(void);
__LA_DECL const char * archive_libzstd_version(void);
__LA_DECL const char * archive_liblzo2_version(void);
__LA_DECL const char * archive_libexpat_version(void);
__LA_DECL const char * archive_libbsdxml_version(void);
__LA_DECL const char * archive_libxml2_version(void);
__LA_DECL const char * archive_mbedtls_version(void);
__LA_DECL const char * archive_nettle_version(void);
__LA_DECL const char * archive_openssl_version(void);
__LA_DECL const char * archive_libmd_version(void);
__LA_DECL const char * archive_commoncrypto_version(void);
__LA_DECL const char * archive_cng_version(void);
__LA_DECL const char * archive_wincrypt_version(void);
__LA_DECL const char * archive_librichacl_version(void);
__LA_DECL const char * archive_libacl_version(void);
__LA_DECL const char * archive_libattr_version(void);
__LA_DECL const char * archive_libiconv_version(void);
__LA_DECL const char * archive_libpcre_version(void);
__LA_DECL const char * archive_libpcre2_version(void);
/* Declare our basic types. */
struct archive;
@@ -449,6 +488,8 @@ __LA_DECL int archive_read_support_format_by_code(struct archive *, int);
__LA_DECL int archive_read_support_format_cab(struct archive *);
__LA_DECL int archive_read_support_format_cpio(struct archive *);
__LA_DECL int archive_read_support_format_empty(struct archive *);
/* archive_read_support_format_gnutar() is an alias for historical reasons
* of archive_read_support_format_tar(). */
__LA_DECL int archive_read_support_format_gnutar(struct archive *);
__LA_DECL int archive_read_support_format_iso9660(struct archive *);
__LA_DECL int archive_read_support_format_lha(struct archive *);
@@ -828,6 +869,10 @@ __LA_DECL int archive_write_set_format_filter_by_ext(struct archive *a, const ch
__LA_DECL int archive_write_set_format_filter_by_ext_def(struct archive *a, const char *filename, const char * def_ext);
__LA_DECL int archive_write_zip_set_compression_deflate(struct archive *);
__LA_DECL int archive_write_zip_set_compression_store(struct archive *);
__LA_DECL int archive_write_zip_set_compression_lzma(struct archive *);
__LA_DECL int archive_write_zip_set_compression_xz(struct archive *);
__LA_DECL int archive_write_zip_set_compression_bzip2(struct archive *);
__LA_DECL int archive_write_zip_set_compression_zstd(struct archive *);
/* Deprecated; use archive_write_open2 instead */
__LA_DECL int archive_write_open(struct archive *, void *,
archive_open_callback *, archive_write_callback *,
@@ -1083,6 +1128,10 @@ __LA_DECL int archive_compression(struct archive *)
__LA_DEPRECATED;
#endif
/* Parses a date string relative to the current time.
* NOTE: This is not intended for general date parsing, and the resulting timestamp should only be used for libarchive. */
__LA_DECL time_t archive_parse_date(time_t now, const char *datestr);
__LA_DECL int archive_errno(struct archive *);
__LA_DECL const char *archive_error_string(struct archive *);
__LA_DECL const char *archive_format_name(struct archive *);
@@ -1201,8 +1250,10 @@ __LA_DECL int archive_match_include_gname_w(struct archive *,
const wchar_t *);
/* Utility functions */
#if ARCHIVE_VERSION_NUMBER < 4000000
/* Convenience function to sort a NULL terminated list of strings */
__LA_DECL int archive_utility_string_sort(char **);
#endif
#ifdef __cplusplus
}
+12 -2
View File
@@ -1185,8 +1185,13 @@ archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text,
/* Set remaining fields to blank. */
for (n = fields; n < numfields; ++n)
field[n].start = field[n].end = NULL;
if (field[0].start == NULL || field[0].end == NULL) {
/* This should never happen */
return (ARCHIVE_FATAL);
}
if (field[0].start != NULL && *(field[0].start) == L'#') {
if (*(field[0].start) == L'#') {
/* Comment, skip entry */
continue;
}
@@ -1676,7 +1681,12 @@ archive_acl_from_text_nl(struct archive_acl *acl, const char *text,
for (n = fields; n < numfields; ++n)
field[n].start = field[n].end = NULL;
if (field[0].start != NULL && *(field[0].start) == '#') {
if (field[0].start == NULL || field[0].end == NULL) {
/* This should never happen */
return (ARCHIVE_FATAL);
}
if (*(field[0].start) == '#') {
/* Comment, skip entry */
continue;
}
@@ -80,4 +80,4 @@ int archive_acl_from_text_l(struct archive_acl *, const char * /* text */,
int archive_acl_from_text_nl(struct archive_acl *, const char * /* text */,
size_t /* size of text */, int /* type */, struct archive_string_conv *);
#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
#endif /* !ARCHIVE_ACL_PRIVATE_H_INCLUDED */
@@ -71,7 +71,7 @@ get_argument(struct archive_string *as, const char *p)
archive_string_empty(as);
/* Skip beginning space characters. */
while (*s != '\0' && *s == ' ')
while (*s == ' ')
s++;
/* Copy non-space characters. */
while (*s != '\0' && *s != ' ') {
@@ -64,6 +64,7 @@ typedef struct {
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
#include <bcrypt.h>
#define ARCHIVE_CRYPTOR_USE_CNG 1
/* Common in other bcrypt implementations, but missing from VS2008. */
#ifndef BCRYPT_SUCCESS
@@ -86,6 +87,7 @@ typedef struct {
#include <mbedtls/aes.h>
#include <mbedtls/md.h>
#include <mbedtls/pkcs5.h>
#define ARCHIVE_CRYPTOR_USE_MBED 1
#define AES_MAX_KEY_SIZE 32
#define AES_BLOCK_SIZE 16
@@ -105,6 +107,7 @@ typedef struct {
#endif
#include <nettle/aes.h>
#include <nettle/version.h>
#define ARCHIVE_CRYPTOR_USE_NETTLE 1
typedef struct {
#if NETTLE_VERSION_MAJOR < 3
@@ -125,6 +128,7 @@ typedef struct {
#elif defined(HAVE_LIBCRYPTO)
#include "archive_openssl_evp_private.h"
#define ARCHIVE_CRYPTOR_USE_OPENSSL 1
#define AES_BLOCK_SIZE 16
#define AES_MAX_KEY_SIZE 32
@@ -140,6 +144,10 @@ typedef struct {
#else
#if defined(_WIN32) && !defined(__CYGWIN__) && !(defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA)
#define ARCHIVE_CRYPTOR_USE_WINCRYPT 1
#endif
#define AES_BLOCK_SIZE 16
#define AES_MAX_KEY_SIZE 32
typedef int archive_crypto_ctx;
+214 -130
View File
@@ -196,6 +196,13 @@ __archive_md5final(archive_md5_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM)
// These functions are available in macOS 10.4 and later, but deprecated from 10.15 onwards.
// We need to continue supporting this feature regardless, so suppress the warnings.
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif
static int
__archive_md5init(archive_md5_ctx *ctx)
{
@@ -218,13 +225,46 @@ __archive_md5final(archive_md5_ctx *ctx, void *md)
return (ARCHIVE_OK);
}
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
static int
__archive_md5init(archive_md5_ctx *ctx)
{
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
return (win_crypto_init(ctx, BCRYPT_MD5_ALGORITHM));
#else
return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_MD5));
#endif
}
static int
__archive_md5update(archive_md5_ctx *ctx, const void *indata,
size_t insize)
{
return (win_crypto_Update(ctx, indata, insize));
}
static int
__archive_md5final(archive_md5_ctx *ctx, void *md)
{
return (win_crypto_Final(md, 16, ctx));
}
#elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS)
static int
__archive_md5init(archive_md5_ctx *ctx)
{
mbedtls_md5_init(ctx);
#if MBEDTLS_VERSION_NUMBER > 0x03000000
if (mbedtls_md5_starts(ctx) == 0)
#else
if (mbedtls_md5_starts_ret(ctx) == 0)
#endif
return (ARCHIVE_OK);
else
return (ARCHIVE_FATAL);
@@ -234,7 +274,11 @@ static int
__archive_md5update(archive_md5_ctx *ctx, const void *indata,
size_t insize)
{
#if MBEDTLS_VERSION_NUMBER > 0x03000000
if (mbedtls_md5_update(ctx, indata, insize) == 0)
#else
if (mbedtls_md5_update_ret(ctx, indata, insize) == 0)
#endif
return (ARCHIVE_OK);
else
return (ARCHIVE_FATAL);
@@ -243,7 +287,11 @@ __archive_md5update(archive_md5_ctx *ctx, const void *indata,
static int
__archive_md5final(archive_md5_ctx *ctx, void *md)
{
#if MBEDTLS_VERSION_NUMBER > 0x03000000
if (mbedtls_md5_finish(ctx, md) == 0) {
#else
if (mbedtls_md5_finish_ret(ctx, md) == 0) {
#endif
mbedtls_md5_free(ctx);
return (ARCHIVE_OK);
} else {
@@ -311,31 +359,6 @@ __archive_md5final(archive_md5_ctx *ctx, void *md)
return (ARCHIVE_OK);
}
#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
static int
__archive_md5init(archive_md5_ctx *ctx)
{
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
return (win_crypto_init(ctx, BCRYPT_MD5_ALGORITHM));
#else
return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_MD5));
#endif
}
static int
__archive_md5update(archive_md5_ctx *ctx, const void *indata,
size_t insize)
{
return (win_crypto_Update(ctx, indata, insize));
}
static int
__archive_md5final(archive_md5_ctx *ctx, void *md)
{
return (win_crypto_Final(md, 16, ctx));
}
#else
static int
@@ -420,7 +443,11 @@ static int
__archive_ripemd160init(archive_rmd160_ctx *ctx)
{
mbedtls_ripemd160_init(ctx);
#if MBEDTLS_VERSION_NUMBER > 0x03000000
if (mbedtls_ripemd160_starts(ctx) == 0)
#else
if (mbedtls_ripemd160_starts_ret(ctx) == 0)
#endif
return (ARCHIVE_OK);
else
return (ARCHIVE_FATAL);
@@ -430,7 +457,11 @@ static int
__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
size_t insize)
{
#if MBEDTLS_VERSION_NUMBER > 0x03000000
if (mbedtls_ripemd160_update(ctx, indata, insize) == 0)
#else
if (mbedtls_ripemd160_update_ret(ctx, indata, insize) == 0)
#endif
return (ARCHIVE_OK);
else
return (ARCHIVE_FATAL);
@@ -439,7 +470,11 @@ __archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
static int
__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
{
#if MBEDTLS_VERSION_NUMBER > 0x03000000
if (mbedtls_ripemd160_finish(ctx, md) == 0) {
#else
if (mbedtls_ripemd160_finish_ret(ctx, md) == 0) {
#endif
mbedtls_ripemd160_free(ctx);
return (ARCHIVE_OK);
} else {
@@ -605,13 +640,42 @@ __archive_sha1final(archive_sha1_ctx *ctx, void *md)
return (ARCHIVE_OK);
}
#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
static int
__archive_sha1init(archive_sha1_ctx *ctx)
{
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
return (win_crypto_init(ctx, BCRYPT_SHA1_ALGORITHM));
#else
return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_SHA1));
#endif
}
static int
__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
size_t insize)
{
return (win_crypto_Update(ctx, indata, insize));
}
static int
__archive_sha1final(archive_sha1_ctx *ctx, void *md)
{
return (win_crypto_Final(md, 20, ctx));
}
#elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS)
static int
__archive_sha1init(archive_sha1_ctx *ctx)
{
mbedtls_sha1_init(ctx);
#if MBEDTLS_VERSION_NUMBER > 0x03000000
if (mbedtls_sha1_starts(ctx) == 0)
#else
if (mbedtls_sha1_starts_ret(ctx) == 0)
#endif
return (ARCHIVE_OK);
else
return (ARCHIVE_FATAL);
@@ -621,7 +685,11 @@ static int
__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
size_t insize)
{
#if MBEDTLS_VERSION_NUMBER > 0x03000000
if (mbedtls_sha1_update(ctx, indata, insize) == 0)
#else
if (mbedtls_sha1_update_ret(ctx, indata, insize) == 0)
#endif
return (ARCHIVE_OK);
else
return (ARCHIVE_FATAL);
@@ -630,7 +698,11 @@ __archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
static int
__archive_sha1final(archive_sha1_ctx *ctx, void *md)
{
#if MBEDTLS_VERSION_NUMBER > 0x03000000
if (mbedtls_sha1_finish(ctx, md) == 0) {
#else
if (mbedtls_sha1_finish_ret(ctx, md) == 0) {
#endif
mbedtls_sha1_free(ctx);
return (ARCHIVE_OK);
} else {
@@ -698,31 +770,6 @@ __archive_sha1final(archive_sha1_ctx *ctx, void *md)
return (ARCHIVE_OK);
}
#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
static int
__archive_sha1init(archive_sha1_ctx *ctx)
{
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
return (win_crypto_init(ctx, BCRYPT_SHA1_ALGORITHM));
#else
return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_SHA1));
#endif
}
static int
__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
size_t insize)
{
return (win_crypto_Update(ctx, indata, insize));
}
static int
__archive_sha1final(archive_sha1_ctx *ctx, void *md)
{
return (win_crypto_Final(md, 20, ctx));
}
#else
static int
@@ -873,13 +920,42 @@ __archive_sha256final(archive_sha256_ctx *ctx, void *md)
return (ARCHIVE_OK);
}
#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
static int
__archive_sha256init(archive_sha256_ctx *ctx)
{
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
return (win_crypto_init(ctx, BCRYPT_SHA256_ALGORITHM));
#else
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_256));
#endif
}
static int
__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
size_t insize)
{
return (win_crypto_Update(ctx, indata, insize));
}
static int
__archive_sha256final(archive_sha256_ctx *ctx, void *md)
{
return (win_crypto_Final(md, 32, ctx));
}
#elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS)
static int
__archive_sha256init(archive_sha256_ctx *ctx)
{
mbedtls_sha256_init(ctx);
#if MBEDTLS_VERSION_NUMBER > 0x03000000
if (mbedtls_sha256_starts(ctx, 0) == 0)
#else
if (mbedtls_sha256_starts_ret(ctx, 0) == 0)
#endif
return (ARCHIVE_OK);
else
return (ARCHIVE_FATAL);
@@ -889,7 +965,11 @@ static int
__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
size_t insize)
{
#if MBEDTLS_VERSION_NUMBER > 0x03000000
if (mbedtls_sha256_update(ctx, indata, insize) == 0)
#else
if (mbedtls_sha256_update_ret(ctx, indata, insize) == 0)
#endif
return (ARCHIVE_OK);
else
return (ARCHIVE_FATAL);
@@ -898,7 +978,11 @@ __archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
static int
__archive_sha256final(archive_sha256_ctx *ctx, void *md)
{
#if MBEDTLS_VERSION_NUMBER > 0x03000000
if (mbedtls_sha256_finish(ctx, md) == 0) {
#else
if (mbedtls_sha256_finish_ret(ctx, md) == 0) {
#endif
mbedtls_sha256_free(ctx);
return (ARCHIVE_OK);
} else {
@@ -962,31 +1046,6 @@ __archive_sha256final(archive_sha256_ctx *ctx, void *md)
return (ARCHIVE_OK);
}
#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
static int
__archive_sha256init(archive_sha256_ctx *ctx)
{
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
return (win_crypto_init(ctx, BCRYPT_SHA256_ALGORITHM));
#else
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_256));
#endif
}
static int
__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
size_t insize)
{
return (win_crypto_Update(ctx, indata, insize));
}
static int
__archive_sha256final(archive_sha256_ctx *ctx, void *md)
{
return (win_crypto_Final(md, 32, ctx));
}
#else
static int
@@ -1113,13 +1172,42 @@ __archive_sha384final(archive_sha384_ctx *ctx, void *md)
return (ARCHIVE_OK);
}
#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
static int
__archive_sha384init(archive_sha384_ctx *ctx)
{
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
return (win_crypto_init(ctx, BCRYPT_SHA384_ALGORITHM));
#else
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_384));
#endif
}
static int
__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
size_t insize)
{
return (win_crypto_Update(ctx, indata, insize));
}
static int
__archive_sha384final(archive_sha384_ctx *ctx, void *md)
{
return (win_crypto_Final(md, 48, ctx));
}
#elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS)
static int
__archive_sha384init(archive_sha384_ctx *ctx)
{
mbedtls_sha512_init(ctx);
#if MBEDTLS_VERSION_NUMBER > 0x03000000
if (mbedtls_sha512_starts(ctx, 1) == 0)
#else
if (mbedtls_sha512_starts_ret(ctx, 1) == 0)
#endif
return (ARCHIVE_OK);
else
return (ARCHIVE_FATAL);
@@ -1129,7 +1217,11 @@ static int
__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
size_t insize)
{
#if MBEDTLS_VERSION_NUMBER > 0x03000000
if (mbedtls_sha512_update(ctx, indata, insize) == 0)
#else
if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0)
#endif
return (ARCHIVE_OK);
else
return (ARCHIVE_FATAL);
@@ -1138,7 +1230,11 @@ __archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
static int
__archive_sha384final(archive_sha384_ctx *ctx, void *md)
{
#if MBEDTLS_VERSION_NUMBER > 0x03000000
if (mbedtls_sha512_finish(ctx, md) == 0) {
#else
if (mbedtls_sha512_finish_ret(ctx, md) == 0) {
#endif
mbedtls_sha512_free(ctx);
return (ARCHIVE_OK);
} else {
@@ -1202,31 +1298,6 @@ __archive_sha384final(archive_sha384_ctx *ctx, void *md)
return (ARCHIVE_OK);
}
#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
static int
__archive_sha384init(archive_sha384_ctx *ctx)
{
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
return (win_crypto_init(ctx, BCRYPT_SHA384_ALGORITHM));
#else
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_384));
#endif
}
static int
__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
size_t insize)
{
return (win_crypto_Update(ctx, indata, insize));
}
static int
__archive_sha384final(archive_sha384_ctx *ctx, void *md)
{
return (win_crypto_Final(md, 48, ctx));
}
#else
static int
@@ -1377,13 +1448,42 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
return (ARCHIVE_OK);
}
#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
static int
__archive_sha512init(archive_sha512_ctx *ctx)
{
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
return (win_crypto_init(ctx, BCRYPT_SHA512_ALGORITHM));
#else
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_512));
#endif
}
static int
__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
size_t insize)
{
return (win_crypto_Update(ctx, indata, insize));
}
static int
__archive_sha512final(archive_sha512_ctx *ctx, void *md)
{
return (win_crypto_Final(md, 64, ctx));
}
#elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS)
static int
__archive_sha512init(archive_sha512_ctx *ctx)
{
mbedtls_sha512_init(ctx);
#if MBEDTLS_VERSION_NUMBER > 0x03000000
if (mbedtls_sha512_starts(ctx, 0) == 0)
#else
if (mbedtls_sha512_starts_ret(ctx, 0) == 0)
#endif
return (ARCHIVE_OK);
else
return (ARCHIVE_FATAL);
@@ -1393,7 +1493,11 @@ static int
__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
size_t insize)
{
#if MBEDTLS_VERSION_NUMBER > 0x03000000
if (mbedtls_sha512_update(ctx, indata, insize) == 0)
#else
if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0)
#endif
return (ARCHIVE_OK);
else
return (ARCHIVE_FATAL);
@@ -1402,7 +1506,11 @@ __archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
static int
__archive_sha512final(archive_sha512_ctx *ctx, void *md)
{
#if MBEDTLS_VERSION_NUMBER > 0x03000000
if (mbedtls_sha512_finish(ctx, md) == 0) {
#else
if (mbedtls_sha512_finish_ret(ctx, md) == 0) {
#endif
mbedtls_sha512_free(ctx);
return (ARCHIVE_OK);
} else {
@@ -1466,31 +1574,6 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
return (ARCHIVE_OK);
}
#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
static int
__archive_sha512init(archive_sha512_ctx *ctx)
{
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
return (win_crypto_init(ctx, BCRYPT_SHA512_ALGORITHM));
#else
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_512));
#endif
}
static int
__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
size_t insize)
{
return (win_crypto_Update(ctx, indata, insize));
}
static int
__archive_sha512final(archive_sha512_ctx *ctx, void *md)
{
return (win_crypto_Final(md, 64, ctx));
}
#else
static int
@@ -1525,11 +1608,12 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
* 1. libc
* 2. libc2
* 3. libc3
* 4. libSystem
* 5. Nettle
* 6. OpenSSL
* 7. libmd
* 8. Windows API
* 4. libmd
* 5. libSystem
* 6. Windows API
* 7. mbedTLS
* 8. Nettle
* 9. OpenSSL
*/
const struct archive_digest __archive_digest =
{
@@ -113,6 +113,7 @@
defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) ||\
defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
#include <CommonCrypto/CommonDigest.h>
#define ARCHIVE_CRYPTO_CommonCrypto 1
#endif
/* mbed TLS crypto headers */
@@ -167,6 +168,7 @@
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
/* don't use bcrypt when XP needs to be supported */
#include <bcrypt.h>
#define ARCHIVE_CRYPTO_CNG 1
typedef struct {
int valid;
BCRYPT_ALG_HANDLE hAlg;
@@ -175,6 +177,7 @@ typedef struct {
#else
#include <windows.h>
#include <wincrypt.h>
#define ARCHIVE_CRYPTO_WINCRYPT 1
typedef struct {
int valid;
HCRYPTPROV cryptProv;
@@ -190,14 +193,16 @@ typedef MD5_CTX archive_md5_ctx;
typedef MD5_CTX archive_md5_ctx;
#elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM)
typedef CC_MD5_CTX archive_md5_ctx;
#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
typedef Digest_CTX archive_md5_ctx;
#elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS)
#define ARCHIVE_CRYPTO_MBED 1
typedef mbedtls_md5_context archive_md5_ctx;
#elif defined(ARCHIVE_CRYPTO_MD5_NETTLE)
#define ARCHIVE_CRYPTO_NETTLE 1
typedef struct md5_ctx archive_md5_ctx;
#elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL)
typedef EVP_MD_CTX *archive_md5_ctx;
#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
typedef Digest_CTX archive_md5_ctx;
#else
typedef unsigned char archive_md5_ctx;
#endif
@@ -207,8 +212,10 @@ typedef RMD160_CTX archive_rmd160_ctx;
#elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD)
typedef RIPEMD160_CTX archive_rmd160_ctx;
#elif defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS)
#define ARCHIVE_CRYPTO_MBED 1
typedef mbedtls_ripemd160_context archive_rmd160_ctx;
#elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE)
#define ARCHIVE_CRYPTO_NETTLE 1
typedef struct ripemd160_ctx archive_rmd160_ctx;
#elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL)
typedef EVP_MD_CTX *archive_rmd160_ctx;
@@ -222,14 +229,16 @@ typedef SHA1_CTX archive_sha1_ctx;
typedef SHA1_CTX archive_sha1_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM)
typedef CC_SHA1_CTX archive_sha1_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
typedef Digest_CTX archive_sha1_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS)
#define ARCHIVE_CRYPTO_MBED 1
typedef mbedtls_sha1_context archive_sha1_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE)
#define ARCHIVE_CRYPTO_NETTLE 1
typedef struct sha1_ctx archive_sha1_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL)
typedef EVP_MD_CTX *archive_sha1_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
typedef Digest_CTX archive_sha1_ctx;
#else
typedef unsigned char archive_sha1_ctx;
#endif
@@ -244,14 +253,16 @@ typedef SHA2_CTX archive_sha256_ctx;
typedef SHA256_CTX archive_sha256_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM)
typedef CC_SHA256_CTX archive_sha256_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
typedef Digest_CTX archive_sha256_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS)
#define ARCHIVE_CRYPTO_MBED 1
typedef mbedtls_sha256_context archive_sha256_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE)
#define ARCHIVE_CRYPTO_NETTLE 1
typedef struct sha256_ctx archive_sha256_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL)
typedef EVP_MD_CTX *archive_sha256_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
typedef Digest_CTX archive_sha256_ctx;
#else
typedef unsigned char archive_sha256_ctx;
#endif
@@ -264,14 +275,16 @@ typedef SHA384_CTX archive_sha384_ctx;
typedef SHA2_CTX archive_sha384_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM)
typedef CC_SHA512_CTX archive_sha384_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
typedef Digest_CTX archive_sha384_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS)
#define ARCHIVE_CRYPTO_MBED 1
typedef mbedtls_sha512_context archive_sha384_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE)
#define ARCHIVE_CRYPTO_NETTLE 1
typedef struct sha384_ctx archive_sha384_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL)
typedef EVP_MD_CTX *archive_sha384_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
typedef Digest_CTX archive_sha384_ctx;
#else
typedef unsigned char archive_sha384_ctx;
#endif
@@ -286,14 +299,16 @@ typedef SHA2_CTX archive_sha512_ctx;
typedef SHA512_CTX archive_sha512_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
typedef CC_SHA512_CTX archive_sha512_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
typedef Digest_CTX archive_sha512_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS)
#define ARCHIVE_CRYPTO_MBED 1
typedef mbedtls_sha512_context archive_sha512_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
#define ARCHIVE_CRYPTO_NETTLE 1
typedef struct sha512_ctx archive_sha512_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
typedef EVP_MD_CTX *archive_sha512_ctx;
#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
typedef Digest_CTX archive_sha512_ctx;
#else
typedef unsigned char archive_sha512_ctx;
#endif
@@ -262,7 +262,7 @@ translate_acl(struct archive_read_disk *a,
}
for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
r = acl_get_flag_np(acl_flagset,
acl_nfs4_flag_map[i].p_perm);
(acl_flag_t)acl_nfs4_flag_map[i].p_perm);
if (r == -1) {
archive_set_error(&a->archive, errno,
"Failed to check flag in a NFSv4 "
@@ -517,7 +517,7 @@ set_acl(struct archive *a, int fd, const char *name,
for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
if (acl_add_flag_np(acl_flagset,
acl_nfs4_flag_map[i].p_perm) != 0) {
(acl_flag_t)acl_nfs4_flag_map[i].p_perm) != 0) {
archive_set_error(a, errno,
"Failed to add flag to "
"NFSv4 ACL flagset");
+32 -22
View File
@@ -275,7 +275,7 @@ archive_entry_new2(struct archive *a)
* Functions for reading fields from an archive_entry.
*/
time_t
__LA_TIME_T
archive_entry_atime(struct archive_entry *entry)
{
return (entry->ae_stat.aest_atime);
@@ -293,7 +293,7 @@ archive_entry_atime_is_set(struct archive_entry *entry)
return (entry->ae_set & AE_SET_ATIME);
}
time_t
__LA_TIME_T
archive_entry_birthtime(struct archive_entry *entry)
{
return (entry->ae_stat.aest_birthtime);
@@ -311,7 +311,7 @@ archive_entry_birthtime_is_set(struct archive_entry *entry)
return (entry->ae_set & AE_SET_BIRTHTIME);
}
time_t
__LA_TIME_T
archive_entry_ctime(struct archive_entry *entry)
{
return (entry->ae_stat.aest_ctime);
@@ -329,7 +329,7 @@ archive_entry_ctime_nsec(struct archive_entry *entry)
return (entry->ae_stat.aest_ctime_nsec);
}
dev_t
__LA_DEV_T
archive_entry_dev(struct archive_entry *entry)
{
if (entry->ae_stat.aest_dev_is_broken_down)
@@ -345,7 +345,7 @@ archive_entry_dev_is_set(struct archive_entry *entry)
return (entry->ae_set & AE_SET_DEV);
}
dev_t
__LA_DEV_T
archive_entry_devmajor(struct archive_entry *entry)
{
if (entry->ae_stat.aest_dev_is_broken_down)
@@ -354,7 +354,7 @@ archive_entry_devmajor(struct archive_entry *entry)
return major(entry->ae_stat.aest_dev);
}
dev_t
__LA_DEV_T
archive_entry_devminor(struct archive_entry *entry)
{
if (entry->ae_stat.aest_dev_is_broken_down)
@@ -568,7 +568,7 @@ archive_entry_mode(struct archive_entry *entry)
return (entry->acl.mode);
}
time_t
__LA_TIME_T
archive_entry_mtime(struct archive_entry *entry)
{
return (entry->ae_stat.aest_mtime);
@@ -667,7 +667,7 @@ archive_entry_rdev_is_set(struct archive_entry *entry)
return (entry->ae_set & AE_SET_RDEV);
}
dev_t
__LA_DEV_T
archive_entry_rdev(struct archive_entry *entry)
{
if (archive_entry_rdev_is_set(entry)) {
@@ -681,7 +681,7 @@ archive_entry_rdev(struct archive_entry *entry)
}
}
dev_t
__LA_DEV_T
archive_entry_rdevmajor(struct archive_entry *entry)
{
if (archive_entry_rdev_is_set(entry)) {
@@ -694,7 +694,7 @@ archive_entry_rdevmajor(struct archive_entry *entry)
}
}
dev_t
__LA_DEV_T
archive_entry_rdevminor(struct archive_entry *entry)
{
if (archive_entry_rdev_is_set(entry)) {
@@ -984,7 +984,9 @@ void
archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino)
{
if (ino < 0) {
ino = 0;
entry->stat_valid = 0;
entry->ae_set &= ~AE_SET_INO;
return;
}
entry->stat_valid = 0;
entry->ae_set |= AE_SET_INO;
@@ -995,7 +997,9 @@ void
archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino)
{
if (ino < 0) {
ino = 0;
entry->stat_valid = 0;
entry->ae_set &= ~AE_SET_INO;
return;
}
entry->stat_valid = 0;
entry->ae_set |= AE_SET_INO;
@@ -1088,7 +1092,7 @@ _archive_entry_copy_hardlink_l(struct archive_entry *entry,
}
void
archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns)
archive_entry_set_atime(struct archive_entry *entry, __LA_TIME_T t, long ns)
{
FIX_NS(t, ns);
entry->stat_valid = 0;
@@ -1105,7 +1109,7 @@ archive_entry_unset_atime(struct archive_entry *entry)
}
void
archive_entry_set_birthtime(struct archive_entry *entry, time_t t, long ns)
archive_entry_set_birthtime(struct archive_entry *entry, __LA_TIME_T t, long ns)
{
FIX_NS(t, ns);
entry->stat_valid = 0;
@@ -1122,7 +1126,7 @@ archive_entry_unset_birthtime(struct archive_entry *entry)
}
void
archive_entry_set_ctime(struct archive_entry *entry, time_t t, long ns)
archive_entry_set_ctime(struct archive_entry *entry, __LA_TIME_T t, long ns)
{
FIX_NS(t, ns);
entry->stat_valid = 0;
@@ -1139,7 +1143,7 @@ archive_entry_unset_ctime(struct archive_entry *entry)
}
void
archive_entry_set_dev(struct archive_entry *entry, dev_t d)
archive_entry_set_dev(struct archive_entry *entry, __LA_DEV_T d)
{
entry->stat_valid = 0;
entry->ae_set |= AE_SET_DEV;
@@ -1148,7 +1152,7 @@ archive_entry_set_dev(struct archive_entry *entry, dev_t d)
}
void
archive_entry_set_devmajor(struct archive_entry *entry, dev_t m)
archive_entry_set_devmajor(struct archive_entry *entry, __LA_DEV_T m)
{
entry->stat_valid = 0;
entry->ae_set |= AE_SET_DEV;
@@ -1157,7 +1161,7 @@ archive_entry_set_devmajor(struct archive_entry *entry, dev_t m)
}
void
archive_entry_set_devminor(struct archive_entry *entry, dev_t m)
archive_entry_set_devminor(struct archive_entry *entry, __LA_DEV_T m)
{
entry->stat_valid = 0;
entry->ae_set |= AE_SET_DEV;
@@ -1243,7 +1247,7 @@ archive_entry_set_mode(struct archive_entry *entry, mode_t m)
}
void
archive_entry_set_mtime(struct archive_entry *entry, time_t t, long ns)
archive_entry_set_mtime(struct archive_entry *entry, __LA_TIME_T t, long ns)
{
FIX_NS(t, ns);
entry->stat_valid = 0;
@@ -1319,7 +1323,7 @@ archive_entry_set_perm(struct archive_entry *entry, mode_t p)
}
void
archive_entry_set_rdev(struct archive_entry *entry, dev_t m)
archive_entry_set_rdev(struct archive_entry *entry, __LA_DEV_T m)
{
entry->stat_valid = 0;
entry->ae_stat.aest_rdev = m;
@@ -1330,7 +1334,7 @@ archive_entry_set_rdev(struct archive_entry *entry, dev_t m)
}
void
archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m)
archive_entry_set_rdevmajor(struct archive_entry *entry, __LA_DEV_T m)
{
entry->stat_valid = 0;
entry->ae_stat.aest_rdev_is_broken_down = 1;
@@ -1340,7 +1344,7 @@ archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m)
}
void
archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m)
archive_entry_set_rdevminor(struct archive_entry *entry, __LA_DEV_T m)
{
entry->stat_valid = 0;
entry->ae_stat.aest_rdev_is_broken_down = 1;
@@ -1603,21 +1607,27 @@ archive_entry_set_digest(struct archive_entry *entry, int type,
switch (type) {
case ARCHIVE_ENTRY_DIGEST_MD5:
copy_digest(entry, md5, digest);
entry->mset_digest |= AE_MSET_DIGEST_MD5;
break;
case ARCHIVE_ENTRY_DIGEST_RMD160:
copy_digest(entry, rmd160, digest);
entry->mset_digest |= AE_MSET_DIGEST_RMD160;
break;
case ARCHIVE_ENTRY_DIGEST_SHA1:
copy_digest(entry, sha1, digest);
entry->mset_digest |= AE_MSET_DIGEST_SHA1;
break;
case ARCHIVE_ENTRY_DIGEST_SHA256:
copy_digest(entry, sha256, digest);
entry->mset_digest |= AE_MSET_DIGEST_SHA256;
break;
case ARCHIVE_ENTRY_DIGEST_SHA384:
copy_digest(entry, sha384, digest);
entry->mset_digest |= AE_MSET_DIGEST_SHA384;
break;
case ARCHIVE_ENTRY_DIGEST_SHA512:
copy_digest(entry, sha512, digest);
entry->mset_digest |= AE_MSET_DIGEST_SHA512;
break;
default:
return ARCHIVE_WARN;
+58 -26
View File
@@ -28,7 +28,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
#define ARCHIVE_VERSION_NUMBER 3007007
#define ARCHIVE_VERSION_NUMBER 3008001
/*
* Note: archive_entry.h is for use outside of libarchive; the
@@ -40,8 +40,11 @@
#include <sys/types.h>
#include <stddef.h> /* for wchar_t */
#include <stdint.h>
#include <stdint.h> /* for C99 int64_t, etc. */
#if ARCHIVE_VERSION_NUMBER < 4000000
/* time_t is slated to be removed from public includes in 4.0 */
#include <time.h>
#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <windows.h>
@@ -55,12 +58,15 @@
#define __LA_INT64_T_DEFINED
# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
typedef __int64 la_int64_t;
typedef unsigned __int64 la_uint64_t;
# else
#include <unistd.h>
# if defined(_SCO_DS) || defined(__osf__)
typedef long long la_int64_t;
typedef unsigned long long la_uint64_t;
# else
typedef int64_t la_int64_t;
typedef uint64_t la_uint64_t;
# endif
# endif
#endif
@@ -96,6 +102,30 @@ typedef ssize_t la_ssize_t;
# define __LA_MODE_T mode_t
#endif
#if ARCHIVE_VERSION_NUMBER < 4000000
/* Use the platform types for time_t */
#define __LA_TIME_T time_t
#else
/* Use 64-bits integer types for time_t */
#define __LA_TIME_T la_int64_t
#endif
#if ARCHIVE_VERSION_NUMBER < 4000000
/* Use the platform types for dev_t */
#define __LA_DEV_T dev_t
#else
/* Use 64-bits integer types for dev_t */
#define __LA_DEV_T la_int64_t
#endif
#if ARCHIVE_VERSION_NUMBER < 4000000
/* Libarchive 3.x used signed int64 for inode numbers */
#define __LA_INO_T la_int64_t
#else
/* Switch to unsigned for libarchive 4.0 */
#define __LA_INO_T la_uint64_t
#endif
/* Large file support for Android */
#if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__)
#include "android_lf.h"
@@ -127,7 +157,8 @@ typedef ssize_t la_ssize_t;
# define __LA_DECL
#endif
#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1
#if defined(__GNUC__) && (__GNUC__ > 3 || \
(__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
# define __LA_DEPRECATED __attribute__((deprecated))
#else
# define __LA_DEPRECATED
@@ -235,19 +266,19 @@ __LA_DECL struct archive_entry *archive_entry_new2(struct archive *);
* also return NULL when implicit character set conversions fail.
* This is usually what you want.
*/
__LA_DECL time_t archive_entry_atime(struct archive_entry *);
__LA_DECL __LA_TIME_T archive_entry_atime(struct archive_entry *);
__LA_DECL long archive_entry_atime_nsec(struct archive_entry *);
__LA_DECL int archive_entry_atime_is_set(struct archive_entry *);
__LA_DECL time_t archive_entry_birthtime(struct archive_entry *);
__LA_DECL __LA_TIME_T archive_entry_birthtime(struct archive_entry *);
__LA_DECL long archive_entry_birthtime_nsec(struct archive_entry *);
__LA_DECL int archive_entry_birthtime_is_set(struct archive_entry *);
__LA_DECL time_t archive_entry_ctime(struct archive_entry *);
__LA_DECL __LA_TIME_T archive_entry_ctime(struct archive_entry *);
__LA_DECL long archive_entry_ctime_nsec(struct archive_entry *);
__LA_DECL int archive_entry_ctime_is_set(struct archive_entry *);
__LA_DECL dev_t archive_entry_dev(struct archive_entry *);
__LA_DECL __LA_DEV_T archive_entry_dev(struct archive_entry *);
__LA_DECL int archive_entry_dev_is_set(struct archive_entry *);
__LA_DECL dev_t archive_entry_devmajor(struct archive_entry *);
__LA_DECL dev_t archive_entry_devminor(struct archive_entry *);
__LA_DECL __LA_DEV_T archive_entry_devmajor(struct archive_entry *);
__LA_DECL __LA_DEV_T archive_entry_devminor(struct archive_entry *);
__LA_DECL __LA_MODE_T archive_entry_filetype(struct archive_entry *);
__LA_DECL int archive_entry_filetype_is_set(struct archive_entry *);
__LA_DECL void archive_entry_fflags(struct archive_entry *,
@@ -264,8 +295,8 @@ __LA_DECL const char *archive_entry_hardlink(struct archive_entry *);
__LA_DECL const char *archive_entry_hardlink_utf8(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_hardlink_w(struct archive_entry *);
__LA_DECL int archive_entry_hardlink_is_set(struct archive_entry *);
__LA_DECL la_int64_t archive_entry_ino(struct archive_entry *);
__LA_DECL la_int64_t archive_entry_ino64(struct archive_entry *);
__LA_DECL __LA_INO_T archive_entry_ino(struct archive_entry *);
__LA_DECL __LA_INO_T archive_entry_ino64(struct archive_entry *);
__LA_DECL int archive_entry_ino_is_set(struct archive_entry *);
__LA_DECL __LA_MODE_T archive_entry_mode(struct archive_entry *);
__LA_DECL time_t archive_entry_mtime(struct archive_entry *);
@@ -278,9 +309,9 @@ __LA_DECL const wchar_t *archive_entry_pathname_w(struct archive_entry *);
__LA_DECL __LA_MODE_T archive_entry_perm(struct archive_entry *);
__LA_DECL int archive_entry_perm_is_set(struct archive_entry *);
__LA_DECL int archive_entry_rdev_is_set(struct archive_entry *);
__LA_DECL dev_t archive_entry_rdev(struct archive_entry *);
__LA_DECL dev_t archive_entry_rdevmajor(struct archive_entry *);
__LA_DECL dev_t archive_entry_rdevminor(struct archive_entry *);
__LA_DECL __LA_DEV_T archive_entry_rdev(struct archive_entry *);
__LA_DECL __LA_DEV_T archive_entry_rdevmajor(struct archive_entry *);
__LA_DECL __LA_DEV_T archive_entry_rdevminor(struct archive_entry *);
__LA_DECL const char *archive_entry_sourcepath(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_sourcepath_w(struct archive_entry *);
__LA_DECL la_int64_t archive_entry_size(struct archive_entry *);
@@ -309,18 +340,18 @@ __LA_DECL int archive_entry_is_encrypted(struct archive_entry *);
* always copied.
*/
__LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long);
__LA_DECL void archive_entry_set_atime(struct archive_entry *, __LA_TIME_T, long);
__LA_DECL void archive_entry_unset_atime(struct archive_entry *);
#if defined(_WIN32) && !defined(__CYGWIN__)
__LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, BY_HANDLE_FILE_INFORMATION *);
#endif
__LA_DECL void archive_entry_set_birthtime(struct archive_entry *, time_t, long);
__LA_DECL void archive_entry_set_birthtime(struct archive_entry *, __LA_TIME_T, long);
__LA_DECL void archive_entry_unset_birthtime(struct archive_entry *);
__LA_DECL void archive_entry_set_ctime(struct archive_entry *, time_t, long);
__LA_DECL void archive_entry_set_ctime(struct archive_entry *, __LA_TIME_T, long);
__LA_DECL void archive_entry_unset_ctime(struct archive_entry *);
__LA_DECL void archive_entry_set_dev(struct archive_entry *, dev_t);
__LA_DECL void archive_entry_set_devmajor(struct archive_entry *, dev_t);
__LA_DECL void archive_entry_set_devminor(struct archive_entry *, dev_t);
__LA_DECL void archive_entry_set_dev(struct archive_entry *, __LA_DEV_T);
__LA_DECL void archive_entry_set_devmajor(struct archive_entry *, __LA_DEV_T);
__LA_DECL void archive_entry_set_devminor(struct archive_entry *, __LA_DEV_T);
__LA_DECL void archive_entry_set_filetype(struct archive_entry *, unsigned int);
__LA_DECL void archive_entry_set_fflags(struct archive_entry *,
unsigned long /* set */, unsigned long /* clear */);
@@ -343,15 +374,15 @@ __LA_DECL void archive_entry_set_hardlink_utf8(struct archive_entry *, const cha
__LA_DECL void archive_entry_copy_hardlink(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *);
__LA_DECL int archive_entry_update_hardlink_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_ino(struct archive_entry *, la_int64_t);
__LA_DECL void archive_entry_set_ino64(struct archive_entry *, la_int64_t);
__LA_DECL void archive_entry_set_ino(struct archive_entry *, __LA_INO_T);
__LA_DECL void archive_entry_set_ino64(struct archive_entry *, __LA_INO_T);
__LA_DECL void archive_entry_set_link(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_link_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_link(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_link_w(struct archive_entry *, const wchar_t *);
__LA_DECL int archive_entry_update_link_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_mode(struct archive_entry *, __LA_MODE_T);
__LA_DECL void archive_entry_set_mtime(struct archive_entry *, time_t, long);
__LA_DECL void archive_entry_set_mtime(struct archive_entry *, __LA_TIME_T, long);
__LA_DECL void archive_entry_unset_mtime(struct archive_entry *);
__LA_DECL void archive_entry_set_nlink(struct archive_entry *, unsigned int);
__LA_DECL void archive_entry_set_pathname(struct archive_entry *, const char *);
@@ -360,9 +391,9 @@ __LA_DECL void archive_entry_copy_pathname(struct archive_entry *, const char *)
__LA_DECL void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *);
__LA_DECL int archive_entry_update_pathname_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_perm(struct archive_entry *, __LA_MODE_T);
__LA_DECL void archive_entry_set_rdev(struct archive_entry *, dev_t);
__LA_DECL void archive_entry_set_rdevmajor(struct archive_entry *, dev_t);
__LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, dev_t);
__LA_DECL void archive_entry_set_rdev(struct archive_entry *, __LA_DEV_T);
__LA_DECL void archive_entry_set_rdevmajor(struct archive_entry *, __LA_DEV_T);
__LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, __LA_DEV_T);
__LA_DECL void archive_entry_set_size(struct archive_entry *, la_int64_t);
__LA_DECL void archive_entry_unset_size(struct archive_entry *);
__LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *);
@@ -418,6 +449,7 @@ __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const voi
#define ARCHIVE_ENTRY_DIGEST_SHA512 0x00000006
__LA_DECL const unsigned char * archive_entry_digest(struct archive_entry *, int /* type */);
__LA_DECL int archive_entry_set_digest(struct archive_entry *, int, const unsigned char *);
/*
* ACL routines. This used to simply store and return text-format ACL
@@ -280,6 +280,10 @@ find_entry(struct archive_entry_linkresolver *res,
dev_t dev;
int64_t ino;
if (!archive_entry_ino_is_set(entry) || !archive_entry_dev_is_set(entry)) {
return (NULL);
}
/* Free a held entry. */
if (res->spare != NULL) {
archive_entry_free(res->spare->canonical);
@@ -369,6 +373,10 @@ insert_entry(struct archive_entry_linkresolver *res,
struct links_entry *le;
size_t hash, bucket;
if (!archive_entry_ino_is_set(entry) || !archive_entry_dev_is_set(entry)) {
return (NULL);
}
/* Add this entry to the links cache. */
le = calloc(1, sizeof(struct links_entry));
if (le == NULL)
@@ -87,4 +87,4 @@ int _archive_entry_copy_symlink_l(struct archive_entry *,
int _archive_entry_copy_uname_l(struct archive_entry *,
const char *, size_t, struct archive_string_conv *);
#endif /* ARCHIVE_ENTRY_LOCALE_H_INCLUDED */
#endif /* !ARCHIVE_ENTRY_LOCALE_H_INCLUDED */
@@ -174,6 +174,13 @@ struct archive_entry {
size_t mac_metadata_size;
/* Digest support. */
#define AE_MSET_DIGEST_MD5 1
#define AE_MSET_DIGEST_RMD160 2
#define AE_MSET_DIGEST_SHA1 4
#define AE_MSET_DIGEST_SHA256 8
#define AE_MSET_DIGEST_SHA384 16
#define AE_MSET_DIGEST_SHA512 32
uint_least32_t mset_digest;
struct ae_digest digest;
/* ACL support. */
@@ -195,8 +202,4 @@ struct archive_entry {
int ae_symlink_type;
};
int
archive_entry_set_digest(struct archive_entry *entry, int type,
const unsigned char *digest);
#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
#endif /* !ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
@@ -116,4 +116,4 @@ struct archive_hmac {
};
extern const struct archive_hmac __archive_hmac;
#endif /* ARCHIVE_HMAC_PRIVATE_H_INCLUDED */
#endif /* !ARCHIVE_HMAC_PRIVATE_H_INCLUDED */
+37 -65
View File
@@ -35,14 +35,17 @@
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#include "archive.h"
#include "archive_private.h"
#include "archive_entry.h"
#include "archive_getdate.h"
#include "archive_pathmatch.h"
#include "archive_rb.h"
#include "archive_string.h"
#include "archive_time_private.h"
struct match {
struct match *next;
@@ -53,8 +56,7 @@ struct match {
struct match_list {
struct match *first;
struct match **last;
int count;
int unmatched_count;
size_t unmatched_count;
struct match *unmatched_next;
int unmatched_eof;
};
@@ -73,7 +75,6 @@ struct match_file {
struct entry_list {
struct match_file *first;
struct match_file **last;
int count;
};
struct id_array {
@@ -144,12 +145,15 @@ static int add_pattern_mbs(struct archive_match *, struct match_list *,
const char *);
static int add_pattern_wcs(struct archive_match *, struct match_list *,
const wchar_t *);
#if !defined(_WIN32) || defined(__CYGWIN__)
static int cmp_key_mbs(const struct archive_rb_node *, const void *);
static int cmp_key_wcs(const struct archive_rb_node *, const void *);
static int cmp_node_mbs(const struct archive_rb_node *,
const struct archive_rb_node *);
#else
static int cmp_key_wcs(const struct archive_rb_node *, const void *);
static int cmp_node_wcs(const struct archive_rb_node *,
const struct archive_rb_node *);
#endif
static void entry_list_add(struct entry_list *, struct match_file *);
static void entry_list_free(struct entry_list *);
static void entry_list_init(struct entry_list *);
@@ -187,14 +191,14 @@ static int time_excluded(struct archive_match *,
struct archive_entry *);
static int validate_time_flag(struct archive *, int, const char *);
#define get_date __archive_get_date
#define get_date archive_parse_date
static const struct archive_rb_tree_ops rb_ops_mbs = {
static const struct archive_rb_tree_ops rb_ops = {
#if !defined(_WIN32) || defined(__CYGWIN__)
cmp_node_mbs, cmp_key_mbs
};
static const struct archive_rb_tree_ops rb_ops_wcs = {
#else
cmp_node_wcs, cmp_key_wcs
#endif
};
/*
@@ -228,7 +232,7 @@ archive_match_new(void)
a->recursive_include = 1;
match_list_init(&(a->inclusions));
match_list_init(&(a->exclusions));
__archive_rb_tree_init(&(a->exclusion_tree), &rb_ops_mbs);
__archive_rb_tree_init(&(a->exclusion_tree), &rb_ops);
entry_list_init(&(a->exclusion_entry_list));
match_list_init(&(a->inclusion_unames));
match_list_init(&(a->inclusion_gnames));
@@ -507,7 +511,9 @@ archive_match_path_unmatched_inclusions(struct archive *_a)
ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions");
a = (struct archive_match *)_a;
return (a->inclusions.unmatched_count);
if (a->inclusions.unmatched_count > (size_t)INT_MAX)
return INT_MAX;
return (int)(a->inclusions.unmatched_count);
}
int
@@ -650,7 +656,7 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
break;
}
} else {
if (*b == 0x0d || *b == 0x0a) {
if (*b == 0x0d || *b == 0x0a) {
found_separator = 1;
break;
}
@@ -735,7 +741,7 @@ path_excluded(struct archive_match *a, int mbs, const void *pathname)
}
}
/* Exclusions take priority */
/* Exclusions take priority. */
for (match = a->exclusions.first; match != NULL;
match = match->next){
r = match_path_exclusion(a, match, mbs, pathname);
@@ -834,7 +840,6 @@ match_list_init(struct match_list *list)
{
list->first = NULL;
list->last = &(list->first);
list->count = 0;
}
static void
@@ -855,7 +860,6 @@ match_list_add(struct match_list *list, struct match *m)
{
*list->last = m;
list->last = &(m->next);
list->count++;
list->unmatched_count++;
}
@@ -1145,36 +1149,15 @@ set_timefilter_date_w(struct archive_match *a, int timetype,
}
#if defined(_WIN32) && !defined(__CYGWIN__)
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
static int
set_timefilter_find_data(struct archive_match *a, int timetype,
DWORD ftLastWriteTime_dwHighDateTime, DWORD ftLastWriteTime_dwLowDateTime,
DWORD ftCreationTime_dwHighDateTime, DWORD ftCreationTime_dwLowDateTime)
const FILETIME* ftLastWriteTime, const FILETIME* ftCreationTime)
{
ULARGE_INTEGER utc;
time_t ctime_sec, mtime_sec;
long ctime_ns, mtime_ns;
uint32_t ctime_ns, mtime_ns;
utc.HighPart = ftCreationTime_dwHighDateTime;
utc.LowPart = ftCreationTime_dwLowDateTime;
if (utc.QuadPart >= EPOC_TIME) {
utc.QuadPart -= EPOC_TIME;
ctime_sec = (time_t)(utc.QuadPart / 10000000);
ctime_ns = (long)(utc.QuadPart % 10000000) * 100;
} else {
ctime_sec = 0;
ctime_ns = 0;
}
utc.HighPart = ftLastWriteTime_dwHighDateTime;
utc.LowPart = ftLastWriteTime_dwLowDateTime;
if (utc.QuadPart >= EPOC_TIME) {
utc.QuadPart -= EPOC_TIME;
mtime_sec = (time_t)(utc.QuadPart / 10000000);
mtime_ns = (long)(utc.QuadPart % 10000000) * 100;
} else {
mtime_sec = 0;
mtime_ns = 0;
}
ntfs_to_unix(FILETIME_to_ntfs(ftLastWriteTime), &mtime_sec, &mtime_ns);
ntfs_to_unix(FILETIME_to_ntfs(ftCreationTime), &ctime_sec, &ctime_ns);
return set_timefilter(a, timetype,
mtime_sec, mtime_ns, ctime_sec, ctime_ns);
}
@@ -1199,9 +1182,7 @@ set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
return (ARCHIVE_FAILED);
}
FindClose(h);
return set_timefilter_find_data(a, timetype,
d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
return set_timefilter_find_data(a, timetype, &d.ftLastWriteTime, &d.ftCreationTime);
}
static int
@@ -1223,9 +1204,7 @@ set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
return (ARCHIVE_FAILED);
}
FindClose(h);
return set_timefilter_find_data(a, timetype,
d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
return set_timefilter_find_data(a, timetype, &d.ftLastWriteTime, &d.ftCreationTime);
}
#else /* _WIN32 && !__CYGWIN__ */
@@ -1300,6 +1279,7 @@ set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
/*
* Call back functions for archive_rb.
*/
#if !defined(_WIN32) || defined(__CYGWIN__)
static int
cmp_node_mbs(const struct archive_rb_node *n1,
const struct archive_rb_node *n2)
@@ -1316,7 +1296,7 @@ cmp_node_mbs(const struct archive_rb_node *n1,
return (-1);
return (strcmp(p1, p2));
}
static int
cmp_key_mbs(const struct archive_rb_node *n, const void *key)
{
@@ -1328,7 +1308,7 @@ cmp_key_mbs(const struct archive_rb_node *n, const void *key)
return (-1);
return (strcmp(p, (const char *)key));
}
#else
static int
cmp_node_wcs(const struct archive_rb_node *n1,
const struct archive_rb_node *n2)
@@ -1345,7 +1325,7 @@ cmp_node_wcs(const struct archive_rb_node *n1,
return (-1);
return (wcscmp(p1, p2));
}
static int
cmp_key_wcs(const struct archive_rb_node *n, const void *key)
{
@@ -1357,13 +1337,13 @@ cmp_key_wcs(const struct archive_rb_node *n, const void *key)
return (-1);
return (wcscmp(p, (const wchar_t *)key));
}
#endif
static void
entry_list_init(struct entry_list *list)
{
list->first = NULL;
list->last = &(list->first);
list->count = 0;
}
static void
@@ -1384,7 +1364,6 @@ entry_list_add(struct entry_list *list, struct match_file *file)
{
*list->last = file;
list->last = &(file->next);
list->count++;
}
static int
@@ -1407,9 +1386,7 @@ add_entry(struct archive_match *a, int flag,
return (ARCHIVE_FAILED);
}
archive_mstring_copy_wcs(&(f->pathname), pathname);
a->exclusion_tree.rbt_ops = &rb_ops_wcs;
#else
(void)rb_ops_wcs;
pathname = archive_entry_pathname(entry);
if (pathname == NULL) {
free(f);
@@ -1417,7 +1394,6 @@ add_entry(struct archive_match *a, int flag,
return (ARCHIVE_FAILED);
}
archive_mstring_copy_mbs(&(f->pathname), pathname);
a->exclusion_tree.rbt_ops = &rb_ops_mbs;
#endif
f->flag = flag;
f->mtime_sec = archive_entry_mtime(entry);
@@ -1542,16 +1518,13 @@ time_excluded(struct archive_match *a, struct archive_entry *entry)
}
/* If there is no exclusion list, include the file. */
if (a->exclusion_entry_list.count == 0)
if (a->exclusion_entry_list.first == NULL)
return (0);
#if defined(_WIN32) && !defined(__CYGWIN__)
pathname = archive_entry_pathname_w(entry);
a->exclusion_tree.rbt_ops = &rb_ops_wcs;
#else
(void)rb_ops_wcs;
pathname = archive_entry_pathname(entry);
a->exclusion_tree.rbt_ops = &rb_ops_mbs;
#endif
if (pathname == NULL)
return (0);
@@ -1707,7 +1680,7 @@ archive_match_owner_excluded(struct archive *_a,
static int
add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
{
unsigned i;
size_t i;
if (ids->count + 1 >= ids->size) {
void *p;
@@ -1744,10 +1717,10 @@ add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
static int
match_owner_id(struct id_array *ids, int64_t id)
{
unsigned b, m, t;
size_t b, m, t;
t = 0;
b = (unsigned)ids->count;
b = ids->count;
while (t < b) {
m = (t + b)>>1;
if (ids->ids[m] == id)
@@ -1842,7 +1815,7 @@ owner_excluded(struct archive_match *a, struct archive_entry *entry)
return (1);
}
if (a->inclusion_unames.count) {
if (a->inclusion_unames.first != NULL) {
#if defined(_WIN32) && !defined(__CYGWIN__)
r = match_owner_name_wcs(a, &(a->inclusion_unames),
archive_entry_uname_w(entry));
@@ -1856,7 +1829,7 @@ owner_excluded(struct archive_match *a, struct archive_entry *entry)
return (r);
}
if (a->inclusion_gnames.count) {
if (a->inclusion_gnames.first != NULL) {
#if defined(_WIN32) && !defined(__CYGWIN__)
r = match_owner_name_wcs(a, &(a->inclusion_gnames),
archive_entry_gname_w(entry));
@@ -1871,4 +1844,3 @@ owner_excluded(struct archive_match *a, struct archive_entry *entry)
}
return (0);
}
@@ -38,7 +38,7 @@ parse_option(const char **str,
int
_archive_set_option(struct archive *a,
const char *m, const char *o, const char *v,
int magic, const char *fn, option_handler use_option)
unsigned int magic, const char *fn, option_handler use_option)
{
const char *mp, *op, *vp;
int r;
@@ -97,7 +97,7 @@ _archive_set_either_option(struct archive *a, const char *m, const char *o, cons
int
_archive_set_options(struct archive *a, const char *options,
int magic, const char *fn, option_handler use_option)
unsigned int magic, const char *fn, option_handler use_option)
{
int allok = 1, anyok = 0, ignore_mod_err = 0, r;
char *data;
@@ -35,11 +35,11 @@ typedef int (*option_handler)(struct archive *a,
int
_archive_set_option(struct archive *a,
const char *mod, const char *opt, const char *val,
int magic, const char *fn, option_handler use_option);
unsigned int magic, const char *fn, option_handler use_option);
int
_archive_set_options(struct archive *a, const char *options,
int magic, const char *fn, option_handler use_option);
unsigned int magic, const char *fn, option_handler use_option);
int
_archive_set_either_option(struct archive *a,
@@ -46,4 +46,4 @@ pack_t pack_native;
(((y) << 12) & 0xfff00000) | \
(((y) << 0) & 0x000000ff)))
#endif /* ARCHIVE_PACK_DEV_H */
#endif /* !ARCHIVE_PACK_DEV_H */
@@ -35,8 +35,7 @@
#include <string.h>
#include <time.h>
#define __LIBARCHIVE_BUILD 1
#include "archive_getdate.h"
#include "archive.h"
/* Basic time units. */
#define EPOCH 1970
@@ -820,6 +819,23 @@ RelativeMonth(time_t Start, time_t Timezone, time_t RelMonth)
Timezone, DSTmaybe));
}
/*
* Parses and consumes an unsigned number.
* Returns 1 if any number is parsed. Otherwise, *value is unchanged.
*/
static char
consume_unsigned_number(const char **in, time_t *value)
{
char c;
if (isdigit((unsigned char)(c = **in))) {
for (*value = 0; isdigit((unsigned char)(c = *(*in)++)); )
*value = 10 * *value + c - '0';
(*in)--;
return 1;
}
return 0;
}
/*
* Tokenizer.
*/
@@ -861,7 +877,8 @@ nexttoken(const char **in, time_t *value)
&& i < sizeof(buff)-1) {
if (*src != '.') {
if (isupper((unsigned char)*src))
buff[i++] = tolower((unsigned char)*src);
buff[i++] = (char)tolower(
(unsigned char)*src);
else
buff[i++] = *src;
}
@@ -895,10 +912,7 @@ nexttoken(const char **in, time_t *value)
* Because '-' and '+' have other special meanings, I
* don't deal with signed numbers here.
*/
if (isdigit((unsigned char)(c = **in))) {
for (*value = 0; isdigit((unsigned char)(c = *(*in)++)); )
*value = 10 * *value + c - '0';
(*in)--;
if (consume_unsigned_number(in, value)) {
return (tUNUMBER);
}
@@ -914,7 +928,7 @@ difftm (struct tm *a, struct tm *b)
{
int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
int days = (
long days = (
/* difference in day of year */
a->tm_yday - b->tm_yday
/* + intervening leap days */
@@ -929,6 +943,32 @@ difftm (struct tm *a, struct tm *b)
+ (a->tm_sec - b->tm_sec));
}
/*
* Parses a Unix epoch timestamp (seconds).
* This supports a subset of what GNU tar accepts from black box testing,
* but covers common use cases.
*/
static time_t
parse_unix_epoch(const char *p)
{
time_t epoch;
/* may begin with + */
if (*p == '+') {
p++;
}
/* followed by some number */
if (!consume_unsigned_number(&p, &epoch))
return (time_t)-1;
/* ...and nothing else */
if (*p != '\0')
return (time_t)-1;
return epoch;
}
/*
*
* The public function.
@@ -936,7 +976,7 @@ difftm (struct tm *a, struct tm *b)
* TODO: tokens[] array should be dynamically sized.
*/
time_t
__archive_get_date(time_t now, const char *p)
archive_parse_date(time_t now, const char *p)
{
struct token tokens[256];
struct gdstate _gds;
@@ -948,6 +988,13 @@ __archive_get_date(time_t now, const char *p)
time_t tod;
long tzone;
/*
* @-prefixed Unix epoch timestamps (seconds)
* Skip the complex tokenizer - We do not want to accept strings like "@tenth"
*/
if (*p == '@')
return parse_unix_epoch(p + 1);
/* Clear out the parsed token array. */
memset(tokens, 0, sizeof(tokens));
/* Initialize the parser state. */
@@ -61,6 +61,11 @@
# endif
#endif
/* For cygwin, to avoid missing LONG, ULONG, PUCHAR, ... definitions */
#ifdef __CYGWIN__
#include <windef.h>
#endif
/* It should be possible to get rid of this by extending the feature-test
* macros to cover Windows API functions, probably along with non-trivial
* refactoring of code to find structures that sit more cleanly on top of
@@ -50,4 +50,4 @@
#define ARCHIVE_ACL_SUPPORT 1
#endif
#endif /* ARCHIVE_PLATFORM_ACL_H_INCLUDED */
#endif /* !ARCHIVE_PLATFORM_ACL_H_INCLUDED */
@@ -42,4 +42,4 @@
#define ARCHIVE_XATTR_SUPPORT 1
#endif
#endif /* ARCHIVE_PLATFORM_XATTR_H_INCLUDED */
#endif /* !ARCHIVE_PLATFORM_XATTR_H_INCLUDED */
@@ -287,9 +287,14 @@ static void *AllocUnits(CPpmd7 *p, unsigned indx)
return AllocUnitsRare(p, indx);
}
#define MyMem12Cpy(dest, src, num) \
{ UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \
do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); }
#define MyMem12Cpy(dest, src, num) do { \
UInt32 *d = (UInt32 *)dest; \
const UInt32 *s = (const UInt32 *)src; \
UInt32 n = num; \
do { \
d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; \
} while(--n); \
} while (0)
static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
{
+11 -4
View File
@@ -242,9 +242,14 @@ static void *AllocUnits(CPpmd8 *p, unsigned indx)
return AllocUnitsRare(p, indx);
}
#define MyMem12Cpy(dest, src, num) \
{ UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \
do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); }
#define MyMem12Cpy(dest, src, num) do { \
UInt32 *d = (UInt32 *)dest; \
const UInt32 *z = (const UInt32 *)src; \
UInt32 n = num; \
do { \
d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; \
} while (--n); \
} while (0)
static void *ShrinkUnits(CPpmd8 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
{
@@ -341,7 +346,9 @@ static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
(p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
}
#define RESET_TEXT(offs) { p->Text = p->Base + p->AlignOffset + (offs); }
#define RESET_TEXT(offs) do { \
p->Text = p->Base + p->AlignOffset + (offs); \
} while (0)
static void RestartModel(CPpmd8 *p)
{
@@ -109,8 +109,12 @@ typedef struct
Byte Count; /* Count to next change of Shift */
} CPpmd_See;
#define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \
{ (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); }
#define Ppmd_See_Update(p) do { \
if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) { \
(p)->Summ <<= 1; \
(p)->Count = (Byte)(3 << (p)->Shift++); \
} \
} while (0)
typedef struct
{
@@ -144,8 +148,12 @@ typedef
#endif
CPpmd_Byte_Ref;
#define PPMD_SetAllBitsIn256Bytes(p) \
{ unsigned j; for (j = 0; j < 256 / sizeof(p[0]); j += 8) { \
p[j+7] = p[j+6] = p[j+5] = p[j+4] = p[j+3] = p[j+2] = p[j+1] = p[j+0] = ~(size_t)0; }}
#define PPMD_SetAllBitsIn256Bytes(p) do { \
unsigned j; \
for (j = 0; j < 256 / sizeof(p[0]); j += 8) { \
p[j+7] = p[j+6] = p[j+5] = p[j+4] = \
p[j+3] = p[j+2] = p[j+1] = p[j+0] = ~(size_t)0; \
} \
} while (0)
#endif
@@ -33,4 +33,4 @@
/* Random number generator. */
int archive_random(void *buf, size_t nbytes);
#endif /* ARCHIVE_RANDOM_PRIVATE_H_INCLUDED */
#endif /* !ARCHIVE_RANDOM_PRIVATE_H_INCLUDED */
+1 -1
View File
@@ -110,4 +110,4 @@ struct archive_rb_node *
__archive_rb_tree_iterate(struct archive_rb_tree *,
struct archive_rb_node *, const unsigned int);
#endif /* ARCHIVE_RB_H_*/
#endif /* !ARCHIVE_RB_H_INCLUDED */
@@ -176,15 +176,9 @@ client_skip_proxy(struct archive_read_filter *self, int64_t request)
return 0;
if (self->archive->client.skipper != NULL) {
/* Seek requests over 1GiB are broken down into
* multiple seeks. This avoids overflows when the
* requests get passed through 32-bit arguments. */
int64_t skip_limit = (int64_t)1 << 30;
int64_t total = 0;
for (;;) {
int64_t get, ask = request;
if (ask > skip_limit)
ask = skip_limit;
get = (self->archive->client.skipper)
(&self->archive->archive, self->data, ask);
total += get;
@@ -96,6 +96,10 @@ archive_read_append_filter(struct archive *_a, int code)
strcpy(str, "lzip");
r1 = archive_read_support_filter_lzip(_a);
break;
case ARCHIVE_FILTER_LZOP:
strcpy(str, "lzop");
r1 = archive_read_support_filter_lzop(_a);
break;
case ARCHIVE_FILTER_LRZIP:
strcpy(str, "lrzip");
r1 = archive_read_support_filter_lrzip(_a);
@@ -888,7 +888,7 @@ setup_sparse_fiemap(struct archive_read_disk *a,
count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe);
fm = (struct fiemap *)buff;
fm->fm_start = 0;
fm->fm_length = ~0ULL;;
fm->fm_length = ~0ULL;
fm->fm_flags = FIEMAP_FLAG_SYNC;
fm->fm_extent_count = count;
do_fiemap = 1;
@@ -276,7 +276,7 @@ tree_dir_next_posix(struct tree *t);
#endif
/* Initiate/terminate a tree traversal. */
static struct tree *tree_open(const char *, int, int);
static struct tree *tree_open(const char *, char, int);
static struct tree *tree_reopen(struct tree *, const char *, int);
static void tree_close(struct tree *);
static void tree_free(struct tree *);
@@ -514,7 +514,7 @@ _archive_read_close(struct archive *_a)
static void
setup_symlink_mode(struct archive_read_disk *a, char symlink_mode,
int follow_symlinks)
char follow_symlinks)
{
a->symlink_mode = symlink_mode;
a->follow_symlinks = follow_symlinks;
@@ -778,7 +778,8 @@ _archive_read_data_block(struct archive *_a, const void **buff,
*/
if (t->current_sparse->offset > t->entry_total) {
if (lseek(t->entry_fd,
(off_t)t->current_sparse->offset, SEEK_SET) < 0) {
(off_t)t->current_sparse->offset, SEEK_SET) !=
t->current_sparse->offset) {
archive_set_error(&a->archive, errno, "Seek error");
r = ARCHIVE_FATAL;
a->archive.state = ARCHIVE_STATE_FATAL;
@@ -2180,7 +2181,7 @@ tree_append(struct tree *t, const char *name, size_t name_length)
* Open a directory tree for traversal.
*/
static struct tree *
tree_open(const char *path, int symlink_mode, int restore_time)
tree_open(const char *path, char symlink_mode, int restore_time)
{
struct tree *t;
@@ -52,10 +52,11 @@ struct archive_read_disk {
/*
* Since symlink interaction changes, we need to track whether
* we're following symlinks for the current item. 'L' mode above
* sets this true, 'P' sets it false, 'H' changes it as we traverse.
* we're following symlinks for the current item, governed by the above
* symlink_mode. 'L' sets this true, 'P' sets it false, 'H' changes it
* as we traverse.
*/
char follow_symlinks; /* Either 'L' or 'P'. */
char follow_symlinks; /* Either 0 or 1. */
/* Directory traversals. */
struct tree *tree;
@@ -37,8 +37,10 @@
.Nm archive_read_support_format_lha ,
.Nm archive_read_support_format_mtree ,
.Nm archive_read_support_format_rar ,
.Nm archive_read_support_format_rar5 ,
.Nm archive_read_support_format_raw ,
.Nm archive_read_support_format_tar ,
.Nm archive_read_support_format_warc ,
.Nm archive_read_support_format_xar ,
.Nm archive_read_support_format_zip
.Nd functions for reading streaming archives
@@ -70,10 +72,14 @@ Streaming Archive Library (libarchive, -larchive)
.Ft int
.Fn archive_read_support_format_rar "struct archive *"
.Ft int
.Fn archive_read_support_format_rar5 "struct archive *"
.Ft int
.Fn archive_read_support_format_raw "struct archive *"
.Ft int
.Fn archive_read_support_format_tar "struct archive *"
.Ft int
.Fn archive_read_support_format_warc "struct archive *"
.Ft int
.Fn archive_read_support_format_xar "struct archive *"
.Ft int
.Fn archive_read_support_format_zip "struct archive *"
@@ -89,8 +95,10 @@ Streaming Archive Library (libarchive, -larchive)
.Fn archive_read_support_format_lha ,
.Fn archive_read_support_format_mtree ,
.Fn archive_read_support_format_rar ,
.Fn archive_read_support_format_rar5 ,
.Fn archive_read_support_format_raw ,
.Fn archive_read_support_format_tar ,
.Fn archive_read_support_format_warc ,
.Fn archive_read_support_format_xar ,
.Fn archive_read_support_format_zip
.Xc
@@ -100,6 +108,13 @@ For example,
.Fn archive_read_support_format_tar
enables support for a variety of standard tar formats, old-style tar,
ustar, pax interchange format, and many common variants.
.Fn archive_read_support_format_zip
enables support for both the streaming and the seeking zip readers,
which can separately be enabled by respectively
.Fn archive_read_support_format_zip_streamable
and
.Fn archive_read_support_format_zip_seekable
.
.It Fn archive_read_support_format_all
Enables support for all available formats except the
.Dq raw
@@ -52,6 +52,7 @@
struct read_fd_data {
int fd;
size_t block_size;
int64_t size;
char use_lseek;
void *buffer;
};
@@ -95,6 +96,7 @@ archive_read_open_fd(struct archive *a, int fd, size_t block_size)
if (S_ISREG(st.st_mode)) {
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
mine->use_lseek = 1;
mine->size = st.st_size;
}
#if defined(__CYGWIN__) || defined(_WIN32)
setmode(mine->fd, O_BINARY);
@@ -131,7 +133,7 @@ static int64_t
file_skip(struct archive *a, void *client_data, int64_t request)
{
struct read_fd_data *mine = (struct read_fd_data *)client_data;
int64_t skip = request;
off_t skip = (off_t)request;
int64_t old_offset, new_offset;
int skip_bits = sizeof(skip) * 8 - 1; /* off_t is a signed type. */
@@ -140,20 +142,25 @@ file_skip(struct archive *a, void *client_data, int64_t request)
/* Reduce a request that would overflow the 'skip' variable. */
if (sizeof(request) > sizeof(skip)) {
int64_t max_skip =
const int64_t max_skip =
(((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
if (request > max_skip)
skip = max_skip;
skip = (off_t)max_skip;
}
/* Reduce request to the next smallest multiple of block_size */
request = (request / mine->block_size) * mine->block_size;
if (request == 0)
/* Reduce 'skip' to the next smallest multiple of block_size */
skip = (off_t)(((int64_t)skip / mine->block_size) * mine->block_size);
if (skip == 0)
return (0);
if (((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) &&
((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0))
return (new_offset - old_offset);
if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) {
if (old_offset >= mine->size ||
skip > mine->size - old_offset) {
/* Do not seek past end of file. */
errno = ESPIPE;
} else if ((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0)
return (new_offset - old_offset);
}
/* If seek failed once, it will probably fail again. */
mine->use_lseek = 0;
@@ -178,11 +185,24 @@ static int64_t
file_seek(struct archive *a, void *client_data, int64_t request, int whence)
{
struct read_fd_data *mine = (struct read_fd_data *)client_data;
off_t seek = (off_t)request;
int64_t r;
int seek_bits = sizeof(seek) * 8 - 1; /* off_t is a signed type. */
/* We use off_t here because lseek() is declared that way. */
/* See above for notes about when off_t is less than 64 bits. */
r = lseek(mine->fd, request, whence);
/* Reduce a request that would overflow the 'seek' variable. */
if (sizeof(request) > sizeof(seek)) {
const int64_t max_seek =
(((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1;
const int64_t min_seek = ~max_seek;
if (request > max_seek)
seek = (off_t)max_seek;
else if (request < min_seek)
seek = (off_t)min_seek;
}
r = lseek(mine->fd, seek, whence);
if (r >= 0)
return r;
@@ -52,13 +52,15 @@
struct read_FILE_data {
FILE *f;
size_t block_size;
int64_t size;
void *buffer;
char can_skip;
};
static int file_close(struct archive *, void *);
static ssize_t file_read(struct archive *, void *, const void **buff);
static int64_t file_skip(struct archive *, void *, int64_t request);
static int FILE_close(struct archive *, void *);
static ssize_t FILE_read(struct archive *, void *, const void **buff);
static int64_t FILE_seek(struct archive *, void *, int64_t, int);
static int64_t FILE_skip(struct archive *, void *, int64_t);
int
archive_read_open_FILE(struct archive *a, FILE *f)
@@ -69,7 +71,7 @@ archive_read_open_FILE(struct archive *a, FILE *f)
void *b;
archive_clear_error(a);
mine = malloc(sizeof(*mine));
mine = calloc(1, sizeof(*mine));
b = malloc(block_size);
if (mine == NULL || b == NULL) {
archive_set_error(a, ENOMEM, "No memory");
@@ -90,22 +92,23 @@ archive_read_open_FILE(struct archive *a, FILE *f)
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
/* Enable the seek optimization only for regular files. */
mine->can_skip = 1;
} else
mine->can_skip = 0;
mine->size = st.st_size;
}
#if defined(__CYGWIN__) || defined(_WIN32)
setmode(fileno(mine->f), O_BINARY);
#endif
archive_read_set_read_callback(a, file_read);
archive_read_set_skip_callback(a, file_skip);
archive_read_set_close_callback(a, file_close);
archive_read_set_read_callback(a, FILE_read);
archive_read_set_skip_callback(a, FILE_skip);
archive_read_set_seek_callback(a, FILE_seek);
archive_read_set_close_callback(a, FILE_close);
archive_read_set_callback_data(a, mine);
return (archive_read_open1(a));
}
static ssize_t
file_read(struct archive *a, void *client_data, const void **buff)
FILE_read(struct archive *a, void *client_data, const void **buff)
{
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
size_t bytes_read;
@@ -119,16 +122,17 @@ file_read(struct archive *a, void *client_data, const void **buff)
}
static int64_t
file_skip(struct archive *a, void *client_data, int64_t request)
FILE_skip(struct archive *a, void *client_data, int64_t request)
{
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
#if HAVE_FSEEKO
off_t skip = (off_t)request;
#elif HAVE__FSEEKI64
#if HAVE__FSEEKI64
int64_t skip = request;
#elif HAVE_FSEEKO
off_t skip = (off_t)request;
#else
long skip = (long)request;
#endif
int64_t old_offset, new_offset = -1;
int skip_bits = sizeof(skip) * 8 - 1;
(void)a; /* UNUSED */
@@ -144,7 +148,7 @@ file_skip(struct archive *a, void *client_data, int64_t request)
/* If request is too big for a long or an off_t, reduce it. */
if (sizeof(request) > sizeof(skip)) {
int64_t max_skip =
const int64_t max_skip =
(((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
if (request > max_skip)
skip = max_skip;
@@ -152,23 +156,92 @@ file_skip(struct archive *a, void *client_data, int64_t request)
#ifdef __ANDROID__
/* fileno() isn't safe on all platforms ... see above. */
if (lseek(fileno(mine->f), skip, SEEK_CUR) < 0)
old_offset = lseek(fileno(mine->f), 0, SEEK_CUR);
#elif HAVE__FSEEKI64
if (_fseeki64(mine->f, skip, SEEK_CUR) != 0)
old_offset = _ftelli64(mine->f);
#elif HAVE_FSEEKO
if (fseeko(mine->f, skip, SEEK_CUR) != 0)
old_offset = ftello(mine->f);
#else
if (fseek(mine->f, skip, SEEK_CUR) != 0)
old_offset = ftell(mine->f);
#endif
{
mine->can_skip = 0;
return (0);
if (old_offset >= 0) {
if (old_offset < mine->size &&
skip <= mine->size - old_offset) {
#ifdef __ANDROID__
new_offset = lseek(fileno(mine->f), skip, SEEK_CUR);
#elif HAVE__FSEEKI64
if (_fseeki64(mine->f, skip, SEEK_CUR) == 0)
new_offset = _ftelli64(mine->f);
#elif HAVE_FSEEKO
if (fseeko(mine->f, skip, SEEK_CUR) == 0)
new_offset = ftello(mine->f);
#else
if (fseek(mine->f, skip, SEEK_CUR) == 0)
new_offset = ftell(mine->f);
#endif
if (new_offset >= 0)
return (new_offset - old_offset);
}
}
return (request);
mine->can_skip = 0;
return (0);
}
/*
* TODO: Store the offset and use it in the read callback.
*/
static int64_t
FILE_seek(struct archive *a, void *client_data, int64_t request, int whence)
{
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
#if HAVE__FSEEKI64
int64_t seek = request;
#elif HAVE_FSEEKO
off_t seek = (off_t)request;
#else
long seek = (long)request;
#endif
int seek_bits = sizeof(seek) * 8 - 1;
(void)a; /* UNUSED */
/* Reduce a request that would overflow the 'seek' variable. */
if (sizeof(request) > sizeof(seek)) {
const int64_t max_seek =
(((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1;
const int64_t min_seek = ~max_seek;
if (request > max_seek)
seek = max_seek;
else if (request < min_seek)
seek = min_seek;
}
#ifdef __ANDROID__
/* Newer Android versions have fseeko...to meditate. */
int64_t ret = lseek(fileno(mine->f), seek, whence);
if (ret >= 0) {
return ret;
}
#elif HAVE__FSEEKI64
if (_fseeki64(mine->f, seek, whence) == 0) {
return _ftelli64(mine->f);
}
#elif HAVE_FSEEKO
if (fseeko(mine->f, seek, whence) == 0) {
return ftello(mine->f);
}
#else
if (fseek(mine->f, seek, whence) == 0) {
return ftell(mine->f);
}
#endif
/* If we arrive here, the input is corrupted or truncated so fail. */
archive_set_error(a, errno, "Error seeking in FILE* pointer");
return (ARCHIVE_FATAL);
}
static int
file_close(struct archive *a, void *client_data)
FILE_close(struct archive *a, void *client_data)
{
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
@@ -74,6 +74,7 @@ struct read_file_data {
size_t block_size;
void *buffer;
mode_t st_mode; /* Mode bits for opened file. */
int64_t size;
char use_lseek;
enum fnt_e { FNT_STDIN, FNT_MBS, FNT_WCS } filename_type;
union {
@@ -303,7 +304,7 @@ file_open(struct archive *a, void *client_data)
}
if (fd < 0) {
archive_set_error(a, errno,
"Failed to open '%S'", wfilename);
"Failed to open '%ls'", wfilename);
return (ARCHIVE_FATAL);
}
#else
@@ -315,7 +316,7 @@ file_open(struct archive *a, void *client_data)
if (fstat(fd, &st) != 0) {
#if defined(_WIN32) && !defined(__CYGWIN__)
if (mine->filename_type == FNT_WCS)
archive_set_error(a, errno, "Can't stat '%S'",
archive_set_error(a, errno, "Can't stat '%ls'",
wfilename);
else
#endif
@@ -400,8 +401,10 @@ file_open(struct archive *a, void *client_data)
mine->st_mode = st.st_mode;
/* Disk-like inputs can use lseek(). */
if (is_disk_like)
if (is_disk_like) {
mine->use_lseek = 1;
mine->size = st.st_size;
}
return (ARCHIVE_OK);
fail:
@@ -447,7 +450,7 @@ file_read(struct archive *a, void *client_data, const void **buff)
"Error reading '%s'", mine->filename.m);
else
archive_set_error(a, errno,
"Error reading '%S'", mine->filename.w);
"Error reading '%ls'", mine->filename.w);
}
return (bytes_read);
}
@@ -479,21 +482,30 @@ file_skip_lseek(struct archive *a, void *client_data, int64_t request)
struct read_file_data *mine = (struct read_file_data *)client_data;
#if defined(_WIN32) && !defined(__CYGWIN__)
/* We use _lseeki64() on Windows. */
int64_t old_offset, new_offset;
int64_t old_offset, new_offset, skip = request;
#else
off_t old_offset, new_offset;
off_t old_offset, new_offset, skip = (off_t)request;
#endif
int skip_bits = sizeof(skip) * 8 - 1;
/* We use off_t here because lseek() is declared that way. */
/* TODO: Deal with case where off_t isn't 64 bits.
* This shouldn't be a problem on Linux or other POSIX
* systems, since the configuration logic for libarchive
* tries to obtain a 64-bit off_t.
*/
if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0 &&
(new_offset = lseek(mine->fd, request, SEEK_CUR)) >= 0)
return (new_offset - old_offset);
/* Reduce a request that would overflow the 'skip' variable. */
if (sizeof(request) > sizeof(skip)) {
const int64_t max_skip =
(((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
if (request > max_skip)
skip = max_skip;
}
if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) {
if (old_offset >= mine->size ||
skip > mine->size - old_offset) {
/* Do not seek past end of file. */
errno = ESPIPE;
} else if ((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0)
return (new_offset - old_offset);
}
/* If lseek() fails, don't bother trying again. */
mine->use_lseek = 0;
@@ -509,7 +521,7 @@ file_skip_lseek(struct archive *a, void *client_data, int64_t request)
archive_set_error(a, errno, "Error seeking in '%s'",
mine->filename.m);
else
archive_set_error(a, errno, "Error seeking in '%S'",
archive_set_error(a, errno, "Error seeking in '%ls'",
mine->filename.w);
return (-1);
}
@@ -540,11 +552,24 @@ static int64_t
file_seek(struct archive *a, void *client_data, int64_t request, int whence)
{
struct read_file_data *mine = (struct read_file_data *)client_data;
off_t seek = (off_t)request;
int64_t r;
int seek_bits = sizeof(seek) * 8 - 1;
/* We use off_t here because lseek() is declared that way. */
/* See above for notes about when off_t is less than 64 bits. */
r = lseek(mine->fd, request, whence);
/* Reduce a request that would overflow the 'seek' variable. */
if (sizeof(request) > sizeof(seek)) {
const int64_t max_seek =
(((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1;
const int64_t min_seek = ~max_seek;
if (request > max_seek)
seek = (off_t)max_seek;
else if (request < min_seek)
seek = (off_t)min_seek;
}
r = lseek(mine->fd, seek, whence);
if (r >= 0)
return r;
@@ -555,7 +580,7 @@ file_seek(struct archive *a, void *client_data, int64_t request, int whence)
archive_set_error(a, errno, "Error seeking in '%s'",
mine->filename.m);
else
archive_set_error(a, errno, "Error seeking in '%S'",
archive_set_error(a, errno, "Error seeking in '%ls'",
mine->filename.w);
return (ARCHIVE_FATAL);
}
@@ -37,46 +37,32 @@ archive_read_support_filter_by_code(struct archive *a, int filter_code)
switch (filter_code) {
case ARCHIVE_FILTER_NONE:
return archive_read_support_filter_none(a);
break;
case ARCHIVE_FILTER_GZIP:
return archive_read_support_filter_gzip(a);
break;
case ARCHIVE_FILTER_BZIP2:
return archive_read_support_filter_bzip2(a);
break;
case ARCHIVE_FILTER_COMPRESS:
return archive_read_support_filter_compress(a);
break;
case ARCHIVE_FILTER_LZMA:
return archive_read_support_filter_lzma(a);
break;
case ARCHIVE_FILTER_XZ:
return archive_read_support_filter_xz(a);
break;
case ARCHIVE_FILTER_UU:
return archive_read_support_filter_uu(a);
break;
case ARCHIVE_FILTER_RPM:
return archive_read_support_filter_rpm(a);
break;
case ARCHIVE_FILTER_LZIP:
return archive_read_support_filter_lzip(a);
break;
case ARCHIVE_FILTER_LRZIP:
return archive_read_support_filter_lrzip(a);
break;
case ARCHIVE_FILTER_LZOP:
return archive_read_support_filter_lzop(a);
break;
case ARCHIVE_FILTER_GRZIP:
return archive_read_support_filter_grzip(a);
break;
case ARCHIVE_FILTER_LZ4:
return archive_read_support_filter_lz4(a);
break;
case ARCHIVE_FILTER_ZSTD:
return archive_read_support_filter_zstd(a);
break;
}
return (ARCHIVE_FATAL);
}
@@ -328,6 +328,7 @@ next_code(struct archive_read_filter *self)
static int debug_buff[1024];
static unsigned debug_index;
again:
code = newcode = getbits(self, state->bits);
if (code < 0)
return (code);
@@ -360,7 +361,7 @@ next_code(struct archive_read_filter *self)
state->section_end_code = (1 << state->bits) - 1;
state->free_ent = 257;
state->oldcode = -1;
return (next_code(self));
goto again;
}
if (code > state->free_ent
@@ -323,7 +323,6 @@ lz4_filter_read(struct archive_read_filter *self, const void **p)
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_MISC, "Program error.");
return (ARCHIVE_FATAL);
break;
}
while (state->stage == SELECT_STREAM) {
@@ -28,6 +28,9 @@
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#if HAVE_STDINT_H
#include <stdint.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@@ -50,6 +53,7 @@
#include "archive_ppmd7_private.h"
#include "archive_private.h"
#include "archive_read_private.h"
#include "archive_time_private.h"
#include "archive_endian.h"
#ifndef HAVE_ZLIB_H
@@ -59,7 +63,26 @@
#define _7ZIP_SIGNATURE "7z\xBC\xAF\x27\x1C"
#define SFX_MIN_ADDR 0x27000
#define SFX_MAX_ADDR 0x60000
#define SFX_MAX_OFFSET (SFX_MAX_ADDR - SFX_MIN_ADDR)
/*
* PE format
*/
#define PE_DOS_HDR_LEN 0x40
#define PE_DOS_HDR_ELFANEW_OFFSET 0x3c
#define PE_COFF_HDR_LEN 0x18
#define PE_COFF_HDR_SEC_CNT_OFFSET 0x6
#define PE_COFF_HDR_OPT_SZ_OFFSET 0x14
#define PE_SEC_HDR_LEN 0x28
#define PE_SEC_HDR_RAW_ADDR_OFFSET 0x14
#define PE_SEC_HDR_RAW_SZ_OFFSET 0x10
/*
* ELF format
*/
#define ELF_HDR_MIN_LEN 0x34
#define ELF_HDR_EI_CLASS_OFFSET 0x04
#define ELF_HDR_EI_DATA_OFFSET 0x05
/*
* Codec ID
@@ -83,6 +106,7 @@
#define _7Z_ARM 0x03030501
#define _7Z_ARMTHUMB 0x03030701
#define _7Z_ARM64 0xa
#define _7Z_RISCV 0xb
#define _7Z_SPARC 0x03030805
#define _7Z_ZSTD 0x4F71101 /* Copied from https://github.com/mcmilk/7-Zip-zstd.git */
@@ -144,7 +168,6 @@ struct _7z_digests {
uint32_t *digests;
};
struct _7z_folder {
uint64_t numCoders;
struct _7z_coder {
@@ -224,13 +247,13 @@ struct _7zip_entry {
#define CRC32_IS_SET (1<<3)
#define HAS_STREAM (1<<4)
time_t mtime;
time_t atime;
time_t ctime;
long mtime_ns;
long atime_ns;
long ctime_ns;
uint32_t mode;
int64_t mtime;
int64_t atime;
int64_t ctime;
uint32_t mtime_ns;
uint32_t atime_ns;
uint32_t ctime_ns;
__LA_MODE_T mode;
uint32_t attr;
};
@@ -388,7 +411,6 @@ static int decode_encoded_header_info(struct archive_read *,
static int decompress(struct archive_read *, struct _7zip *,
void *, size_t *, const void *, size_t *);
static ssize_t extract_pack_stream(struct archive_read *, size_t);
static void fileTimeToUtc(uint64_t, time_t *, long *);
static uint64_t folder_uncompressed_size(struct _7z_folder *);
static void free_CodersInfo(struct _7z_coders_info *);
static void free_Digest(struct _7z_digests *);
@@ -424,7 +446,9 @@ static ssize_t read_stream(struct archive_read *, const void **, size_t,
size_t);
static int seek_pack(struct archive_read *);
static int64_t skip_stream(struct archive_read *, size_t);
static int skip_sfx(struct archive_read *, ssize_t);
static int skip_sfx(struct archive_read *, const ssize_t);
static ssize_t find_pe_overlay(struct archive_read *);
static ssize_t find_elf_data_sec(struct archive_read *);
static int slurp_central_directory(struct archive_read *, struct _7zip *,
struct _7z_header_info *);
static int setup_decode_folder(struct archive_read *, struct _7z_folder *,
@@ -435,6 +459,8 @@ static void arm_Init(struct _7zip *);
static size_t arm_Convert(struct _7zip *, uint8_t *, size_t);
static size_t arm64_Convert(struct _7zip *, uint8_t *, size_t);
static ssize_t Bcj2_Decode(struct _7zip *, uint8_t *, size_t);
static size_t sparc_Convert(struct _7zip *, uint8_t *, size_t);
static size_t powerpc_Convert(struct _7zip *, uint8_t *, size_t);
int
@@ -522,15 +548,17 @@ archive_read_format_7zip_bid(struct archive_read *a, int best_bid)
* It may a 7-Zip SFX archive file. If first two bytes are
* 'M' and 'Z' available on Windows or first four bytes are
* "\x7F\x45LF" available on posix like system, seek the 7-Zip
* signature. Although we will perform a seek when reading
* a header, what we do not use __archive_read_seek() here is
* due to a bidding performance.
* signature. While find_pe_overlay can be performed without
* performing a seek, find_elf_data_sec requires one,
* thus a performance difference between the two is expected.
*/
if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) {
ssize_t offset = SFX_MIN_ADDR;
const ssize_t min_addr = p[0] == 'M' ? find_pe_overlay(a) :
find_elf_data_sec(a);
ssize_t offset = min_addr;
ssize_t window = 4096;
ssize_t bytes_avail;
while (offset + window <= (SFX_MAX_ADDR)) {
while (offset + window <= (min_addr + SFX_MAX_OFFSET)) {
const char *buff = __archive_read_ahead(a,
offset + window, &bytes_avail);
if (buff == NULL) {
@@ -580,21 +608,14 @@ check_7zip_header_in_sfx(const char *p)
}
static int
skip_sfx(struct archive_read *a, ssize_t bytes_avail)
skip_sfx(struct archive_read *a, const ssize_t min_addr)
{
const void *h;
const char *p, *q;
size_t skip, offset;
ssize_t bytes, window;
/*
* If bytes_avail > SFX_MIN_ADDR we do not have to call
* __archive_read_seek() at this time since we have
* already had enough data.
*/
if (bytes_avail > SFX_MIN_ADDR)
__archive_read_consume(a, SFX_MIN_ADDR);
else if (__archive_read_seek(a, SFX_MIN_ADDR, SEEK_SET) < 0)
if (__archive_read_seek(a, min_addr, SEEK_SET) < 0)
return (ARCHIVE_FATAL);
offset = 0;
@@ -627,7 +648,7 @@ skip_sfx(struct archive_read *a, ssize_t bytes_avail)
(struct _7zip *)a->format->data;
skip = p - (const char *)h;
__archive_read_consume(a, skip);
zip->seek_base = SFX_MIN_ADDR + offset + skip;
zip->seek_base = min_addr + offset + skip;
return (ARCHIVE_OK);
}
p += step;
@@ -644,6 +665,207 @@ fatal:
return (ARCHIVE_FATAL);
}
static ssize_t
find_pe_overlay(struct archive_read *a)
{
const char *h;
ssize_t bytes, max_offset, offset, sec_end;
ssize_t opt_hdr_sz, sec_cnt;
for (;;) {
/*
* Read Dos header to find e_lfanew
*/
h = __archive_read_ahead(a, PE_DOS_HDR_LEN, &bytes);
if (h == NULL || h[0] != 'M' || h[1] != 'Z') {
break;
}
offset = archive_le32dec(h + PE_DOS_HDR_ELFANEW_OFFSET);
/*
* Read COFF header to find opt header size and sec cnt
*/
if (bytes < offset + PE_COFF_HDR_LEN) {
h = __archive_read_ahead(a, offset + PE_COFF_HDR_LEN,
&bytes);
if (h == NULL || h[offset] != 'P' ||
h[offset + 1] != 'E') {
break;
}
}
sec_cnt = archive_le16dec(
h + offset + PE_COFF_HDR_SEC_CNT_OFFSET);
opt_hdr_sz = archive_le16dec(
h + offset + PE_COFF_HDR_OPT_SZ_OFFSET);
/*
* Skip optional header
*/
if (opt_hdr_sz != 0) {
offset += PE_COFF_HDR_LEN + opt_hdr_sz;
} else {
break;
}
/*
* Traverse sec table to find max raw offset (i.e., overlay)
*/
if (bytes < offset + sec_cnt * PE_SEC_HDR_LEN) {
h = __archive_read_ahead(a,
offset + sec_cnt * PE_SEC_HDR_LEN, NULL);
if (h == NULL) {
break;
}
}
max_offset = offset;
while (sec_cnt > 0) {
sec_end = archive_le32dec(
h + offset + PE_SEC_HDR_RAW_SZ_OFFSET) +
archive_le32dec(
h + offset + PE_SEC_HDR_RAW_ADDR_OFFSET);
if (sec_end > max_offset) {
max_offset = sec_end;
}
offset += PE_SEC_HDR_LEN;
sec_cnt--;
}
return (max_offset);
}
/*
* If encounter any weirdness, revert to old brute-force style search
*/
return (SFX_MIN_ADDR);
}
static ssize_t
find_elf_data_sec(struct archive_read *a)
{
const char *h;
char big_endian, format_64;
ssize_t bytes, min_addr = SFX_MIN_ADDR;
uint64_t e_shoff, strtab_offset, strtab_size;
uint16_t e_shentsize, e_shnum, e_shstrndx;
uint16_t (*dec16)(const void *);
uint32_t (*dec32)(const void *);
uint64_t (*dec64)(const void *);
for (;;) {
/*
* Read Elf header to find bitness & endianness
*/
h = __archive_read_ahead(a, ELF_HDR_MIN_LEN, &bytes);
if (h == NULL || memcmp(h, "\x7F\x45LF", 4) != 0) {
break;
}
format_64 = h[ELF_HDR_EI_CLASS_OFFSET] == 0x2;
big_endian = h[ELF_HDR_EI_DATA_OFFSET] == 0x2;
if (big_endian) {
dec16 = &archive_be16dec;
dec32 = &archive_be32dec;
dec64 = &archive_be64dec;
} else {
dec16 = &archive_le16dec;
dec32 = &archive_le32dec;
dec64 = &archive_le64dec;
}
/*
* Read section header table info
*/
if (format_64) {
e_shoff = (*dec64)(h + 0x28);
e_shentsize = (*dec16)(h + 0x3A);
e_shnum = (*dec16)(h + 0x3C);
e_shstrndx = (*dec16)(h + 0x3E);
if (e_shnum < e_shstrndx || e_shentsize < 0x28)
break;
} else {
e_shoff = (*dec32)(h + 0x20);
e_shentsize = (*dec16)(h + 0x2E);
e_shnum = (*dec16)(h + 0x30);
e_shstrndx = (*dec16)(h + 0x32);
if (e_shnum < e_shstrndx || e_shentsize < 0x18)
break;
}
/*
* Reading the section table to find strtab section
*/
if (__archive_read_seek(a, e_shoff, SEEK_SET) < 0) {
break;
}
h = __archive_read_ahead(a, (size_t)e_shnum * (size_t)e_shentsize, NULL);
if (h == NULL) {
break;
}
if (format_64) {
strtab_offset = (*dec64)(
h + e_shstrndx * e_shentsize + 0x18);
strtab_size = (*dec64)(
h + e_shstrndx * e_shentsize + 0x20);
} else {
strtab_offset = (*dec32)(
h + e_shstrndx * e_shentsize + 0x10);
strtab_size = (*dec32)(
h + e_shstrndx * e_shentsize + 0x14);
}
/*
* Read the STRTAB section to find the .data offset
*/
if (__archive_read_seek(a, strtab_offset, SEEK_SET) < 0) {
break;
}
h = __archive_read_ahead(a, strtab_size, NULL);
if (h == NULL) {
break;
}
ssize_t data_sym_offset = -1;
for (size_t offset = 0; offset < strtab_size - 6; offset++) {
if (memcmp(h + offset, ".data\00", 6) == 0) {
data_sym_offset = offset;
break;
}
}
if (data_sym_offset == -1) {
break;
}
/*
* Find the section with the .data name
*/
if (__archive_read_seek(a, e_shoff, SEEK_SET) < 0) {
break;
}
h = __archive_read_ahead(a, (size_t)e_shnum * (size_t)e_shentsize, NULL);
if (h == NULL) {
break;
}
ssize_t sec_tbl_offset = 0, name_offset;
while (e_shnum > 0) {
name_offset = (*dec32)(h + sec_tbl_offset);
if (name_offset == data_sym_offset) {
if (format_64) {
min_addr = (*dec64)(
h + sec_tbl_offset + 0x18);
} else {
min_addr = (*dec32)(
h + sec_tbl_offset + 0x10);
}
break;
}
sec_tbl_offset += e_shentsize;
e_shnum--;
}
break;
}
__archive_read_seek(a, 0, SEEK_SET);
return (min_addr);
}
static int
archive_read_format_7zip_read_header(struct archive_read *a,
struct archive_entry *entry)
@@ -770,7 +992,7 @@ archive_read_format_7zip_read_header(struct archive_read *a,
/* allocate for ",rdonly,hidden,system" */
fflags_text = malloc(22 * sizeof(*fflags_text));
if (fflags_text != NULL) {
ptr = fflags_text;
ptr = fflags_text;
if (zip_entry->attr & FILE_ATTRIBUTE_READONLY) {
strcpy(ptr, ",rdonly");
ptr = ptr + 7;
@@ -1109,7 +1331,9 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
if (coder2->codec != _7Z_X86 &&
coder2->codec != _7Z_X86_BCJ2 &&
coder2->codec != _7Z_ARM &&
coder2->codec != _7Z_ARM64) {
coder2->codec != _7Z_ARM64 &&
coder2->codec != _7Z_POWERPC &&
coder2->codec != _7Z_SPARC) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Unsupported filter %lx for %lx",
@@ -1223,6 +1447,12 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
filters[fi].id = LZMA_FILTER_ARM64;
fi++;
break;
#endif
#ifdef LZMA_FILTER_RISCV
case _7Z_RISCV:
filters[fi].id = LZMA_FILTER_RISCV;
fi++;
break;
#endif
case _7Z_SPARC:
filters[fi].id = LZMA_FILTER_SPARC;
@@ -1396,6 +1626,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
case _7Z_ARM:
case _7Z_ARMTHUMB:
case _7Z_ARM64:
case _7Z_RISCV:
case _7Z_SPARC:
case _7Z_DELTA:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@@ -1708,6 +1939,10 @@ decompress(struct archive_read *a, struct _7zip *zip,
*outbytes = arm_Convert(zip, buff, *outbytes);
} else if (zip->codec2 == _7Z_ARM64) {
*outbytes = arm64_Convert(zip, buff, *outbytes);
} else if (zip->codec2 == _7Z_SPARC) {
*outbytes = sparc_Convert(zip, buff, *outbytes);
} else if (zip->codec2 == _7Z_POWERPC) {
*outbytes = powerpc_Convert(zip, buff, *outbytes);
}
}
@@ -2841,23 +3076,6 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
return (0);
}
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
static void
fileTimeToUtc(uint64_t fileTime, time_t *timep, long *ns)
{
if (fileTime >= EPOC_TIME) {
fileTime -= EPOC_TIME;
/* milli seconds base */
*timep = (time_t)(fileTime / 10000000);
/* nano seconds base */
*ns = (long)(fileTime % 10000000) * 100;
} else {
*timep = 0;
*ns = 0;
}
}
static int
read_Times(struct archive_read *a, struct _7z_header_info *h, int type)
{
@@ -2900,19 +3118,19 @@ read_Times(struct archive_read *a, struct _7z_header_info *h, int type)
goto failed;
switch (type) {
case kCTime:
fileTimeToUtc(archive_le64dec(p),
ntfs_to_unix(archive_le64dec(p),
&(entries[i].ctime),
&(entries[i].ctime_ns));
entries[i].flg |= CTIME_IS_SET;
break;
case kATime:
fileTimeToUtc(archive_le64dec(p),
ntfs_to_unix(archive_le64dec(p),
&(entries[i].atime),
&(entries[i].atime_ns));
entries[i].flg |= ATIME_IS_SET;
break;
case kMTime:
fileTimeToUtc(archive_le64dec(p),
ntfs_to_unix(archive_le64dec(p),
&(entries[i].mtime),
&(entries[i].mtime_ns));
entries[i].flg |= MTIME_IS_SET;
@@ -3007,7 +3225,9 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip,
if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) {
/* This is an executable ? Must be self-extracting... */
r = skip_sfx(a, bytes_avail);
const ssize_t min_addr = p[0] == 'M' ? find_pe_overlay(a) :
find_elf_data_sec(a);
r = skip_sfx(a, min_addr);
if (r < ARCHIVE_WARN)
return (r);
if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL)
@@ -4007,6 +4227,121 @@ arm64_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
return i;
}
static size_t
sparc_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
{
// This function was adapted from
// static size_t bcj_sparc(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
// in https://git.tukaani.org/xz-embedded.git
/*
* Branch/Call/Jump (BCJ) filter decoders
*
* Authors: Lasse Collin <lasse.collin@tukaani.org>
* Igor Pavlov <https://7-zip.org/>
*
* Copyright (C) The XZ Embedded authors and contributors
*
* Permission to use, copy, modify, and/or distribute this
* software for any purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
size_t i;
uint32_t instr;
size &= ~(size_t)3;
for (i = 0; i < size; i += 4) {
instr = (uint32_t)(buf[i] << 24)
| ((uint32_t)buf[i+1] << 16)
| ((uint32_t)buf[i+2] << 8)
| (uint32_t)buf[i+3];
if ((instr >> 22) == 0x100 || (instr >> 22) == 0x1FF) {
instr <<= 2;
instr -= zip->bcj_ip + (uint32_t)i;
instr >>= 2;
instr = ((uint32_t)0x40000000 - (instr & 0x400000))
| 0x40000000 | (instr & 0x3FFFFF);
buf[i] = (uint8_t)(instr >> 24);
buf[i+1] = (uint8_t)(instr >> 16);
buf[i+2] = (uint8_t)(instr >> 8);
buf[i+3] = (uint8_t)instr;
}
}
zip->bcj_ip += (uint32_t)i;
return i;
}
static size_t
powerpc_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
{
// This function was adapted from
// static size_t powerpc_code(void *simple, uint32_t now_pos, bool is_encoder, uint8_t *buffer, size_t size)
// in https://git.tukaani.org/xz.git
/*
* Filter for PowerPC (big endian) binaries
*
* Authors: Igor Pavlov
* Lasse Collin
*
* Copyright (C) The XZ Utils authors and contributors
*
* Permission to use, copy, modify, and/or distribute this
* software for any purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
size &= ~(size_t)3;
size_t i;
for (i = 0; i < size; i += 4) {
// PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link)
if ((buf[i] >> 2) == 0x12
&& ((buf[i + 3] & 3) == 1)) {
const uint32_t src
= (((uint32_t)(buf[i + 0]) & 3) << 24)
| ((uint32_t)(buf[i + 1]) << 16)
| ((uint32_t)(buf[i + 2]) << 8)
| ((uint32_t)(buf[i + 3]) & ~UINT32_C(3));
uint32_t dest = src - (zip->bcj_ip + (uint32_t)(i));
buf[i + 0] = 0x48 | ((dest >> 24) & 0x03);
buf[i + 1] = (dest >> 16);
buf[i + 2] = (dest >> 8);
buf[i + 3] &= 0x03;
buf[i + 3] |= dest;
}
}
zip->bcj_ip += (uint32_t)i;
return i;
}
/*
* Brought from LZMA SDK.
*
@@ -4029,8 +4364,17 @@ arm64_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
#define RC_READ_BYTE (*buffer++)
#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }
#define RC_INIT2 zip->bcj2_code = 0; zip->bcj2_range = 0xFFFFFFFF; \
{ int ii; for (ii = 0; ii < 5; ii++) { RC_TEST; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; }}
#define RC_INIT2 do { \
zip->bcj2_code = 0; \
zip->bcj2_range = 0xFFFFFFFF; \
{ \
int ii; \
for (ii = 0; ii < 5; ii++) { \
RC_TEST; \
zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; \
} \
} \
} while (0)
#define NORMALIZE if (zip->bcj2_range < kTopValue) { RC_TEST; zip->bcj2_range <<= 8; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; }
@@ -4177,4 +4521,3 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize)
return ((ssize_t)outPos);
}
@@ -41,49 +41,34 @@ archive_read_support_format_by_code(struct archive *a, int format_code)
switch (format_code & ARCHIVE_FORMAT_BASE_MASK) {
case ARCHIVE_FORMAT_7ZIP:
return archive_read_support_format_7zip(a);
break;
case ARCHIVE_FORMAT_AR:
return archive_read_support_format_ar(a);
break;
case ARCHIVE_FORMAT_CAB:
return archive_read_support_format_cab(a);
break;
case ARCHIVE_FORMAT_CPIO:
return archive_read_support_format_cpio(a);
break;
case ARCHIVE_FORMAT_EMPTY:
return archive_read_support_format_empty(a);
break;
case ARCHIVE_FORMAT_ISO9660:
return archive_read_support_format_iso9660(a);
break;
case ARCHIVE_FORMAT_LHA:
return archive_read_support_format_lha(a);
break;
case ARCHIVE_FORMAT_MTREE:
return archive_read_support_format_mtree(a);
break;
case ARCHIVE_FORMAT_RAR:
return archive_read_support_format_rar(a);
break;
case ARCHIVE_FORMAT_RAR_V5:
return archive_read_support_format_rar5(a);
break;
case ARCHIVE_FORMAT_RAW:
return archive_read_support_format_raw(a);
break;
case ARCHIVE_FORMAT_TAR:
return archive_read_support_format_tar(a);
break;
case ARCHIVE_FORMAT_WARC:
return archive_read_support_format_warc(a);
break;
case ARCHIVE_FORMAT_XAR:
return archive_read_support_format_xar(a);
break;
case ARCHIVE_FORMAT_ZIP:
return archive_read_support_format_zip(a);
break;
}
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
"Invalid format code specified");
@@ -363,7 +363,12 @@ archive_read_support_format_cab(struct archive *_a)
return (ARCHIVE_FATAL);
}
archive_string_init(&cab->ws);
archive_wstring_ensure(&cab->ws, 256);
if (archive_wstring_ensure(&cab->ws, 256) == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory");
free(cab);
return (ARCHIVE_FATAL);
}
r = __archive_read_register_format(a,
cab,
@@ -189,6 +189,7 @@ struct cpio {
};
static int64_t atol16(const char *, unsigned);
static uint64_t atol16u(const char *, unsigned);
static int64_t atol8(const char *, unsigned);
static int archive_read_format_cpio_bid(struct archive_read *, int);
static int archive_read_format_cpio_options(struct archive_read *,
@@ -835,6 +836,7 @@ header_afiol(struct archive_read *a, struct cpio *cpio,
struct archive_entry *entry, size_t *namelength, size_t *name_pad)
{
int64_t t;
uint64_t u;
const void *h;
const char *header;
@@ -851,12 +853,12 @@ header_afiol(struct archive_read *a, struct cpio *cpio,
archive_entry_set_dev(entry,
(dev_t)atol16(header + afiol_dev_offset, afiol_dev_size));
t = atol16(header + afiol_ino_offset, afiol_ino_size);
if (t < 0) {
archive_set_error(&a->archive, 0, "Nonsensical ino value");
return (ARCHIVE_FATAL);
}
archive_entry_set_ino(entry, t);
u = atol16u(header + afiol_ino_offset, afiol_ino_size);
#if ARCHIVE_VERSION_NUMBER < 4000000
archive_entry_set_ino(entry, (int64_t)(u & INT64_MAX));
#else
archive_entry_set_ino(entry, u);
#endif
archive_entry_set_mode(entry,
(mode_t)atol8(header + afiol_mode_offset, afiol_mode_size));
archive_entry_set_uid(entry, atol16(header + afiol_uid_offset, afiol_uid_size));
@@ -1030,6 +1032,12 @@ atol8(const char *p, unsigned char_cnt)
static int64_t
atol16(const char *p, unsigned char_cnt)
{
return ((int64_t)atol16u(p, char_cnt));
}
static uint64_t
atol16u(const char *p, unsigned char_cnt)
{
uint64_t l;
int digit;
@@ -1048,7 +1056,7 @@ atol16(const char *p, unsigned char_cnt)
l <<= 4;
l |= digit;
}
return ((int64_t)l);
return (l);
}
static int
@@ -1429,7 +1429,7 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
* information first, then store all file bodies. */
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Ignoring out-of-order file @%jx (%s) %jd < %jd",
(intmax_t)file->number,
(uintmax_t)file->number,
iso9660->pathname.s,
(intmax_t)file->offset,
(intmax_t)iso9660->current_position);
@@ -2273,7 +2273,7 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
if (version == 1) {
if (data_length >= 8)
file->mode
= toi(data, 4);
= (__LA_MODE_T)toi(data, 4);
if (data_length >= 16)
file->nlinks
= toi(data + 8, 4);
@@ -43,6 +43,7 @@
#include "archive_entry_locale.h"
#include "archive_private.h"
#include "archive_read_private.h"
#include "archive_time_private.h"
#include "archive_endian.h"
@@ -162,12 +163,12 @@ struct lha {
#define ATIME_IS_SET 2
#define UNIX_MODE_IS_SET 4
#define CRC_IS_SET 8
time_t birthtime;
long birthtime_tv_nsec;
time_t mtime;
long mtime_tv_nsec;
time_t atime;
long atime_tv_nsec;
int64_t birthtime;
uint32_t birthtime_tv_nsec;
int64_t mtime;
uint32_t mtime_tv_nsec;
int64_t atime;
uint32_t atime_tv_nsec;
mode_t mode;
int64_t uid;
int64_t gid;
@@ -230,8 +231,6 @@ static int lha_read_file_extended_header(struct archive_read *,
struct lha *, uint16_t *, int, uint64_t, size_t *);
static size_t lha_check_header_format(const void *);
static int lha_skip_sfx(struct archive_read *);
static time_t lha_dos_time(const unsigned char *);
static time_t lha_win_time(uint64_t, long *);
static unsigned char lha_calcsum(unsigned char, const void *,
int, size_t);
static int lha_parse_linkname(struct archive_wstring *,
@@ -819,7 +818,7 @@ lha_read_file_header_0(struct archive_read *a, struct lha *lha)
headersum = p[H0_HEADER_SUM_OFFSET];
lha->compsize = archive_le32dec(p + H0_COMP_SIZE_OFFSET);
lha->origsize = archive_le32dec(p + H0_ORIG_SIZE_OFFSET);
lha->mtime = lha_dos_time(p + H0_DOS_TIME_OFFSET);
lha->mtime = dos_to_unix(archive_le32dec(p + H0_DOS_TIME_OFFSET));
namelen = p[H0_NAME_LEN_OFFSET];
extdsize = (int)lha->header_size - H0_FIXED_SIZE - namelen;
if ((namelen > 221 || extdsize < 0) && extdsize != -2) {
@@ -919,7 +918,7 @@ lha_read_file_header_1(struct archive_read *a, struct lha *lha)
/* Note: An extended header size is included in a compsize. */
lha->compsize = archive_le32dec(p + H1_COMP_SIZE_OFFSET);
lha->origsize = archive_le32dec(p + H1_ORIG_SIZE_OFFSET);
lha->mtime = lha_dos_time(p + H1_DOS_TIME_OFFSET);
lha->mtime = dos_to_unix(archive_le32dec(p + H1_DOS_TIME_OFFSET));
namelen = p[H1_NAME_LEN_OFFSET];
/* Calculate a padding size. The result will be normally 0 only(?) */
padding = ((int)lha->header_size) - H1_FIXED_SIZE - namelen;
@@ -1090,7 +1089,7 @@ lha_read_file_header_3(struct archive_read *a, struct lha *lha)
if (archive_le16dec(p + H3_FIELD_LEN_OFFSET) != 4)
goto invalid;
lha->header_size =archive_le32dec(p + H3_HEADER_SIZE_OFFSET);
lha->header_size = archive_le32dec(p + H3_HEADER_SIZE_OFFSET);
lha->compsize = archive_le32dec(p + H3_COMP_SIZE_OFFSET);
lha->origsize = archive_le32dec(p + H3_ORIG_SIZE_OFFSET);
lha->mtime = archive_le32dec(p + H3_TIME_OFFSET);
@@ -1326,16 +1325,16 @@ lha_read_file_extended_header(struct archive_read *a, struct lha *lha,
break;
case EXT_TIMESTAMP:
if (datasize == (sizeof(uint64_t) * 3)) {
lha->birthtime = lha_win_time(
archive_le64dec(extdheader),
ntfs_to_unix(archive_le64dec(extdheader),
&lha->birthtime,
&lha->birthtime_tv_nsec);
extdheader += sizeof(uint64_t);
lha->mtime = lha_win_time(
archive_le64dec(extdheader),
ntfs_to_unix(archive_le64dec(extdheader),
&lha->mtime,
&lha->mtime_tv_nsec);
extdheader += sizeof(uint64_t);
lha->atime = lha_win_time(
archive_le64dec(extdheader),
ntfs_to_unix(archive_le64dec(extdheader),
&lha->atime,
&lha->atime_tv_nsec);
lha->setflag |= BIRTHTIME_IS_SET |
ATIME_IS_SET;
@@ -1716,45 +1715,6 @@ lha_parse_linkname(struct archive_wstring *linkname,
return (0);
}
/* Convert an MSDOS-style date/time into Unix-style time. */
static time_t
lha_dos_time(const unsigned char *p)
{
int msTime, msDate;
struct tm ts;
msTime = archive_le16dec(p);
msDate = archive_le16dec(p+2);
memset(&ts, 0, sizeof(ts));
ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */
ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */
ts.tm_mday = msDate & 0x1f; /* Day of month. */
ts.tm_hour = (msTime >> 11) & 0x1f;
ts.tm_min = (msTime >> 5) & 0x3f;
ts.tm_sec = (msTime << 1) & 0x3e;
ts.tm_isdst = -1;
return (mktime(&ts));
}
/* Convert an MS-Windows-style date/time into Unix-style time. */
static time_t
lha_win_time(uint64_t wintime, long *ns)
{
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
if (wintime >= EPOC_TIME) {
wintime -= EPOC_TIME; /* 1970-01-01 00:00:00 (UTC) */
if (ns != NULL)
*ns = (long)(wintime % 10000000) * 100;
return (wintime / 10000000);
} else {
if (ns != NULL)
*ns = 0;
return (0);
}
}
static unsigned char
lha_calcsum(unsigned char sum, const void *pp, int offset, size_t size)
{
@@ -2917,4 +2877,3 @@ lzh_decode_huffman(struct huffman *hf, unsigned rbits)
/* This bit pattern needs to be found out at a huffman tree. */
return (lzh_decode_huffman_tree(hf, rbits, c));
}
@@ -335,8 +335,8 @@ struct rar
int found_first_header;
char has_endarc_header;
struct data_block_offsets *dbo;
unsigned int cursor;
unsigned int nodes;
size_t cursor;
size_t nodes;
char filename_must_match;
/* LZSS members */
@@ -451,7 +451,7 @@ static int read_filter(struct archive_read *, int64_t *);
static int rar_decode_byte(struct archive_read*, uint8_t *);
static int execute_filter(struct archive_read*, struct rar_filter *,
struct rar_virtual_machine *, size_t);
static int copy_from_lzss_window(struct archive_read *, void *, int64_t, int);
static int copy_from_lzss_window(struct archive_read *, uint8_t *, int64_t, int);
static inline void vm_write_32(struct rar_virtual_machine*, size_t, uint32_t);
static inline uint32_t vm_read_32(struct rar_virtual_machine*, size_t);
@@ -475,7 +475,7 @@ static inline uint32_t vm_read_32(struct rar_virtual_machine*, size_t);
((rar_br_has(br, (n)) || rar_br_fillup(a, br)) || rar_br_has(br, (n)))
/* Notify how many bits we consumed. */
#define rar_br_consume(br, n) ((br)->cache_avail -= (n))
#define rar_br_consume_unalined_bits(br) ((br)->cache_avail &= ~7)
#define rar_br_consume_unaligned_bits(br) ((br)->cache_avail &= ~7)
static const uint32_t cache_masks[] = {
0x00000000, 0x00000001, 0x00000003, 0x00000007,
@@ -741,11 +741,11 @@ archive_read_support_format_rar(struct archive *_a)
return (ARCHIVE_FATAL);
}
/*
* Until enough data has been read, we cannot tell about
* any encrypted entries yet.
*/
rar->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
/*
* Until enough data has been read, we cannot tell about
* any encrypted entries yet.
*/
rar->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
r = __archive_read_register_format(a,
rar,
@@ -768,21 +768,21 @@ archive_read_support_format_rar(struct archive *_a)
static int
archive_read_support_format_rar_capabilities(struct archive_read * a)
{
(void)a; /* UNUSED */
return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA
| ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
(void)a; /* UNUSED */
return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA
| ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
}
static int
archive_read_format_rar_has_encrypted_entries(struct archive_read *_a)
{
if (_a && _a->format) {
struct rar * rar = (struct rar *)_a->format->data;
if (rar) {
return rar->has_encrypted_entries;
}
}
return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
if (_a && _a->format) {
struct rar * rar = (struct rar *)_a->format->data;
if (rar) {
return rar->has_encrypted_entries;
}
}
return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
}
@@ -793,7 +793,7 @@ archive_read_format_rar_bid(struct archive_read *a, int best_bid)
/* If there's already a bid > 30, we'll never win. */
if (best_bid > 30)
return (-1);
return (-1);
if ((p = __archive_read_ahead(a, 7, NULL)) == NULL)
return (-1);
@@ -865,7 +865,7 @@ skip_sfx(struct archive_read *a)
}
skip = p - (const char *)h;
__archive_read_consume(a, skip);
total += skip;
total += skip;
}
fatal:
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
@@ -910,7 +910,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
const void *h;
const char *p;
struct rar *rar;
size_t skip;
int64_t skip;
char head_type;
int ret;
unsigned flags;
@@ -930,7 +930,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
* as well.
*/
if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
rar->has_encrypted_entries = 0;
rar->has_encrypted_entries = 0;
}
/* RAR files can be generated without EOF headers, so return ARCHIVE_EOF if
@@ -953,8 +953,11 @@ archive_read_format_rar_read_header(struct archive_read *a,
{
unsigned long crc32_val;
if ((h = __archive_read_ahead(a, 7, NULL)) == NULL)
if ((h = __archive_read_ahead(a, 7, NULL)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Failed to read next header.");
return (ARCHIVE_FATAL);
}
p = h;
head_type = p[2];
@@ -972,7 +975,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
case MAIN_HEAD:
rar->main_flags = archive_le16dec(p + 3);
skip = archive_le16dec(p + 5);
if (skip < 7 + sizeof(rar->reserved1) + sizeof(rar->reserved2)) {
if ((size_t)skip < 7 + sizeof(rar->reserved1) + sizeof(rar->reserved2)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Invalid header size");
return (ARCHIVE_FATAL);
@@ -984,7 +987,8 @@ archive_read_format_rar_read_header(struct archive_read *a,
memcpy(rar->reserved2, p + 7 + sizeof(rar->reserved1),
sizeof(rar->reserved2));
if (rar->main_flags & MHD_ENCRYPTVER) {
if (skip < 7 + sizeof(rar->reserved1) + sizeof(rar->reserved2)+1) {
if ((size_t)skip <
7 + sizeof(rar->reserved1) + sizeof(rar->reserved2) + 1) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Invalid header size");
return (ARCHIVE_FATAL);
@@ -1053,28 +1057,30 @@ archive_read_format_rar_read_header(struct archive_read *a,
/* Skim the entire header and compute the CRC. */
crc32_val = 0;
while (skip > 0) {
size_t to_read = skip;
if (to_read > 32 * 1024)
to_read = 32 * 1024;
if ((h = __archive_read_ahead(a, to_read, NULL)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Bad RAR file");
return (ARCHIVE_FATAL);
}
p = h;
crc32_val = crc32(crc32_val, (const unsigned char *)p, (unsigned int)to_read);
__archive_read_consume(a, to_read);
skip -= to_read;
unsigned to_read;
if (skip > 32 * 1024)
to_read = 32 * 1024;
else
to_read = (unsigned)skip;
if ((h = __archive_read_ahead(a, to_read, NULL)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Bad RAR file");
return (ARCHIVE_FATAL);
}
p = h;
crc32_val = crc32(crc32_val, (const unsigned char *)p, to_read);
__archive_read_consume(a, to_read);
skip -= to_read;
}
if ((crc32_val & 0xffff) != crc32_expected) {
#ifndef DONT_FAIL_ON_CRC_ERROR
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Header CRC error");
return (ARCHIVE_FATAL);
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Header CRC error");
return (ARCHIVE_FATAL);
#endif
}
if (head_type == ENDARC_HEAD)
return (ARCHIVE_EOF);
return (ARCHIVE_EOF);
break;
case NEWSUB_HEAD:
@@ -1083,7 +1089,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
break;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Bad RAR file");
return (ARCHIVE_FATAL);
}
@@ -1098,7 +1104,7 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
int ret;
if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
rar->has_encrypted_entries = 0;
rar->has_encrypted_entries = 0;
}
if (rar->bytes_unconsumed > 0) {
@@ -1186,7 +1192,7 @@ archive_read_format_rar_seek_data(struct archive_read *a, int64_t offset,
int whence)
{
int64_t client_offset, ret;
unsigned int i;
size_t i;
struct rar *rar = (struct rar *)(a->format->data);
if (rar->compression_method == COMPRESS_METHOD_STORE)
@@ -1433,7 +1439,11 @@ read_header(struct archive_read *a, struct archive_entry *entry,
}
if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Failed to read full header content.");
return (ARCHIVE_FATAL);
}
/* File Header CRC check. */
crc32_computed = crc32(crc32_computed, h, (unsigned)(header_size - 7));
@@ -1460,8 +1470,8 @@ read_header(struct archive_read *a, struct archive_entry *entry,
if (rar->file_flags & FHD_PASSWORD)
{
archive_entry_set_is_data_encrypted(entry, 1);
rar->has_encrypted_entries = 1;
archive_entry_set_is_data_encrypted(entry, 1);
rar->has_encrypted_entries = 1;
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"RAR encryption support unavailable.");
/* Since it is only the data part itself that is encrypted we can at least
@@ -1506,10 +1516,23 @@ read_header(struct archive_read *a, struct archive_entry *entry,
*/
if (head_type == NEWSUB_HEAD) {
size_t distance = p - (const char *)h;
if (rar->packed_size > INT64_MAX - header_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Extended header size too large.");
return (ARCHIVE_FATAL);
}
header_size += rar->packed_size;
if ((uintmax_t)header_size > SIZE_MAX) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Unable to read extended header data.");
return (ARCHIVE_FATAL);
}
/* Make sure we have the extended data. */
if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL)
return (ARCHIVE_FATAL);
if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Failed to read extended header data.");
return (ARCHIVE_FATAL);
}
p = h;
endp = p + header_size - 7;
p += distance;
@@ -1670,6 +1693,8 @@ read_header(struct archive_read *a, struct archive_entry *entry,
!memcmp(rar->filename, rar->filename_save, filename_size + 1))
{
__archive_read_consume(a, header_size - 7);
rar->br.avail_in = 0;
rar->br.next_in = NULL;
rar->cursor++;
if (rar->cursor >= rar->nodes)
{
@@ -1689,6 +1714,12 @@ read_header(struct archive_read *a, struct archive_entry *entry,
}
if (rar->dbo[rar->cursor].start_offset < 0)
{
if (rar->packed_size > INT64_MAX - a->filter->position)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Unable to store offsets.");
return (ARCHIVE_FATAL);
}
rar->dbo[rar->cursor].start_offset = a->filter->position;
rar->dbo[rar->cursor].end_offset = rar->dbo[rar->cursor].start_offset +
rar->packed_size;
@@ -1745,6 +1776,11 @@ read_header(struct archive_read *a, struct archive_entry *entry,
}
__archive_read_consume(a, header_size - 7);
if (rar->packed_size > INT64_MAX - a->filter->position) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Unable to store offsets.");
return (ARCHIVE_FATAL);
}
rar->dbo[0].start_offset = a->filter->position;
rar->dbo[0].end_offset = rar->dbo[0].start_offset + rar->packed_size;
@@ -1753,7 +1789,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
case OS_MSDOS:
case OS_OS2:
case OS_WIN32:
rar->mode = archive_le32dec(file_header.file_attr);
rar->mode = (__LA_MODE_T)archive_le32dec(file_header.file_attr);
if (rar->mode & FILE_ATTRIBUTE_DIRECTORY)
rar->mode = AE_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
else
@@ -1764,7 +1800,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
case OS_UNIX:
case OS_MAC_OS:
case OS_BEOS:
rar->mode = archive_le32dec(file_header.file_attr);
rar->mode = (__LA_MODE_T)archive_le32dec(file_header.file_attr);
break;
default:
@@ -1780,6 +1816,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
rar->offset_outgoing = 0;
rar->br.cache_avail = 0;
rar->br.avail_in = 0;
rar->br.next_in = NULL;
rar->crc_calculated = 0;
rar->entry_eof = 0;
rar->valid = 1;
@@ -1941,8 +1978,18 @@ read_symlink_stored(struct archive_read *a, struct archive_entry *entry,
int ret = (ARCHIVE_OK);
rar = (struct rar *)(a->format->data);
if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL)
if ((uintmax_t)rar->packed_size > SIZE_MAX)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Unable to read link.");
return (ARCHIVE_FATAL);
}
if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Failed to read link.");
return (ARCHIVE_FATAL);
}
p = h;
if (archive_entry_copy_symlink_l(entry,
@@ -2224,7 +2271,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
ret = expand(a, &end);
if (ret != ARCHIVE_OK)
return (ret);
return (ret);
rar->bytes_uncopied = end - start;
rar->filters.lastend = end;
@@ -2276,7 +2323,7 @@ parse_codes(struct archive_read *a)
free_codes(a);
/* Skip to the next byte */
rar_br_consume_unalined_bits(br);
rar_br_consume_unaligned_bits(br);
/* PPMd block flag */
if (!rar_br_read_ahead(a, br, 1))
@@ -2332,9 +2379,9 @@ parse_codes(struct archive_read *a)
__archive_ppmd7_functions.Ppmd7_Construct(&rar->ppmd7_context);
if (rar->dictionary_size == 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Invalid zero dictionary size");
return (ARCHIVE_FATAL);
return (ARCHIVE_FATAL);
}
if (!__archive_ppmd7_functions.Ppmd7_Alloc(&rar->ppmd7_context,
@@ -2803,7 +2850,7 @@ make_table(struct archive_read *a, struct huffman_code *code)
else
code->tablesize = code->maxlength;
code->table = calloc(1U << code->tablesize, sizeof(*code->table));
code->table = calloc(((size_t)1U) << code->tablesize, sizeof(*code->table));
return make_table_recurse(a, code, 0, code->table, 0, code->tablesize);
}
@@ -2929,11 +2976,11 @@ expand(struct archive_read *a, int64_t *end)
}
if ((symbol = read_next_symbol(a, &rar->maincode)) < 0)
return (ARCHIVE_FATAL);
goto bad_data;
if (symbol < 256)
{
lzss_emit_literal(rar, symbol);
lzss_emit_literal(rar, (uint8_t)symbol);
continue;
}
else if (symbol == 256)
@@ -2956,14 +3003,14 @@ expand(struct archive_read *a, int64_t *end)
else
{
if (parse_codes(a) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
goto bad_data;
continue;
}
}
else if(symbol==257)
{
if (!read_filter(a, end))
return (ARCHIVE_FATAL);
goto bad_data;
continue;
}
else if(symbol==258)
@@ -3048,7 +3095,7 @@ expand(struct archive_read *a, int64_t *end)
{
if ((lowoffsetsymbol =
read_next_symbol(a, &rar->lowoffsetcode)) < 0)
return (ARCHIVE_FATAL);
goto bad_data;
if(lowoffsetsymbol == 16)
{
rar->numlowoffsetrepeats = 15;
@@ -3096,7 +3143,7 @@ bad_data:
}
static int
copy_from_lzss_window(struct archive_read *a, void *buffer,
copy_from_lzss_window(struct archive_read *a, uint8_t *buffer,
int64_t startpos, int length)
{
int windowoffs, firstpart;
@@ -3111,7 +3158,7 @@ copy_from_lzss_window(struct archive_read *a, void *buffer,
}
if (firstpart < length) {
memcpy(buffer, &rar->lzss.window[windowoffs], firstpart);
memcpy(buffer, &rar->lzss.window[0], length - firstpart);
memcpy(buffer + firstpart, &rar->lzss.window[0], length - firstpart);
} else {
memcpy(buffer, &rar->lzss.window[windowoffs], length);
}
@@ -3180,8 +3227,12 @@ static const void *
rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
{
struct rar *rar = (struct rar *)(a->format->data);
const void *h = __archive_read_ahead(a, min, avail);
const void *h;
int ret;
again:
h = __archive_read_ahead(a, min, avail);
if (avail)
{
if (a->archive.read_data_is_posix_read && *avail > (ssize_t)a->archive.read_data_requested)
@@ -3203,7 +3254,7 @@ rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
rar->filename_must_match = 0;
if (ret != (ARCHIVE_OK))
return NULL;
return rar_read_ahead(a, min, avail);
goto again;
}
}
return h;
@@ -3266,6 +3317,9 @@ parse_filter(struct archive_read *a, const uint8_t *bytes, uint16_t length, uint
else
blocklength = prog ? prog->oldfilterlength : 0;
if (blocklength > rar->dictionary_size)
return 0;
registers[3] = PROGRAM_SYSTEM_GLOBAL_ADDRESS;
registers[4] = blocklength;
registers[5] = prog ? prog->usagecount : 0;
@@ -46,6 +46,7 @@
#include "archive_entry_locale.h"
#include "archive_ppmd7_private.h"
#include "archive_entry_private.h"
#include "archive_time_private.h"
#ifdef HAVE_BLAKE2_H
#include <blake2.h>
@@ -100,10 +101,12 @@ struct file_header {
uint8_t dir : 1; /* Is this file entry a directory? */
/* Optional time fields. */
uint64_t e_mtime;
uint64_t e_ctime;
uint64_t e_atime;
uint32_t e_unix_ns;
int64_t e_mtime;
int64_t e_ctime;
int64_t e_atime;
uint32_t e_mtime_ns;
uint32_t e_ctime_ns;
uint32_t e_atime_ns;
/* Optional hash fields. */
uint32_t stored_crc32;
@@ -691,7 +694,8 @@ static int run_filter(struct archive_read* a, struct filter_info* flt) {
default:
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Unsupported filter type: 0x%x", flt->type);
"Unsupported filter type: 0x%x",
(unsigned int)flt->type);
return ARCHIVE_FATAL;
}
@@ -1100,22 +1104,22 @@ static int read_consume_bits(struct archive_read* a, struct rar5* rar,
return ARCHIVE_OK;
}
static int read_u32(struct archive_read* a, uint32_t* pvalue) {
static char read_u32(struct archive_read* a, uint32_t* pvalue) {
const uint8_t* p;
if(!read_ahead(a, 4, &p))
return 0;
*pvalue = archive_le32dec(p);
return ARCHIVE_OK == consume(a, 4) ? 1 : 0;
return ARCHIVE_OK == consume(a, 4);
}
static int read_u64(struct archive_read* a, uint64_t* pvalue) {
static char read_u64(struct archive_read* a, uint64_t* pvalue) {
const uint8_t* p;
if(!read_ahead(a, 8, &p))
return 0;
*pvalue = archive_le64dec(p);
return ARCHIVE_OK == consume(a, 8) ? 1 : 0;
return ARCHIVE_OK == consume(a, 8);
}
static int bid_standard(struct archive_read* a) {
@@ -1293,21 +1297,15 @@ static int parse_file_extra_hash(struct archive_read* a, struct rar5* rar,
*extra_data_size -= hash_size;
} else {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Unsupported hash type (0x%x)", (int) hash_type);
"Unsupported hash type (0x%jx)", (uintmax_t)hash_type);
return ARCHIVE_FATAL;
}
return ARCHIVE_OK;
}
static uint64_t time_win_to_unix(uint64_t win_time) {
const size_t ns_in_sec = 10000000;
const uint64_t sec_to_unix = 11644473600LL;
return win_time / ns_in_sec - sec_to_unix;
}
static int parse_htime_item(struct archive_read* a, char unix_time,
uint64_t* where, int64_t* extra_data_size)
int64_t* sec, uint32_t* nsec, int64_t* extra_data_size)
{
if(unix_time) {
uint32_t time_val;
@@ -1315,13 +1313,13 @@ static int parse_htime_item(struct archive_read* a, char unix_time,
return ARCHIVE_EOF;
*extra_data_size -= 4;
*where = (uint64_t) time_val;
*sec = (int64_t) time_val;
} else {
uint64_t windows_time;
if(!read_u64(a, &windows_time))
return ARCHIVE_EOF;
*where = time_win_to_unix(windows_time);
ntfs_to_unix(windows_time, sec, nsec);
*extra_data_size -= 8;
}
@@ -1385,7 +1383,7 @@ static int parse_file_extra_version(struct archive_read* a,
static int parse_file_extra_htime(struct archive_read* a,
struct archive_entry* e, struct rar5* rar, int64_t* extra_data_size)
{
char unix_time = 0;
char unix_time, has_unix_ns, has_mtime, has_ctime, has_atime;
size_t flags = 0;
size_t value_len;
@@ -1406,32 +1404,62 @@ static int parse_file_extra_htime(struct archive_read* a,
}
unix_time = flags & IS_UNIX;
has_unix_ns = unix_time && (flags & HAS_UNIX_NS);
has_mtime = flags & HAS_MTIME;
has_atime = flags & HAS_ATIME;
has_ctime = flags & HAS_CTIME;
rar->file.e_atime_ns = rar->file.e_ctime_ns = rar->file.e_mtime_ns = 0;
if(flags & HAS_MTIME) {
if(has_mtime) {
parse_htime_item(a, unix_time, &rar->file.e_mtime,
extra_data_size);
archive_entry_set_mtime(e, rar->file.e_mtime, 0);
&rar->file.e_mtime_ns, extra_data_size);
}
if(flags & HAS_CTIME) {
if(has_ctime) {
parse_htime_item(a, unix_time, &rar->file.e_ctime,
extra_data_size);
archive_entry_set_ctime(e, rar->file.e_ctime, 0);
&rar->file.e_ctime_ns, extra_data_size);
}
if(flags & HAS_ATIME) {
if(has_atime) {
parse_htime_item(a, unix_time, &rar->file.e_atime,
extra_data_size);
archive_entry_set_atime(e, rar->file.e_atime, 0);
&rar->file.e_atime_ns, extra_data_size);
}
if(flags & HAS_UNIX_NS) {
if(!read_u32(a, &rar->file.e_unix_ns))
if(has_mtime && has_unix_ns) {
if(!read_u32(a, &rar->file.e_mtime_ns))
return ARCHIVE_EOF;
*extra_data_size -= 4;
}
if(has_ctime && has_unix_ns) {
if(!read_u32(a, &rar->file.e_ctime_ns))
return ARCHIVE_EOF;
*extra_data_size -= 4;
}
if(has_atime && has_unix_ns) {
if(!read_u32(a, &rar->file.e_atime_ns))
return ARCHIVE_EOF;
*extra_data_size -= 4;
}
/* The seconds and nanoseconds are either together, or separated in two
* fields so we parse them, then set the archive_entry's times. */
if(has_mtime) {
archive_entry_set_mtime(e, rar->file.e_mtime, rar->file.e_mtime_ns);
}
if(has_ctime) {
archive_entry_set_ctime(e, rar->file.e_ctime, rar->file.e_ctime_ns);
}
if(has_atime) {
archive_entry_set_atime(e, rar->file.e_atime, rar->file.e_atime_ns);
}
return ARCHIVE_OK;
}
@@ -1896,7 +1924,8 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
} else {
/* Unknown host OS */
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Unsupported Host OS: 0x%x", (int) host_os);
"Unsupported Host OS: 0x%jx",
(uintmax_t)host_os);
return ARCHIVE_FATAL;
}
@@ -2104,8 +2133,8 @@ static int process_head_main(struct archive_read* a, struct rar5* rar,
default:
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Unsupported extra type (0x%x)",
(int) extra_field_id);
"Unsupported extra type (0x%jx)",
(uintmax_t)extra_field_id);
return ARCHIVE_FATAL;
}
@@ -3093,7 +3122,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
* can be stored in the output buffer directly.
*
* - Code 256 defines a new filter, which is later used to
* ransform the data block accordingly to the filter type.
* transform the data block accordingly to the filter type.
* The data block needs to be fully uncompressed first.
*
* - Code bigger than 257 and smaller than 262 define
@@ -3983,7 +4012,7 @@ static int do_unpack(struct archive_read* a, struct rar5* rar,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Compression method not supported: 0x%x",
rar->cstate.method);
(unsigned int)rar->cstate.method);
return ARCHIVE_FATAL;
}
@@ -129,7 +129,11 @@ struct tar {
int64_t entry_offset;
int64_t entry_padding;
int64_t entry_bytes_unconsumed;
int64_t realsize;
int64_t disk_size;
int64_t GNU_sparse_realsize;
int64_t GNU_sparse_size;
int64_t SCHILY_sparse_realsize;
int64_t pax_size;
struct sparse_block *sparse_list;
struct sparse_block *sparse_last;
int64_t sparse_offset;
@@ -138,6 +142,7 @@ struct tar {
int sparse_gnu_minor;
char sparse_gnu_attributes_seen;
char filetype;
char size_fields; /* Bits defined below */
struct archive_string localname;
struct archive_string_conv *opt_sconv;
@@ -148,9 +153,15 @@ struct tar {
int compat_2x;
int process_mac_extensions;
int read_concatenated_archives;
int realsize_override;
};
/* Track which size fields were present in the headers */
#define TAR_SIZE_PAX_SIZE 1
#define TAR_SIZE_GNU_SPARSE_REALSIZE 2
#define TAR_SIZE_GNU_SPARSE_SIZE 4
#define TAR_SIZE_SCHILY_SPARSE_REALSIZE 8
static int archive_block_is_null(const char *p);
static char *base64_decode(const char *, size_t, size_t *);
static int gnu_add_sparse_entry(struct archive_read *, struct tar *,
@@ -158,36 +169,36 @@ static int gnu_add_sparse_entry(struct archive_read *, struct tar *,
static void gnu_clear_sparse_list(struct tar *);
static int gnu_sparse_old_read(struct archive_read *, struct tar *,
const struct archive_entry_header_gnutar *header, size_t *);
const struct archive_entry_header_gnutar *header, int64_t *);
static int gnu_sparse_old_parse(struct archive_read *, struct tar *,
const struct gnu_sparse *sparse, int length);
static int gnu_sparse_01_parse(struct archive_read *, struct tar *,
const char *, size_t);
static ssize_t gnu_sparse_10_read(struct archive_read *, struct tar *,
size_t *);
static int64_t gnu_sparse_10_read(struct archive_read *, struct tar *,
int64_t *);
static int header_Solaris_ACL(struct archive_read *, struct tar *,
struct archive_entry *, const void *, size_t *);
struct archive_entry *, const void *, int64_t *);
static int header_common(struct archive_read *, struct tar *,
struct archive_entry *, const void *);
static int header_old_tar(struct archive_read *, struct tar *,
struct archive_entry *, const void *);
static int header_pax_extension(struct archive_read *, struct tar *,
struct archive_entry *, const void *, size_t *);
struct archive_entry *, const void *, int64_t *);
static int header_pax_global(struct archive_read *, struct tar *,
struct archive_entry *, const void *h, size_t *);
struct archive_entry *, const void *h, int64_t *);
static int header_gnu_longlink(struct archive_read *, struct tar *,
struct archive_entry *, const void *h, size_t *);
struct archive_entry *, const void *h, int64_t *);
static int header_gnu_longname(struct archive_read *, struct tar *,
struct archive_entry *, const void *h, size_t *);
struct archive_entry *, const void *h, int64_t *);
static int is_mac_metadata_entry(struct archive_entry *entry);
static int read_mac_metadata_blob(struct archive_read *,
struct archive_entry *, size_t *);
struct archive_entry *, int64_t *);
static int header_volume(struct archive_read *, struct tar *,
struct archive_entry *, const void *h, size_t *);
struct archive_entry *, const void *h, int64_t *);
static int header_ustar(struct archive_read *, struct tar *,
struct archive_entry *, const void *h);
static int header_gnutar(struct archive_read *, struct tar *,
struct archive_entry *, const void *h, size_t *);
struct archive_entry *, const void *h, int64_t *);
static int archive_read_format_tar_bid(struct archive_read *, int);
static int archive_read_format_tar_options(struct archive_read *,
const char *, const char *);
@@ -200,7 +211,7 @@ static int archive_read_format_tar_read_header(struct archive_read *,
static int checksum(struct archive_read *, const void *);
static int pax_attribute(struct archive_read *, struct tar *,
struct archive_entry *, const char *key, size_t key_length,
size_t value_length, size_t *unconsumed);
size_t value_length, int64_t *unconsumed);
static int pax_attribute_LIBARCHIVE_xattr(struct archive_entry *,
const char *, size_t, const char *, size_t);
static int pax_attribute_SCHILY_acl(struct archive_read *, struct tar *,
@@ -209,20 +220,20 @@ static int pax_attribute_SUN_holesdata(struct archive_read *, struct tar *,
struct archive_entry *, const char *, size_t);
static void pax_time(const char *, size_t, int64_t *sec, long *nanos);
static ssize_t readline(struct archive_read *, struct tar *, const char **,
ssize_t limit, size_t *);
ssize_t limit, int64_t *);
static int read_body_to_string(struct archive_read *, struct tar *,
struct archive_string *, const void *h, size_t *);
struct archive_string *, const void *h, int64_t *);
static int read_bytes_to_string(struct archive_read *,
struct archive_string *, size_t, size_t *);
struct archive_string *, size_t, int64_t *);
static int64_t tar_atol(const char *, size_t);
static int64_t tar_atol10(const char *, size_t);
static int64_t tar_atol256(const char *, size_t);
static int64_t tar_atol8(const char *, size_t);
static int tar_read_header(struct archive_read *, struct tar *,
struct archive_entry *, size_t *);
struct archive_entry *, int64_t *);
static int tohex(int c);
static char *url_decode(const char *, size_t);
static void tar_flush_unconsumed(struct archive_read *, size_t *);
static void tar_flush_unconsumed(struct archive_read *, int64_t *);
/* Sanity limits: These numbers should be low enough to
* prevent a maliciously-crafted archive from forcing us to
@@ -467,7 +478,7 @@ archive_read_format_tar_options(struct archive_read *a,
* anything outstanding since we're going to do read_aheads
*/
static void
tar_flush_unconsumed(struct archive_read *a, size_t *unconsumed)
tar_flush_unconsumed(struct archive_read *a, int64_t *unconsumed)
{
if (*unconsumed) {
/*
@@ -515,7 +526,8 @@ archive_read_format_tar_read_header(struct archive_read *a,
const char *p;
const wchar_t *wp;
int r;
size_t l, unconsumed = 0;
size_t l;
int64_t unconsumed = 0;
/* Assign default device/inode values. */
archive_entry_set_dev(entry, 1 + default_dev); /* Don't use zero. */
@@ -529,8 +541,7 @@ archive_read_format_tar_read_header(struct archive_read *a,
tar = (struct tar *)(a->format->data);
tar->entry_offset = 0;
gnu_clear_sparse_list(tar);
tar->realsize = -1; /* Mark this as "unset" */
tar->realsize_override = 0;
tar->size_fields = 0; /* We don't have any size info yet */
/* Setup default string conversion. */
tar->sconv = tar->opt_sconv;
@@ -617,12 +628,15 @@ archive_read_format_tar_read_data(struct archive_read *a,
/* If we're at end of file, return EOF. */
if (tar->sparse_list == NULL ||
tar->entry_bytes_remaining == 0) {
if (__archive_read_consume(a, tar->entry_padding) < 0)
int64_t request = tar->entry_bytes_remaining +
tar->entry_padding;
if (__archive_read_consume(a, request) != request)
return (ARCHIVE_FATAL);
tar->entry_padding = 0;
*buff = NULL;
*size = 0;
*offset = tar->realsize;
*offset = tar->disk_size;
return (ARCHIVE_EOF);
}
@@ -655,29 +669,15 @@ archive_read_format_tar_read_data(struct archive_read *a,
static int
archive_read_format_tar_skip(struct archive_read *a)
{
int64_t bytes_skipped;
int64_t request;
struct sparse_block *p;
struct tar* tar;
tar = (struct tar *)(a->format->data);
/* Do not consume the hole of a sparse file. */
request = 0;
for (p = tar->sparse_list; p != NULL; p = p->next) {
if (!p->hole) {
if (p->remaining >= INT64_MAX - request) {
return ARCHIVE_FATAL;
}
request += p->remaining;
}
}
if (request > tar->entry_bytes_remaining)
request = tar->entry_bytes_remaining;
request += tar->entry_padding + tar->entry_bytes_unconsumed;
request = tar->entry_bytes_remaining + tar->entry_padding +
tar->entry_bytes_unconsumed;
bytes_skipped = __archive_read_consume(a, request);
if (bytes_skipped < 0)
if (__archive_read_consume(a, request) != request)
return (ARCHIVE_FATAL);
tar->entry_bytes_remaining = 0;
@@ -690,13 +690,29 @@ archive_read_format_tar_skip(struct archive_read *a)
return (ARCHIVE_OK);
}
/*
* This function resets the accumulated state while reading
* a header.
*/
static void
tar_reset_header_state(struct tar *tar)
{
tar->pax_hdrcharset_utf8 = 1;
tar->sparse_gnu_attributes_seen = 0;
archive_string_empty(&(tar->entry_gname));
archive_string_empty(&(tar->entry_pathname));
archive_string_empty(&(tar->entry_pathname_override));
archive_string_empty(&(tar->entry_uname));
archive_string_empty(&tar->entry_linkpath);
}
/*
* This function reads and interprets all of the headers associated
* with a single entry.
*/
static int
tar_read_header(struct archive_read *a, struct tar *tar,
struct archive_entry *entry, size_t *unconsumed)
struct archive_entry *entry, int64_t *unconsumed)
{
ssize_t bytes;
int err = ARCHIVE_OK, err2;
@@ -715,13 +731,7 @@ tar_read_header(struct archive_read *a, struct tar *tar,
static const int32_t seen_x_header = 32; /* Also X */
static const int32_t seen_mac_metadata = 512;
tar->pax_hdrcharset_utf8 = 1;
tar->sparse_gnu_attributes_seen = 0;
archive_string_empty(&(tar->entry_gname));
archive_string_empty(&(tar->entry_pathname));
archive_string_empty(&(tar->entry_pathname_override));
archive_string_empty(&(tar->entry_uname));
archive_string_empty(&tar->entry_linkpath);
tar_reset_header_state(tar);
/* Ensure format is set. */
if (a->archive.archive_format_name == NULL) {
@@ -750,7 +760,7 @@ tar_read_header(struct archive_read *a, struct tar *tar,
* if there's no regular header, then this is
* a premature EOF. */
archive_set_error(&a->archive, EINVAL,
"Damaged tar archive");
"Damaged tar archive (end-of-archive within a sequence of headers)");
return (ARCHIVE_FATAL);
} else {
return (ARCHIVE_EOF);
@@ -760,7 +770,7 @@ tar_read_header(struct archive_read *a, struct tar *tar,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated tar archive"
" detected while reading next heaader");
" detected while reading next header");
return (ARCHIVE_FATAL);
}
*unconsumed += 512;
@@ -787,7 +797,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
/* This is NOT a null block, so it must be a valid header. */
if (!checksum(a, h)) {
tar_flush_unconsumed(a, unconsumed);
archive_set_error(&a->archive, EINVAL, "Damaged tar archive");
archive_set_error(&a->archive, EINVAL,
"Damaged tar archive (bad header checksum)");
/* If we've read some critical information (pax headers, etc)
* and _then_ see a bad header, we can't really recover. */
if (eof_fatal) {
@@ -804,6 +815,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
switch(header->typeflag[0]) {
case 'A': /* Solaris tar ACL */
if (seen_headers & seen_A_header) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Redundant 'A' header");
return (ARCHIVE_FATAL);
}
seen_headers |= seen_A_header;
@@ -813,6 +826,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
break;
case 'g': /* POSIX-standard 'g' header. */
if (seen_headers & seen_g_header) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Redundant 'g' header");
return (ARCHIVE_FATAL);
}
seen_headers |= seen_g_header;
@@ -822,27 +837,41 @@ tar_read_header(struct archive_read *a, struct tar *tar,
break;
case 'K': /* Long link name (GNU tar, others) */
if (seen_headers & seen_K_header) {
return (ARCHIVE_FATAL);
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Damaged archive: Redundant 'K' headers may cause linknames to be incorrect");
err = err_combine(err, ARCHIVE_WARN);
}
seen_headers |= seen_K_header;
a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
a->archive.archive_format_name = "GNU tar format";
err2 = header_gnu_longlink(a, tar, entry, h, unconsumed);
break;
case 'L': /* Long filename (GNU tar, others) */
if (seen_headers & seen_L_header) {
return (ARCHIVE_FATAL);
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Damaged archive: Redundant 'L' headers may cause filenames to be incorrect");
err = err_combine(err, ARCHIVE_WARN);
}
seen_headers |= seen_L_header;
a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
a->archive.archive_format_name = "GNU tar format";
err2 = header_gnu_longname(a, tar, entry, h, unconsumed);
break;
case 'V': /* GNU volume header */
if (seen_headers & seen_V_header) {
return (ARCHIVE_FATAL);
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Redundant 'V' header");
err = err_combine(err, ARCHIVE_WARN);
}
seen_headers |= seen_V_header;
a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
a->archive.archive_format_name = "GNU tar format";
err2 = header_volume(a, tar, entry, h, unconsumed);
break;
case 'X': /* Used by SUN tar; same as 'x'. */
if (seen_headers & seen_x_header) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Redundant 'X'/'x' header");
return (ARCHIVE_FATAL);
}
seen_headers |= seen_x_header;
@@ -853,6 +882,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
break;
case 'x': /* POSIX-standard 'x' header. */
if (seen_headers & seen_x_header) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Redundant 'x' header");
return (ARCHIVE_FATAL);
}
seen_headers |= seen_x_header;
@@ -904,6 +935,7 @@ tar_read_header(struct archive_read *a, struct tar *tar,
err = err_combine(err, err2);
/* Note: Other headers can appear again. */
seen_headers = seen_mac_metadata;
tar_reset_header_state(tar);
break;
}
@@ -1032,13 +1064,13 @@ archive_block_is_null(const char *p)
*/
static int
header_Solaris_ACL(struct archive_read *a, struct tar *tar,
struct archive_entry *entry, const void *h, size_t *unconsumed)
struct archive_entry *entry, const void *h, int64_t *unconsumed)
{
const struct archive_entry_header_ustar *header;
struct archive_string acl_text;
size_t size;
int err, acl_type;
int64_t type;
uint64_t type;
char *acl, *p;
header = (const struct archive_entry_header_ustar *)h;
@@ -1075,7 +1107,7 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
}
p++;
}
switch ((int)type & ~0777777) {
switch (type & ~0777777) {
case 01000000:
/* POSIX.1e ACL */
acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
@@ -1086,8 +1118,8 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
break;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Malformed Solaris ACL attribute (unsupported type %o)",
(int)type);
"Malformed Solaris ACL attribute (unsupported type %llu)",
(unsigned long long)type);
archive_string_free(&acl_text);
return (ARCHIVE_WARN);
}
@@ -1138,14 +1170,16 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
*/
static int
header_gnu_longlink(struct archive_read *a, struct tar *tar,
struct archive_entry *entry, const void *h, size_t *unconsumed)
struct archive_entry *entry, const void *h, int64_t *unconsumed)
{
int err;
struct archive_string linkpath;
archive_string_init(&linkpath);
err = read_body_to_string(a, tar, &linkpath, h, unconsumed);
archive_entry_set_link(entry, linkpath.s);
if (err == ARCHIVE_OK) {
archive_entry_set_link(entry, linkpath.s);
}
archive_string_free(&linkpath);
return (err);
}
@@ -1170,7 +1204,7 @@ set_conversion_failed_error(struct archive_read *a,
*/
static int
header_gnu_longname(struct archive_read *a, struct tar *tar,
struct archive_entry *entry, const void *h, size_t *unconsumed)
struct archive_entry *entry, const void *h, int64_t *unconsumed)
{
int err;
struct archive_string longname;
@@ -1191,7 +1225,7 @@ header_gnu_longname(struct archive_read *a, struct tar *tar,
*/
static int
header_volume(struct archive_read *a, struct tar *tar,
struct archive_entry *entry, const void *h, size_t *unconsumed)
struct archive_entry *entry, const void *h, int64_t *unconsumed)
{
const struct archive_entry_header_ustar *header;
int64_t size, to_consume;
@@ -1217,7 +1251,7 @@ header_volume(struct archive_read *a, struct tar *tar,
static int
read_bytes_to_string(struct archive_read *a,
struct archive_string *as, size_t size,
size_t *unconsumed) {
int64_t *unconsumed) {
const void *src;
/* Fail if we can't make our buffer big enough. */
@@ -1250,7 +1284,7 @@ read_bytes_to_string(struct archive_read *a,
*/
static int
read_body_to_string(struct archive_read *a, struct tar *tar,
struct archive_string *as, const void *h, size_t *unconsumed)
struct archive_string *as, const void *h, int64_t *unconsumed)
{
int64_t size;
const struct archive_entry_header_ustar *header;
@@ -1259,18 +1293,21 @@ read_body_to_string(struct archive_read *a, struct tar *tar,
(void)tar; /* UNUSED */
header = (const struct archive_entry_header_ustar *)h;
size = tar_atol(header->size, sizeof(header->size));
if (size > entry_limit) {
if (size < 0 || size > entry_limit) {
archive_set_error(&a->archive, EINVAL,
"Special header has invalid size: %lld",
(long long)size);
return (ARCHIVE_FATAL);
}
if ((size > (int64_t)pathname_limit) || (size < 0)) {
if (size > (int64_t)pathname_limit) {
archive_string_empty(as);
int64_t to_consume = ((size + 511) & ~511);
if (to_consume != __archive_read_consume(a, to_consume)) {
return (ARCHIVE_FATAL);
}
archive_set_error(&a->archive, EINVAL,
"Special header too large: %d > 1MiB",
(int)size);
"Special header too large: %lld > 1MiB",
(long long)size);
return (ARCHIVE_WARN);
}
r = read_bytes_to_string(a, as, size, unconsumed);
@@ -1287,6 +1324,11 @@ read_body_to_string(struct archive_read *a, struct tar *tar,
* allows header_old_tar and header_ustar
* to handle filenames differently, while still putting most of the
* common parsing into one place.
*
* This is called _after_ ustar, GNU tar, Schily, etc, special
* fields have already been parsed into the `tar` structure.
* So we can make final decisions here about how to reconcile
* size, mode, etc, information.
*/
static int
header_common(struct archive_read *a, struct tar *tar,
@@ -1308,34 +1350,73 @@ header_common(struct archive_read *a, struct tar *tar,
archive_entry_set_perm(entry,
(mode_t)tar_atol(header->mode, sizeof(header->mode)));
}
/* Set uid, gid, mtime if not already set */
if (!archive_entry_uid_is_set(entry)) {
archive_entry_set_uid(entry, tar_atol(header->uid, sizeof(header->uid)));
}
if (!archive_entry_gid_is_set(entry)) {
archive_entry_set_gid(entry, tar_atol(header->gid, sizeof(header->gid)));
}
if (!archive_entry_mtime_is_set(entry)) {
archive_entry_set_mtime(entry, tar_atol(header->mtime, sizeof(header->mtime)), 0);
}
tar->entry_bytes_remaining = tar_atol(header->size, sizeof(header->size));
/* Reconcile the size info. */
/* First, how big is the file on disk? */
if ((tar->size_fields & TAR_SIZE_GNU_SPARSE_REALSIZE) != 0) {
/* GNU sparse format 1.0 uses `GNU.sparse.realsize`
* to hold the size of the file on disk. */
tar->disk_size = tar->GNU_sparse_realsize;
} else if ((tar->size_fields & TAR_SIZE_GNU_SPARSE_SIZE) != 0
&& (tar->sparse_gnu_major == 0)) {
/* GNU sparse format 0.0 and 0.1 use `GNU.sparse.size`
* to hold the size of the file on disk. */
tar->disk_size = tar->GNU_sparse_size;
} else if ((tar->size_fields & TAR_SIZE_SCHILY_SPARSE_REALSIZE) != 0) {
tar->disk_size = tar->SCHILY_sparse_realsize;
} else if ((tar->size_fields & TAR_SIZE_PAX_SIZE) != 0) {
tar->disk_size = tar->pax_size;
} else {
/* There wasn't a suitable pax header, so use the ustar info */
tar->disk_size = tar_atol(header->size, sizeof(header->size));
}
if (tar->disk_size < 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Tar entry has negative file size");
return (ARCHIVE_FATAL);
} else if (tar->disk_size > entry_limit) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Tar entry size overflow");
return (ARCHIVE_FATAL);
} else {
archive_entry_set_size(entry, tar->disk_size);
}
/* Second, how big is the data in the archive? */
if ((tar->size_fields & TAR_SIZE_GNU_SPARSE_SIZE) != 0
&& (tar->sparse_gnu_major == 1)) {
/* GNU sparse format 1.0 uses `GNU.sparse.size`
* to hold the size of the data in the archive. */
tar->entry_bytes_remaining = tar->GNU_sparse_size;
} else if ((tar->size_fields & TAR_SIZE_PAX_SIZE) != 0) {
tar->entry_bytes_remaining = tar->pax_size;
} else {
tar->entry_bytes_remaining
= tar_atol(header->size, sizeof(header->size));
}
if (tar->entry_bytes_remaining < 0) {
tar->entry_bytes_remaining = 0;
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Tar entry has negative size");
"Tar entry has negative size");
return (ARCHIVE_FATAL);
}
if (tar->entry_bytes_remaining > entry_limit) {
} else if (tar->entry_bytes_remaining > entry_limit) {
tar->entry_bytes_remaining = 0;
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Tar entry size overflow");
"Tar entry size overflow");
return (ARCHIVE_FATAL);
}
if (!tar->realsize_override) {
tar->realsize = tar->entry_bytes_remaining;
}
archive_entry_set_size(entry, tar->realsize);
if (!archive_entry_mtime_is_set(entry)) {
archive_entry_set_mtime(entry, tar_atol(header->mtime, sizeof(header->mtime)), 0);
}
/* Handle the tar type flag appropriately. */
tar->filetype = header->typeflag[0];
@@ -1597,7 +1678,7 @@ is_mac_metadata_entry(struct archive_entry *entry) {
*/
static int
read_mac_metadata_blob(struct archive_read *a,
struct archive_entry *entry, size_t *unconsumed)
struct archive_entry *entry, int64_t *unconsumed)
{
int64_t size;
size_t msize;
@@ -1654,7 +1735,7 @@ read_mac_metadata_blob(struct archive_read *a,
*/
static int
header_pax_global(struct archive_read *a, struct tar *tar,
struct archive_entry *entry, const void *h, size_t *unconsumed)
struct archive_entry *entry, const void *h, int64_t *unconsumed)
{
const struct archive_entry_header_ustar *header;
int64_t size, to_consume;
@@ -1665,7 +1746,10 @@ header_pax_global(struct archive_read *a, struct tar *tar,
header = (const struct archive_entry_header_ustar *)h;
size = tar_atol(header->size, sizeof(header->size));
if (size > entry_limit) {
if (size < 0 || size > entry_limit) {
archive_set_error(&a->archive, EINVAL,
"Special header has invalid size: %lld",
(long long)size);
return (ARCHIVE_FATAL);
}
to_consume = ((size + 511) & ~511);
@@ -1761,7 +1845,7 @@ header_ustar(struct archive_read *a, struct tar *tar,
static int
header_pax_extension(struct archive_read *a, struct tar *tar,
struct archive_entry *entry, const void *h, size_t *unconsumed)
struct archive_entry *entry, const void *h, int64_t *unconsumed)
{
/* Sanity checks: The largest `x` body I've ever heard of was
* a little over 4MB. So I doubt there has ever been a
@@ -1812,8 +1896,8 @@ header_pax_extension(struct archive_read *a, struct tar *tar,
return (ARCHIVE_FATAL);
}
archive_set_error(&a->archive, EINVAL,
"Ignoring oversized pax extensions: %d > %d",
(int)ext_size, (int)ext_size_limit);
"Ignoring oversized pax extensions: %lld > %lld",
(long long)ext_size, (long long)ext_size_limit);
return (ARCHIVE_WARN);
}
tar_flush_unconsumed(a, unconsumed);
@@ -1912,6 +1996,13 @@ header_pax_extension(struct archive_read *a, struct tar *tar,
*unconsumed += p - attr_start;
tar_flush_unconsumed(a, unconsumed);
if (value_length == 0) {
archive_set_error(&a->archive, EINVAL,
"Malformed pax attributes");
*unconsumed += ext_size + ext_padding;
return (ARCHIVE_WARN);
}
/* pax_attribute will consume value_length - 1 */
r = pax_attribute(a, tar, entry, attr_name.s, archive_strlen(&attr_name), value_length - 1, unconsumed);
ext_size -= value_length - 1;
@@ -2121,8 +2212,9 @@ pax_attribute_SCHILY_acl(struct archive_read *a, struct tar *tar,
if (value_length > acl_limit) {
__archive_read_consume(a, value_length);
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Unreasonably large ACL: %d > %d",
(int)value_length, (int)acl_limit);
"Unreasonably large ACL: %llu > %llu",
(unsigned long long)value_length,
(unsigned long long)acl_limit);
return (ARCHIVE_WARN);
}
@@ -2154,7 +2246,7 @@ pax_attribute_SCHILY_acl(struct archive_read *a, struct tar *tar,
}
static int
pax_attribute_read_time(struct archive_read *a, size_t value_length, int64_t *ps, long *pn, size_t *unconsumed) {
pax_attribute_read_time(struct archive_read *a, size_t value_length, int64_t *ps, long *pn, int64_t *unconsumed) {
struct archive_string as;
int r;
@@ -2169,12 +2261,16 @@ pax_attribute_read_time(struct archive_read *a, size_t value_length, int64_t *ps
r = read_bytes_to_string(a, &as, value_length, unconsumed);
if (r < ARCHIVE_OK) {
archive_string_free(&as);
*ps = 0;
*pn = 0;
return (r);
}
pax_time(as.s, archive_strlen(&as), ps, pn);
archive_string_free(&as);
if (*ps < 0 || *ps == INT64_MAX) {
if (*ps == INT64_MIN) {
*ps = 0;
*pn = 0;
return (ARCHIVE_WARN);
}
return (ARCHIVE_OK);
@@ -2183,7 +2279,7 @@ pax_attribute_read_time(struct archive_read *a, size_t value_length, int64_t *ps
static int
pax_attribute_read_number(struct archive_read *a, size_t value_length, int64_t *result) {
struct archive_string as;
size_t unconsumed = 0;
int64_t unconsumed = 0;
int r;
if (value_length > 64) {
@@ -2197,6 +2293,7 @@ pax_attribute_read_number(struct archive_read *a, size_t value_length, int64_t *
tar_flush_unconsumed(a, &unconsumed);
if (r < ARCHIVE_OK) {
archive_string_free(&as);
*result = 0;
return (r);
}
@@ -2223,7 +2320,7 @@ pax_attribute_read_number(struct archive_read *a, size_t value_length, int64_t *
*/
static int
pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *entry,
const char *key, size_t key_length, size_t value_length, size_t *unconsumed)
const char *key, size_t key_length, size_t value_length, int64_t *unconsumed)
{
int64_t t;
long n;
@@ -2289,10 +2386,13 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
}
else if (key_length == 4 && memcmp(key, "size", 4) == 0) {
/* GNU.sparse.size */
/* This is either the size of stored entry OR the size of data on disk,
* depending on which GNU sparse format version is in use.
* Since pax attributes can be in any order, we may not actually
* know at this point how to interpret this. */
if ((err = pax_attribute_read_number(a, value_length, &t)) == ARCHIVE_OK) {
tar->realsize = t;
archive_entry_set_size(entry, tar->realsize);
tar->realsize_override = 1;
tar->GNU_sparse_size = t;
tar->size_fields |= TAR_SIZE_GNU_SPARSE_SIZE;
}
return (err);
}
@@ -2304,8 +2404,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
tar->sparse_gnu_minor = 1;
if (value_length > sparse_map_limit) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Unreasonably large sparse map: %d > %d",
(int)value_length, (int)sparse_map_limit);
"Unreasonably large sparse map: %llu > %llu",
(unsigned long long)value_length,
(unsigned long long)sparse_map_limit);
err = ARCHIVE_FAILED;
} else {
p = __archive_read_ahead(a, value_length, &bytes_read);
@@ -2360,11 +2461,10 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
return (err);
}
else if (key_length == 8 && memcmp(key, "realsize", 8) == 0) {
/* GNU.sparse.realsize */
/* GNU.sparse.realsize = size of file on disk */
if ((err = pax_attribute_read_number(a, value_length, &t)) == ARCHIVE_OK) {
tar->realsize = t;
archive_entry_set_size(entry, tar->realsize);
tar->realsize_override = 1;
tar->GNU_sparse_realsize = t;
tar->size_fields |= TAR_SIZE_GNU_SPARSE_REALSIZE;
}
return (err);
}
@@ -2413,8 +2513,8 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
} else {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"symlink type is very long"
"(longest recognized value is 4 bytes, this is %d)",
(int)value_length);
"(longest recognized value is 4 bytes, this is %llu)",
(unsigned long long)value_length);
err = ARCHIVE_WARN;
}
__archive_read_consume(a, value_length);
@@ -2450,8 +2550,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
if (value_length > xattr_limit) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Ignoring unreasonably large security.selinux attribute:"
" %d > %d",
(int)value_length, (int)xattr_limit);
" %llu > %llu",
(unsigned long long)value_length,
(unsigned long long)xattr_limit);
/* TODO: Should this be FAILED instead? */
err = ARCHIVE_WARN;
} else {
@@ -2545,12 +2646,12 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
}
else if (key_length == 8 && memcmp(key, "realsize", 8) == 0) {
if ((err = pax_attribute_read_number(a, value_length, &t)) == ARCHIVE_OK) {
tar->realsize = t;
tar->realsize_override = 1;
archive_entry_set_size(entry, tar->realsize);
tar->SCHILY_sparse_realsize = t;
tar->size_fields |= TAR_SIZE_SCHILY_SPARSE_REALSIZE;
}
return (err);
}
/* TODO: Is there a SCHILY.sparse.size similar to GNU.sparse.size ? */
else if (key_length > 6 && memcmp(key, "xattr.", 6) == 0) {
key_length -= 6;
key += 6;
@@ -2568,8 +2669,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
}
} else {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Unreasonably large xattr: %d > %d",
(int)value_length, (int)xattr_limit);
"Unreasonably large xattr: %llu > %llu",
(unsigned long long)value_length,
(unsigned long long)xattr_limit);
err = ARCHIVE_WARN;
}
__archive_read_consume(a, value_length);
@@ -2599,8 +2701,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
}
} else {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Unreasonably large sparse map: %d > %d",
(int)value_length, (int)sparse_map_limit);
"Unreasonably large sparse map: %llu > %llu",
(unsigned long long)value_length,
(unsigned long long)sparse_map_limit);
err = ARCHIVE_FAILED;
}
__archive_read_consume(a, value_length);
@@ -2669,8 +2772,8 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
}
} else {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"hdrcharset attribute is unreasonably large (%d bytes)",
(int)value_length);
"hdrcharset attribute is unreasonably large (%llu bytes)",
(unsigned long long)value_length);
err = ARCHIVE_WARN;
}
__archive_read_consume(a, value_length);
@@ -2717,19 +2820,8 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
if (key_length == 4 && memcmp(key, "size", 4) == 0) {
/* "size" is the size of the data in the entry. */
if ((err = pax_attribute_read_number(a, value_length, &t)) == ARCHIVE_OK) {
tar->entry_bytes_remaining = t;
/*
* The "size" pax header keyword always overrides the
* "size" field in the tar header.
* GNU.sparse.realsize, GNU.sparse.size and
* SCHILY.realsize override this value.
*/
if (!tar->realsize_override) {
archive_entry_set_size(entry,
tar->entry_bytes_remaining);
tar->realsize
= tar->entry_bytes_remaining;
}
tar->pax_size = t;
tar->size_fields |= TAR_SIZE_PAX_SIZE;
}
else if (t == INT64_MAX) {
/* Note: pax_attr_read_number returns INT64_MAX on overflow or < 0 */
@@ -2768,7 +2860,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
/*
* parse a decimal time value, which may include a fractional portion
* Parse a decimal time value, which may include a fractional portion
*
* Sets ps to INT64_MIN on error.
*/
static void
pax_time(const char *p, size_t length, int64_t *ps, long *pn)
@@ -2784,6 +2878,7 @@ pax_time(const char *p, size_t length, int64_t *ps, long *pn)
if (length <= 0) {
*ps = 0;
*pn = 0;
return;
}
s = 0;
@@ -2797,8 +2892,9 @@ pax_time(const char *p, size_t length, int64_t *ps, long *pn)
digit = *p - '0';
if (s > limit ||
(s == limit && digit > last_digit_limit)) {
s = INT64_MAX;
break;
*ps = INT64_MIN;
*pn = 0;
return;
}
s = (s * 10) + digit;
++p;
@@ -2829,7 +2925,7 @@ pax_time(const char *p, size_t length, int64_t *ps, long *pn)
*/
static int
header_gnutar(struct archive_read *a, struct tar *tar,
struct archive_entry *entry, const void *h, size_t *unconsumed)
struct archive_entry *entry, const void *h, int64_t *unconsumed)
{
const struct archive_entry_header_gnutar *header;
int64_t t;
@@ -2841,11 +2937,6 @@ header_gnutar(struct archive_read *a, struct tar *tar,
* filename is stored as in old-style archives.
*/
/* Grab fields common to all tar variants. */
err = header_common(a, tar, entry, h);
if (err == ARCHIVE_FATAL)
return (err);
/* Copy filename over (to ensure null termination). */
header = (const struct archive_entry_header_gnutar *)h;
const char *existing_pathname = archive_entry_pathname(entry);
@@ -2894,8 +2985,6 @@ header_gnutar(struct archive_read *a, struct tar *tar,
archive_entry_set_rdev(entry, 0);
}
tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining);
/* Grab GNU-specific fields. */
if (!archive_entry_atime_is_set(entry)) {
t = tar_atol(header->atime, sizeof(header->atime));
@@ -2909,10 +2998,10 @@ header_gnutar(struct archive_read *a, struct tar *tar,
}
if (header->realsize[0] != 0) {
tar->realsize
/* Treat as a synonym for the pax GNU.sparse.realsize attr */
tar->GNU_sparse_realsize
= tar_atol(header->realsize, sizeof(header->realsize));
archive_entry_set_size(entry, tar->realsize);
tar->realsize_override = 1;
tar->size_fields |= TAR_SIZE_GNU_SPARSE_REALSIZE;
}
if (header->sparse[0].offset[0] != 0) {
@@ -2925,6 +3014,13 @@ header_gnutar(struct archive_read *a, struct tar *tar,
}
}
/* Grab fields common to all tar variants. */
err = header_common(a, tar, entry, h);
if (err == ARCHIVE_FATAL)
return (err);
tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining);
return (err);
}
@@ -2980,7 +3076,7 @@ gnu_clear_sparse_list(struct tar *tar)
static int
gnu_sparse_old_read(struct archive_read *a, struct tar *tar,
const struct archive_entry_header_gnutar *header, size_t *unconsumed)
const struct archive_entry_header_gnutar *header, int64_t *unconsumed)
{
ssize_t bytes_read;
const void *data;
@@ -3104,8 +3200,7 @@ gnu_sparse_01_parse(struct archive_read *a, struct tar *tar, const char *p, size
* it's not possible to support both variants. This code supports
* the later variant at the expense of not supporting the former.
*
* This variant also replaced GNU.sparse.size with GNU.sparse.realsize
* and introduced the GNU.sparse.major/GNU.sparse.minor attributes.
* This variant also introduced the GNU.sparse.major/GNU.sparse.minor attributes.
*/
/*
@@ -3115,7 +3210,7 @@ gnu_sparse_01_parse(struct archive_read *a, struct tar *tar, const char *p, size
*/
static int64_t
gnu_sparse_10_atol(struct archive_read *a, struct tar *tar,
int64_t *remaining, size_t *unconsumed)
int64_t *remaining, int64_t *unconsumed)
{
int64_t l, limit, last_digit_limit;
const char *p;
@@ -3160,12 +3255,10 @@ gnu_sparse_10_atol(struct archive_read *a, struct tar *tar,
* Returns length (in bytes) of the sparse data description
* that was read.
*/
static ssize_t
gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
static int64_t
gnu_sparse_10_read(struct archive_read *a, struct tar *tar, int64_t *unconsumed)
{
ssize_t bytes_read;
int entries;
int64_t offset, size, to_skip, remaining;
int64_t bytes_read, entries, offset, size, to_skip, remaining;
/* Clear out the existing sparse list. */
gnu_clear_sparse_list(tar);
@@ -3173,7 +3266,7 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
remaining = tar->entry_bytes_remaining;
/* Parse entries. */
entries = (int)gnu_sparse_10_atol(a, tar, &remaining, unconsumed);
entries = gnu_sparse_10_atol(a, tar, &remaining, unconsumed);
if (entries < 0)
return (ARCHIVE_FATAL);
/* Parse the individual entries. */
@@ -3191,14 +3284,14 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
}
/* Skip rest of block... */
tar_flush_unconsumed(a, unconsumed);
bytes_read = (ssize_t)(tar->entry_bytes_remaining - remaining);
bytes_read = tar->entry_bytes_remaining - remaining;
to_skip = 0x1ff & -bytes_read;
/* Fail if tar->entry_bytes_remaing would get negative */
if (to_skip > remaining)
return (ARCHIVE_FATAL);
if (to_skip != __archive_read_consume(a, to_skip))
return (ARCHIVE_FATAL);
return ((ssize_t)(bytes_read + to_skip));
return (bytes_read + to_skip);
}
/*
@@ -3408,7 +3501,7 @@ tar_atol256(const char *_p, size_t char_cnt)
*/
static ssize_t
readline(struct archive_read *a, struct tar *tar, const char **start,
ssize_t limit, size_t *unconsumed)
ssize_t limit, int64_t *unconsumed)
{
ssize_t bytes_read;
ssize_t total_size = 0;
@@ -386,7 +386,8 @@ start_over:
case LAST_WT:
default:
/* consume the content and start over */
_warc_skip(a);
if (_warc_skip(a) < 0)
return (ARCHIVE_FATAL);
goto start_over;
}
return (ARCHIVE_OK);
@@ -439,7 +440,9 @@ _warc_skip(struct archive_read *a)
{
struct warc_s *w = a->format->data;
__archive_read_consume(a, w->cntlen + 4U/*\r\n\r\n separator*/);
if (__archive_read_consume(a, w->cntlen) < 0 ||
__archive_read_consume(a, 4U/*\r\n\r\n separator*/) < 0)
return (ARCHIVE_FATAL);
w->cntlen = 0U;
w->cntoff = 0U;
return (ARCHIVE_OK);
@@ -36,6 +36,10 @@
#include <bsdxml.h>
#elif HAVE_EXPAT_H
#include <expat.h>
#elif HAVE_XMLLITE_H
#include <objidl.h>
#include <initguid.h>
#include <xmllite.h>
#endif
#ifdef HAVE_BZLIB_H
#include <bzlib.h>
@@ -56,12 +60,13 @@
#include "archive_read_private.h"
#if (!defined(HAVE_LIBXML_XMLREADER_H) && \
!defined(HAVE_BSDXML_H) && !defined(HAVE_EXPAT_H)) ||\
!defined(HAVE_BSDXML_H) && !defined(HAVE_EXPAT_H) && \
!defined(HAVE_XMLLITE_H)) ||\
!defined(HAVE_ZLIB_H) || \
!defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1)
/*
* xar needs several external libraries.
* o libxml2 or expat --- XML parser
* o libxml2, expat or (Windows only) xmllite --- XML parser
* o openssl or MD5/SHA1 hash function
* o zlib
* o bzlib2 (option)
@@ -438,6 +443,8 @@ static void expat_start_cb(void *, const XML_Char *, const XML_Char **);
static void expat_end_cb(void *, const XML_Char *);
static void expat_data_cb(void *, const XML_Char *, int);
static int expat_read_toc(struct archive_read *);
#elif defined(HAVE_XMLLITE_H)
static int xmllite_read_toc(struct archive_read *);
#endif
int
@@ -589,6 +596,8 @@ read_toc(struct archive_read *a)
r = xml2_read_toc(a);
#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H)
r = expat_read_toc(a);
#elif defined(HAVE_XMLLITE_H)
r = xmllite_read_toc(a);
#endif
if (r != ARCHIVE_OK)
return (r);
@@ -1110,17 +1119,17 @@ atohex(unsigned char *b, size_t bsize, const char *p, size_t psize)
while (bsize && psize > 1) {
unsigned char x;
if (p[0] >= 'a' && p[0] <= 'z')
if (p[0] >= 'a' && p[0] <= 'f')
x = (p[0] - 'a' + 0x0a) << 4;
else if (p[0] >= 'A' && p[0] <= 'Z')
else if (p[0] >= 'A' && p[0] <= 'F')
x = (p[0] - 'A' + 0x0a) << 4;
else if (p[0] >= '0' && p[0] <= '9')
x = (p[0] - '0') << 4;
else
return (-1);
if (p[1] >= 'a' && p[1] <= 'z')
if (p[1] >= 'a' && p[1] <= 'f')
x |= p[1] - 'a' + 0x0a;
else if (p[1] >= 'A' && p[1] <= 'Z')
else if (p[1] >= 'A' && p[1] <= 'F')
x |= p[1] - 'A' + 0x0a;
else if (p[1] >= '0' && p[1] <= '9')
x |= p[1] - '0';
@@ -1745,15 +1754,6 @@ decompression_cleanup(struct archive_read *a)
#if defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA)
if (xar->lzstream_valid)
lzma_end(&(xar->lzstream));
#elif defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA)
if (xar->lzstream_valid) {
if (lzmadec_end(&(xar->lzstream)) != LZMADEC_OK) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Failed to clean up lzmadec decompressor");
r = ARCHIVE_FATAL;
}
}
#endif
return (r);
}
@@ -2070,7 +2070,7 @@ xml_start(struct archive_read *a, const char *name, struct xmlattr_list *list)
if (xar->file->link > 0)
if (add_link(a, xar, xar->file) != ARCHIVE_OK) {
return (ARCHIVE_FATAL);
};
}
}
}
}
@@ -2851,7 +2851,6 @@ xml_data(void *userData, const char *s, size_t len)
xar->file->has |= HAS_XATTR;
archive_strncpy(&(xar->xattr->fstype), s, len);
break;
break;
case FILE_ACL_DEFAULT:
case FILE_ACL_ACCESS:
case FILE_ACL_APPLEEXTENDED:
@@ -3343,6 +3342,326 @@ expat_read_toc(struct archive_read *a)
XML_ParserFree(parser);
return (ud.state);
}
#endif /* defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) */
#elif defined(HAVE_XMLLITE_H)
struct ArchiveStreamAdapter {
const ISequentialStreamVtbl *lpVtbl; /* see asaStaticVtable */
struct archive_read *a;
};
static HRESULT STDMETHODCALLTYPE
asaQueryInterface(ISequentialStream *this, REFIID riid, void **ppv)
{
if (!IsEqualIID(riid, &IID_ISequentialStream)) {
*ppv = NULL;
return E_NOINTERFACE;
}
*ppv = this;
return S_OK;
}
/*
* We can dispense with reference counting as we tightly manage the lifetime
* of an ArchiveStreamAdapter.
*/
static ULONG STDMETHODCALLTYPE
asaAddRef(ISequentialStream *this)
{
(void)this; /* UNUSED */
return ULONG_MAX;
}
static ULONG STDMETHODCALLTYPE
asaRelease(ISequentialStream *this)
{
(void)this; /* UNUSED */
return ULONG_MAX;
}
static HRESULT STDMETHODCALLTYPE
asaRead(ISequentialStream *this, void *pv, ULONG cb, ULONG *pcbRead)
{
struct ArchiveStreamAdapter *asa = (struct ArchiveStreamAdapter *)this;
struct archive_read *a;
struct xar *xar;
const void *d = pv;
size_t outbytes = cb;
size_t used = 0;
int r;
a = asa->a;
xar = (struct xar *)(a->format->data);
*pcbRead = 0;
if (xar->toc_remaining <= 0)
return cb != 0 ? S_FALSE : S_OK;
r = rd_contents(a, &d, &outbytes, &used, xar->toc_remaining);
if (r != ARCHIVE_OK)
return E_FAIL;
__archive_read_consume(a, used);
xar->toc_remaining -= used;
xar->offset += used;
xar->toc_total += outbytes;
PRINT_TOC(pv, outbytes);
*pcbRead = (ULONG)outbytes;
return outbytes < cb ? S_FALSE : S_OK;
}
static HRESULT STDMETHODCALLTYPE
asaWrite(ISequentialStream *this, const void *pv, ULONG cb, ULONG *pcbWritten)
{
(void)this; /* UNUSED */
(void)pv; /* UNUSED */
(void)cb; /* UNUSED */
if (!pcbWritten) return E_INVALIDARG;
*pcbWritten = 0;
return E_NOTIMPL;
}
static const ISequentialStreamVtbl asaStaticVtable = {
.QueryInterface = asaQueryInterface,
.AddRef = asaAddRef,
.Release = asaRelease,
.Read = asaRead,
.Write = asaWrite,
};
static int
xmllite_create_stream_adapter(struct archive_read *a,
struct ArchiveStreamAdapter **pasa)
{
struct ArchiveStreamAdapter *asa =
calloc(1, sizeof(struct ArchiveStreamAdapter));
if (!asa) {
archive_set_error(&(a->archive), ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
asa->lpVtbl = &asaStaticVtable;
asa->a = a;
*pasa = asa;
return (ARCHIVE_OK);
}
typedef HRESULT(STDMETHODCALLTYPE *xmllite_wstr_func)(IXmlReader *, LPCWSTR *,
UINT *);
/*
* Returns an narrow-char archive_string in *as after calling
* the wide-char COM API callee() on the XmlReader reader.
* Sets an appropriate error on the archive if it fails.
*/
static int
xmllite_call_return_as(struct archive_read *a, struct archive_string *as,
IXmlReader *reader, xmllite_wstr_func callee)
{
LPCWSTR wcs;
UINT wlen;
if (FAILED(callee(reader, &wcs, &wlen))) {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"Failed to read XML data");
return (ARCHIVE_FATAL);
}
archive_string_init(as);
if (archive_string_append_from_wcs(as, wcs, (size_t)wlen) < 0) {
archive_string_free(as);
archive_set_error(&(a->archive), ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
return (ARCHIVE_OK);
}
static char *
xmllite_call_return_mbs(struct archive_read *a, IXmlReader *reader,
xmllite_wstr_func callee)
{
char *ret;
struct archive_string as;
if (xmllite_call_return_as(a, &as, reader, callee) < 0) {
return NULL;
}
ret = strdup(as.s);
archive_string_free(&as);
if (ret == NULL) {
archive_set_error(&(a->archive), ENOMEM, "Out of memory");
return NULL;
}
return ret;
}
static int
xmllite_xmlattr_setup(struct archive_read *a,
struct xmlattr_list *list, IXmlReader *reader)
{
struct xmlattr *attr;
HRESULT hr;
list->first = NULL;
list->last = &(list->first);
hr = reader->lpVtbl->MoveToFirstAttribute(reader);
/* Contrary to other checks, we're not using SUCCEEDED/FAILED
* because MoveToNextAttribute returns *S_FALSE* (success!)
* when it runs out of attributes.
*/
while (hr == S_OK) {
/* Attributes implied as being default by the DTD are ignored */
if (reader->lpVtbl->IsDefault(reader))
continue;
attr = malloc(sizeof*(attr));
if (attr == NULL) {
archive_set_error(&(a->archive), ENOMEM,
"Out of memory");
return (ARCHIVE_FATAL);
}
attr->name = xmllite_call_return_mbs(a, reader,
reader->lpVtbl->GetLocalName);
if (attr->name == NULL) {
free(attr);
/* xmllite_call_return_mbs sets an appropriate error */
return (ARCHIVE_FATAL);
}
attr->value = xmllite_call_return_mbs(a, reader,
reader->lpVtbl->GetValue);
if (attr->value == NULL) {
free(attr->name);
free(attr);
/* xmllite_call_return_mbs sets an appropriate error */
return (ARCHIVE_FATAL);
}
attr->next = NULL;
*list->last = attr;
list->last = &(attr->next);
hr = reader->lpVtbl->MoveToNextAttribute(reader);
}
if (FAILED(hr)) {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_FILE_FORMAT,
"Failed to parse XML document");
return (ARCHIVE_FAILED);
}
return (ARCHIVE_OK);
}
static int
xmllite_read_toc(struct archive_read *a)
{
struct ArchiveStreamAdapter *asa = NULL;
char *name;
struct archive_string as;
BOOL empty;
XmlNodeType type;
struct xmlattr_list list;
IXmlReader *reader = NULL;
int r = ARCHIVE_OK;
if ((r = xmllite_create_stream_adapter(a, &asa)) < 0) {
goto out;
}
if (FAILED(CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL))) {
r = ARCHIVE_FATAL;
goto out;
}
if (FAILED(reader->lpVtbl->SetInput(reader, (IUnknown *)asa))) {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"Failed to prepare XML stream");
r = ARCHIVE_FATAL;
goto out;
}
while (!reader->lpVtbl->IsEOF(reader)) {
if (FAILED(reader->lpVtbl->Read(reader, &type))) {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"Failed to read XML stream");
r = ARCHIVE_FATAL;
goto out;
}
switch (type) {
case XmlNodeType_Element:
empty = reader->lpVtbl->IsEmptyElement(reader);
name = xmllite_call_return_mbs(a, reader,
reader->lpVtbl->GetLocalName);
if (name == NULL) {
/* xmllite_call_return_mbs sets an appropriate error */
r = ARCHIVE_FATAL;
goto out;
}
r = xmllite_xmlattr_setup(a, &list, reader);
if (r == ARCHIVE_OK) {
r = xml_start(a, name, &list);
}
xmlattr_cleanup(&list);
if (r == ARCHIVE_OK && empty) {
xml_end(a, name);
}
free(name);
if (r != ARCHIVE_OK) {
goto out;
}
break;
case XmlNodeType_EndElement:
name = xmllite_call_return_mbs(a, reader,
reader->lpVtbl->GetLocalName);
if (name == NULL) {
/* xmllite_call_return_mbs sets an appropriate error */
r = ARCHIVE_FATAL;
goto out;
}
xml_end(a, name);
free(name);
break;
case XmlNodeType_Text:
r = xmllite_call_return_as(a, &as, reader,
reader->lpVtbl->GetValue);
if (r != ARCHIVE_OK) {
/* xmllite_call_return_as sets an appropriate error */
goto out;
}
xml_data(a, as.s, (int)archive_strlen(&as));
archive_string_free(&as);
case XmlNodeType_None:
case XmlNodeType_Attribute:
case XmlNodeType_CDATA:
case XmlNodeType_ProcessingInstruction:
case XmlNodeType_Comment:
case XmlNodeType_DocumentType:
case XmlNodeType_Whitespace:
case XmlNodeType_XmlDeclaration:
default:
break;
}
}
out:
if (reader)
reader->lpVtbl->Release(reader);
free(asa);
return r;
}
#endif /* defined(XMLLITE) */
#endif /* Support xar format */
@@ -71,6 +71,7 @@
#include "archive_private.h"
#include "archive_rb.h"
#include "archive_read_private.h"
#include "archive_time_private.h"
#include "archive_ppmd8_private.h"
#ifndef HAVE_ZLIB_H
@@ -465,27 +466,6 @@ compression_name(const int compression)
return "??";
}
/* Convert an MSDOS-style date/time into Unix-style time. */
static time_t
zip_time(const char *p)
{
int msTime, msDate;
struct tm ts;
msTime = (0xff & (unsigned)p[0]) + 256 * (0xff & (unsigned)p[1]);
msDate = (0xff & (unsigned)p[2]) + 256 * (0xff & (unsigned)p[3]);
memset(&ts, 0, sizeof(ts));
ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */
ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */
ts.tm_mday = msDate & 0x1f; /* Day of month. */
ts.tm_hour = (msTime >> 11) & 0x1f;
ts.tm_min = (msTime >> 5) & 0x3f;
ts.tm_sec = (msTime << 1) & 0x3e;
ts.tm_isdst = -1;
return mktime(&ts);
}
/*
* The extra data is stored as a list of
* id1+size1+data1 + id2+size2+data2 ...
@@ -978,7 +958,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
}
zip->init_decryption = (zip_entry->zip_flags & ZIP_ENCRYPTED);
zip_entry->compression = (char)archive_le16dec(p + 8);
zip_entry->mtime = zip_time(p + 10);
zip_entry->mtime = dos_to_unix(archive_le32dec(p + 10));
zip_entry->crc32 = archive_le32dec(p + 14);
if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
zip_entry->decdat = p[11];
@@ -2134,15 +2114,15 @@ zipx_ppmd8_init(struct archive_read *a, struct zip *zip)
if(order < 2 || restore_method > 2) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Invalid parameter set in PPMd8 stream (order=%" PRId32 ", "
"restore=%" PRId32 ")", order, restore_method);
"Invalid parameter set in PPMd8 stream (order=%" PRIu32 ", "
"restore=%" PRIu32 ")", order, restore_method);
return (ARCHIVE_FAILED);
}
/* Allocate the memory needed to properly decompress the file. */
if(!__archive_ppmd8_functions.Ppmd8_Alloc(&zip->ppmd8, mem << 20)) {
archive_set_error(&a->archive, ENOMEM,
"Unable to allocate memory for PPMd8 stream: %" PRId32 " bytes",
"Unable to allocate memory for PPMd8 stream: %" PRIu32 " bytes",
mem << 20);
return (ARCHIVE_FATAL);
}
@@ -3168,7 +3148,6 @@ archive_read_format_zip_read_data(struct archive_read *a,
/* We can't decompress this entry, but we will
* be able to skip() it and try the next entry. */
return (ARCHIVE_FAILED);
break;
}
if (r != ARCHIVE_OK)
return (r);
@@ -3987,7 +3966,7 @@ slurp_central_directory(struct archive_read *a, struct archive_entry* entry,
zip->has_encrypted_entries = 1;
}
zip_entry->compression = (char)archive_le16dec(p + 10);
zip_entry->mtime = zip_time(p + 12);
zip_entry->mtime = dos_to_unix(archive_le32dec(p + 12));
zip_entry->crc32 = archive_le32dec(p + 16);
if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
zip_entry->decdat = p[13];
+91 -50
View File
@@ -154,7 +154,6 @@ static int archive_wstring_append_from_mbs_in_codepage(
struct archive_string_conv *);
static int archive_string_append_from_wcs_in_codepage(struct archive_string *,
const wchar_t *, size_t, struct archive_string_conv *);
static int is_big_endian(void);
static int strncat_in_codepage(struct archive_string *, const void *,
size_t, struct archive_string_conv *);
static int win_strncat_from_utf16be(struct archive_string *, const void *,
@@ -199,6 +198,29 @@ static int archive_string_normalize_D(struct archive_string *, const void *,
static int archive_string_append_unicode(struct archive_string *,
const void *, size_t, struct archive_string_conv *);
#if defined __LITTLE_ENDIAN__
#define IS_BIG_ENDIAN 0
#elif defined __BIG_ENDIAN__
#define IS_BIG_ENDIAN 1
#elif defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
#define IS_BIG_ENDIAN 0
#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
#define IS_BIG_ENDIAN 1
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || defined(_M_ARM64))
#define IS_BIG_ENDIAN 0
#else
// Detect endianness at runtime.
static int
is_big_endian(void)
{
uint16_t d = 1;
return (archive_be16dec(&d) == 1);
}
#define IS_BIG_ENDIAN is_big_endian()
#endif
static struct archive_string *
archive_string_append(struct archive_string *as, const char *p, size_t s)
{
@@ -450,7 +472,8 @@ static int
archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
const char *s, size_t length, struct archive_string_conv *sc)
{
int count, ret = 0;
int ret = 0;
size_t count;
UINT from_cp;
if (sc != NULL)
@@ -472,7 +495,7 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
ws = dest->s + dest->length;
mp = (const unsigned char *)s;
count = 0;
while (count < (int)length && *mp) {
while (count < length && *mp) {
*ws++ = (wchar_t)*mp++;
count++;
}
@@ -485,7 +508,7 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
struct archive_string u16;
int saved_flag = sc->flag;/* save current flag. */
if (is_big_endian())
if (IS_BIG_ENDIAN)
sc->flag |= SCONV_TO_UTF16BE;
else
sc->flag |= SCONV_TO_UTF16LE;
@@ -495,16 +518,16 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
* UTF-16BE/LE NFD ===> UTF-16 NFC
* UTF-16BE/LE NFC ===> UTF-16 NFD
*/
count = (int)utf16nbytes(s, length);
count = utf16nbytes(s, length);
} else {
/*
* UTF-8 NFD ===> UTF-16 NFC
* UTF-8 NFC ===> UTF-16 NFD
*/
count = (int)mbsnbytes(s, length);
count = mbsnbytes(s, length);
}
u16.s = (char *)dest->s;
u16.length = dest->length << 1;;
u16.length = dest->length << 1;
u16.buffer_length = dest->buffer_length;
if (sc->flag & SCONV_NORMALIZATION_C)
ret = archive_string_normalize_C(&u16, s, count, sc);
@@ -516,23 +539,23 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
sc->flag = saved_flag;/* restore the saved flag. */
return (ret);
} else if (sc != NULL && (sc->flag & SCONV_FROM_UTF16)) {
count = (int)utf16nbytes(s, length);
count = utf16nbytes(s, length);
count >>= 1; /* to be WCS length */
/* Allocate memory for WCS. */
if (NULL == archive_wstring_ensure(dest,
dest->length + count + 1))
return (-1);
wmemcpy(dest->s + dest->length, (const wchar_t *)s, count);
if ((sc->flag & SCONV_FROM_UTF16BE) && !is_big_endian()) {
if ((sc->flag & SCONV_FROM_UTF16BE) && !IS_BIG_ENDIAN) {
uint16_t *u16 = (uint16_t *)(dest->s + dest->length);
int b;
size_t b;
for (b = 0; b < count; b++) {
uint16_t val = archive_le16dec(u16+b);
archive_be16enc(u16+b, val);
}
} else if ((sc->flag & SCONV_FROM_UTF16LE) && is_big_endian()) {
} else if ((sc->flag & SCONV_FROM_UTF16LE) && IS_BIG_ENDIAN) {
uint16_t *u16 = (uint16_t *)(dest->s + dest->length);
int b;
size_t b;
for (b = 0; b < count; b++) {
uint16_t val = archive_be16dec(u16+b);
archive_le16enc(u16+b, val);
@@ -556,21 +579,28 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
buffsize = dest->length + length + 1;
do {
int r;
/* MultiByteToWideChar is limited to int. */
if (length > (size_t)INT_MAX ||
(dest->buffer_length >> 1) > (size_t)INT_MAX)
return (-1);
/* Allocate memory for WCS. */
if (NULL == archive_wstring_ensure(dest, buffsize))
return (-1);
/* Convert MBS to WCS. */
count = MultiByteToWideChar(from_cp,
r = MultiByteToWideChar(from_cp,
mbflag, s, (int)length, dest->s + dest->length,
(int)(dest->buffer_length >> 1) -1);
if (count == 0 &&
if (r == 0 &&
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
/* Expand the WCS buffer. */
buffsize = dest->buffer_length << 1;
continue;
}
if (count == 0 && length != 0)
if (r == 0 && length != 0)
ret = -1;
count = (size_t)r;
break;
} while (1);
}
@@ -679,9 +709,9 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
const wchar_t *ws, size_t len, struct archive_string_conv *sc)
{
BOOL defchar_used, *dp;
int count, ret = 0;
int ret = 0;
UINT to_cp;
int wslen = (int)len;
size_t count, wslen = len;
if (sc != NULL)
to_cp = sc->to_cp;
@@ -720,13 +750,13 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
count = 0;
defchar_used = 0;
if (sc->flag & SCONV_TO_UTF16BE) {
while (count < (int)len && *ws) {
while (count < len && *ws) {
archive_be16enc(u16+count, *ws);
ws++;
count++;
}
} else {
while (count < (int)len && *ws) {
while (count < len && *ws) {
archive_le16enc(u16+count, *ws);
ws++;
count++;
@@ -739,15 +769,21 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
archive_string_ensure(as, as->length + len * 2 + 1))
return (-1);
do {
int r;
defchar_used = 0;
if (to_cp == CP_UTF8 || sc == NULL)
dp = NULL;
else
dp = &defchar_used;
count = WideCharToMultiByte(to_cp, 0, ws, wslen,
/* WideCharToMultiByte is limited to int. */
if (as->buffer_length - as->length - 1 > (size_t)INT_MAX ||
wslen > (size_t)INT_MAX)
return (-1);
r = WideCharToMultiByte(to_cp, 0, ws, (int)wslen,
as->s + as->length,
(int)as->buffer_length - (int)as->length - 1, NULL, dp);
if (count == 0 &&
(int)(as->buffer_length - as->length - 1), NULL, dp);
if (r == 0 &&
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
/* Expand the MBS buffer and retry. */
if (NULL == archive_string_ensure(as,
@@ -755,8 +791,9 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
return (-1);
continue;
}
if (count == 0)
if (r == 0)
ret = -1;
count = (size_t)r;
break;
} while (1);
}
@@ -2032,7 +2069,7 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
char *outp;
size_t avail, bs;
int return_value = 0; /* success */
int to_size, from_size;
size_t to_size, from_size;
if (sc->flag & SCONV_TO_UTF16)
to_size = 2;
@@ -2051,7 +2088,7 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
remaining = length;
outp = as->s + as->length;
avail = as->buffer_length - as->length - to_size;
while (remaining >= (size_t)from_size) {
while (remaining >= from_size) {
size_t result = iconv(cd, &itp, &remaining, &outp, &avail);
if (result != (size_t)-1)
@@ -2174,6 +2211,8 @@ invalid_mbs(const void *_p, size_t n, struct archive_string_conv *sc)
if (codepage != CP_UTF8)
mbflag |= MB_PRECOMPOSED;
if (n > (size_t)INT_MAX)
return (-1); /* Invalid */
if (MultiByteToWideChar(codepage, mbflag, p, (int)n, NULL, 0) == 0)
return (-1); /* Invalid */
return (0); /* Okay */
@@ -2327,7 +2366,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
cnt = utf8_count[ch];
/* Invalid sequence or there are not plenty bytes. */
if ((int)n < cnt) {
if (n < (size_t)cnt) {
cnt = (int)n;
for (i = 1; i < cnt; i++) {
if ((s[i] & 0xc0) != 0x80) {
@@ -2396,7 +2435,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
cnt = 6;
else
cnt = 1;
if ((int)n < cnt)
if (n < (size_t)cnt)
cnt = (int)n;
for (i = 1; i < cnt; i++) {
if ((s[i] & 0xc0) != 0x80) {
@@ -2612,7 +2651,7 @@ unicode_to_utf16be(char *p, size_t remaining, uint32_t uc)
} else {
if (remaining < 2)
return (0);
archive_be16enc(utf16, uc);
archive_be16enc(utf16, (uint16_t)uc);
return (2);
}
}
@@ -2634,7 +2673,7 @@ unicode_to_utf16le(char *p, size_t remaining, uint32_t uc)
} else {
if (remaining < 2)
return (0);
archive_le16enc(utf16, uc);
archive_le16enc(utf16, (uint16_t)uc);
return (2);
}
}
@@ -3499,10 +3538,9 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
{
struct archive_string tmp;
const char *u16;
int ll;
BOOL defchar;
char *mbs;
size_t mbs_size, b;
size_t mbs_size, b, ll;
int ret = 0;
bytes &= ~1;
@@ -3538,7 +3576,7 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
archive_string_init(&tmp);
if (be) {
if (is_big_endian()) {
if (IS_BIG_ENDIAN) {
u16 = _p;
} else {
if (archive_string_ensure(&tmp, bytes+2) == NULL)
@@ -3551,7 +3589,7 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
u16 = tmp.s;
}
} else {
if (!is_big_endian()) {
if (!IS_BIG_ENDIAN) {
u16 = _p;
} else {
if (archive_string_ensure(&tmp, bytes+2) == NULL)
@@ -3566,18 +3604,24 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
}
do {
int r;
defchar = 0;
ll = WideCharToMultiByte(sc->to_cp, 0,
/* WideCharToMultiByte is limited to int. */
if (bytes > (size_t)INT_MAX || mbs_size > (size_t)INT_MAX)
return (-1);
r = WideCharToMultiByte(sc->to_cp, 0,
(LPCWSTR)u16, (int)bytes>>1, mbs, (int)mbs_size,
NULL, &defchar);
/* Exit loop if we succeeded */
if (ll != 0 ||
if (r != 0 ||
GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
ll = (size_t)r;
break;
}
/* Else expand buffer and loop to try again. */
ll = WideCharToMultiByte(sc->to_cp, 0,
r = WideCharToMultiByte(sc->to_cp, 0,
(LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL);
ll = (size_t)r;
if (archive_string_ensure(as, ll +1) == NULL)
return (-1);
mbs = as->s + as->length;
@@ -3605,14 +3649,6 @@ win_strncat_from_utf16le(struct archive_string *as, const void *_p,
return (win_strncat_from_utf16(as, _p, bytes, sc, 0));
}
static int
is_big_endian(void)
{
uint16_t d = 1;
return (archive_be16dec(&d) == 1);
}
/*
* Convert a current locale string to UTF-16BE/LE and copy the result.
* Return -1 if conversion fails.
@@ -3651,16 +3687,21 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p,
return (0);
}
do {
count = MultiByteToWideChar(sc->from_cp,
int r;
if (length > (size_t)INT_MAX || (avail >> 1) > (size_t)INT_MAX)
return (-1);
r = MultiByteToWideChar(sc->from_cp,
MB_PRECOMPOSED, s, (int)length, (LPWSTR)u16, (int)avail>>1);
/* Exit loop if we succeeded */
if (count != 0 ||
if (r != 0 ||
GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
count = (size_t)r;
break;
}
/* Expand buffer and try again */
count = MultiByteToWideChar(sc->from_cp,
r = MultiByteToWideChar(sc->from_cp,
MB_PRECOMPOSED, s, (int)length, NULL, 0);
count = (size_t)r;
if (archive_string_ensure(as16, (count +1) * 2)
== NULL)
return (-1);
@@ -3673,7 +3714,7 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p,
if (count == 0)
return (-1);
if (is_big_endian()) {
if (IS_BIG_ENDIAN) {
if (!bigendian) {
while (count > 0) {
uint16_t v = archive_be16dec(u16);
@@ -3811,9 +3852,9 @@ best_effort_strncat_to_utf16(struct archive_string *as16, const void *_p,
ret = -1;
}
if (bigendian)
archive_be16enc(utf16, c);
archive_be16enc(utf16, (uint16_t)c);
else
archive_le16enc(utf16, c);
archive_le16enc(utf16, (uint16_t)c);
utf16 += 2;
}
as16->length = utf16 - as16->s;
@@ -2286,5 +2286,4 @@ static const struct unicode_decomposition_table u_decomposition_table[] = {
{ 0x110AB , 0x110A5 , 0x110BA },
};
#endif /* ARCHIVE_STRING_COMPOSITION_H_INCLUDED */
#endif /* !ARCHIVE_STRING_COMPOSITION_H_INCLUDED */
@@ -116,8 +116,14 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
long_flag = '\0';
switch(*p) {
case 'j':
case 'l':
if (p[1] == 'l') {
long_flag = 'L';
p += 2;
break;
}
__LA_FALLTHROUGH;
case 'j':
case 'z':
long_flag = *p;
p++;
@@ -136,6 +142,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
switch(long_flag) {
case 'j': s = va_arg(ap, intmax_t); break;
case 'l': s = va_arg(ap, long); break;
case 'L': s = va_arg(ap, long long); break;
case 'z': s = va_arg(ap, ssize_t); break;
default: s = va_arg(ap, int); break;
}
@@ -144,6 +151,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
case 's':
switch(long_flag) {
case 'l':
case 'L':
pw = va_arg(ap, wchar_t *);
if (pw == NULL)
pw = L"(null)";
@@ -172,6 +180,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
switch(long_flag) {
case 'j': u = va_arg(ap, uintmax_t); break;
case 'l': u = va_arg(ap, unsigned long); break;
case 'L': u = va_arg(ap, unsigned long long); break;
case 'z': u = va_arg(ap, size_t); break;
default: u = va_arg(ap, unsigned int); break;
}
@@ -0,0 +1,163 @@
/*-
* Copyright © 2025 ARJANEN Loïc Jean David
* 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(S) ``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(S) 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.
*/
#include "archive_platform.h"
#include "archive_private.h"
#include "archive_time_private.h"
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#define NTFS_EPOC_TIME ARCHIVE_LITERAL_ULL(11644473600)
#define NTFS_TICKS ARCHIVE_LITERAL_ULL(10000000)
#define NTFS_EPOC_TICKS (NTFS_EPOC_TIME * NTFS_TICKS)
#define DOS_MIN_TIME 0x00210000U
#define DOS_MAX_TIME 0xff9fbf7dU
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <winnt.h>
/* Windows FILETIME to NTFS time. */
uint64_t
FILETIME_to_ntfs(const FILETIME* filetime)
{
ULARGE_INTEGER utc;
utc.HighPart = filetime->dwHighDateTime;
utc.LowPart = filetime->dwLowDateTime;
return utc.QuadPart;
}
#endif
/* Convert an MSDOS-style date/time into Unix-style time. */
int64_t
dos_to_unix(uint32_t dos_time)
{
uint16_t msTime, msDate;
struct tm ts;
time_t t;
msTime = (0xFFFF & dos_time);
msDate = (dos_time >> 16);
memset(&ts, 0, sizeof(ts));
ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */
ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */
ts.tm_mday = msDate & 0x1f; /* Day of month. */
ts.tm_hour = (msTime >> 11) & 0x1f;
ts.tm_min = (msTime >> 5) & 0x3f;
ts.tm_sec = (msTime << 1) & 0x3e;
ts.tm_isdst = -1;
t = mktime(&ts);
return (int64_t)(t == (time_t)-1 ? INT32_MAX : t);
}
/* Convert into MSDOS-style date/time. */
uint32_t
unix_to_dos(int64_t unix_time)
{
struct tm *t;
uint32_t dt;
time_t ut = unix_time;
#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
struct tm tmbuf;
#endif
if (sizeof(time_t) < sizeof(int64_t) && (int64_t)ut != unix_time) {
ut = (time_t)(unix_time > 0 ? INT32_MAX : INT32_MIN);
}
#if defined(HAVE_LOCALTIME_S)
t = localtime_s(&tmbuf, &ut) ? NULL : &tmbuf;
#elif defined(HAVE_LOCALTIME_R)
t = localtime_r(&ut, &tmbuf);
#else
t = localtime(&ut);
#endif
dt = 0;
if (t != NULL && t->tm_year >= INT_MIN + 80) {
const int year = t->tm_year - 80;
if (year & ~0x7f) {
dt = year > 0 ? DOS_MAX_TIME : DOS_MIN_TIME;
}
else {
dt += (year & 0x7f) << 9;
dt += ((t->tm_mon + 1) & 0x0f) << 5;
dt += (t->tm_mday & 0x1f);
dt <<= 16;
dt += (t->tm_hour & 0x1f) << 11;
dt += (t->tm_min & 0x3f) << 5;
/* Only counting every 2 seconds. */
dt += (t->tm_sec & 0x3e) >> 1;
}
}
if (dt > DOS_MAX_TIME) {
dt = DOS_MAX_TIME;
}
else if (dt < DOS_MIN_TIME) {
dt = DOS_MIN_TIME;
}
return dt;
}
/* Convert NTFS time to Unix sec/nsec */
void
ntfs_to_unix(uint64_t ntfs, int64_t* secs, uint32_t* nsecs)
{
if (ntfs > INT64_MAX) {
ntfs -= NTFS_EPOC_TICKS;
*secs = ntfs / NTFS_TICKS;
*nsecs = 100 * (ntfs % NTFS_TICKS);
}
else {
lldiv_t tdiv;
int64_t value = (int64_t)ntfs - (int64_t)NTFS_EPOC_TICKS;
tdiv = lldiv(value, NTFS_TICKS);
*secs = tdiv.quot;
*nsecs = (uint32_t)(tdiv.rem * 100);
}
}
/* Convert Unix sec/nsec to NTFS time */
uint64_t
unix_to_ntfs(int64_t secs, uint32_t nsecs)
{
uint64_t ntfs;
if (secs < -(int64_t)NTFS_EPOC_TIME)
return 0;
ntfs = secs + NTFS_EPOC_TIME;
if (ntfs > UINT64_MAX / NTFS_TICKS)
return UINT64_MAX;
ntfs *= NTFS_TICKS;
if (ntfs > UINT64_MAX - nsecs/100)
return UINT64_MAX;
return ntfs + nsecs/100;
}
@@ -1,5 +1,5 @@
/*-
* Copyright (c) 2003-2015 Tim Kientzle
* Copyright © 2025 ARJANEN Loïc Jean David
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -22,16 +22,26 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef ARCHIVE_GETDATE_H_INCLUDED
#define ARCHIVE_GETDATE_H_INCLUDED
#ifndef ARCHIVE_TIME_PRIVATE_H_INCLUDED
#define ARCHIVE_TIME_PRIVATE_H_INCLUDED
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
#include <stdint.h>
#include <time.h>
time_t __archive_get_date(time_t now, const char *);
/* NTFS time to Unix sec/nsec. */
void ntfs_to_unix(uint64_t ntfs, int64_t* secs, uint32_t* nsecs);
/* DOS time to Unix sec. */
int64_t dos_to_unix(uint32_t dos);
/* Unix sec/nsec to NTFS time. */
uint64_t unix_to_ntfs(int64_t secs, uint32_t nsecs);
/* Unix sec to DOS time. */
uint32_t unix_to_dos(int64_t secs);
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <windef.h>
#include <winbase.h>
/* Windows FILETIME to NTFS time. */
uint64_t FILETIME_to_ntfs(const FILETIME* filetime);
#endif
#endif /* ARCHIVE_TIME_PRIVATE_H_INCLUDED */
+16 -60
View File
@@ -77,7 +77,9 @@
#define O_CLOEXEC 0
#endif
static int archive_utility_string_sort_helper(char **, unsigned int);
#if ARCHIVE_VERSION_NUMBER < 4000000
static int __LA_LIBC_CC archive_utility_string_sort_helper(const void *, const void *);
#endif
/* Generic initialization of 'struct archive' objects. */
int
@@ -629,74 +631,28 @@ __archive_ensure_cloexec_flag(int fd)
#endif
}
#if ARCHIVE_VERSION_NUMBER < 4000000
/*
* Utility function to sort a group of strings using quicksort.
* Utility functions to sort a group of strings using quicksort.
*/
static int
archive_utility_string_sort_helper(char **strings, unsigned int n)
__LA_LIBC_CC
archive_utility_string_sort_helper(const void *p1, const void *p2)
{
unsigned int i, lesser_count, greater_count;
char **lesser, **greater, **tmp, *pivot;
int retval1, retval2;
const char * const * const s1 = p1;
const char * const * const s2 = p2;
/* A list of 0 or 1 elements is already sorted */
if (n <= 1)
return (ARCHIVE_OK);
lesser_count = greater_count = 0;
lesser = greater = NULL;
pivot = strings[0];
for (i = 1; i < n; i++)
{
if (strcmp(strings[i], pivot) < 0)
{
lesser_count++;
tmp = realloc(lesser, lesser_count * sizeof(*tmp));
if (!tmp) {
free(greater);
free(lesser);
return (ARCHIVE_FATAL);
}
lesser = tmp;
lesser[lesser_count - 1] = strings[i];
}
else
{
greater_count++;
tmp = realloc(greater, greater_count * sizeof(*tmp));
if (!tmp) {
free(greater);
free(lesser);
return (ARCHIVE_FATAL);
}
greater = tmp;
greater[greater_count - 1] = strings[i];
}
}
/* quicksort(lesser) */
retval1 = archive_utility_string_sort_helper(lesser, lesser_count);
for (i = 0; i < lesser_count; i++)
strings[i] = lesser[i];
free(lesser);
/* pivot */
strings[lesser_count] = pivot;
/* quicksort(greater) */
retval2 = archive_utility_string_sort_helper(greater, greater_count);
for (i = 0; i < greater_count; i++)
strings[lesser_count + 1 + i] = greater[i];
free(greater);
return (retval1 < retval2) ? retval1 : retval2;
return strcmp(*s1, *s2);
}
int
archive_utility_string_sort(char **strings)
{
unsigned int size = 0;
while (strings[size] != NULL)
size_t size = 0;
while (strings[size] != NULL)
size++;
return archive_utility_string_sort_helper(strings, size);
qsort(strings, size, sizeof(char *),
archive_utility_string_sort_helper);
return (ARCHIVE_OK);
}
#endif
@@ -46,11 +46,125 @@
#endif
#ifdef HAVE_ZSTD_H
#include <zstd.h>
#include <stdio.h>
#endif
#ifdef HAVE_LZO_LZOCONF_H
#include <lzo/lzoconf.h>
#endif
#if HAVE_LIBXML_XMLVERSION_H
#include <libxml/xmlversion.h>
#elif HAVE_BSDXML_H
#include <bsdxml.h>
#elif HAVE_EXPAT_H
#include <expat.h>
#endif
#if HAVE_MBEDTLS_VERSION_H
#include <mbedtls/version.h>
#endif
#if HAVE_NETTLE_VERSION_H
#include <nettle/version.h>
#include <stdio.h>
#endif
#if HAVE_OPENSSL_OPENSSLV_H
#include <openssl/opensslv.h>
#include <stdio.h>
#endif
#if HAVE_ICONV_H
#include <iconv.h>
#endif
#if HAVE_PCRE_H
#include <pcre.h>
#endif
#if HAVE_PCRE2_H
#include <pcre2.h>
#endif
#include "archive.h"
#include "archive_private.h"
#include "archive_string.h"
#include "archive_cryptor_private.h"
#include "archive_digest_private.h"
static void
archive_regex_version(struct archive_string* str)
{
#if HAVE_LIBPCREPOSIX && HAVE_PCRE_H
archive_strcat(str, " libpcre/");
archive_strcat(str, archive_libpcre_version());
#elif HAVE_LIBPCRE2POSIX && HAVE_PCRE2_H
archive_strcat(str, " libpcre2/");
archive_strcat(str, archive_libpcre2_version());
#else
(void)str; /* UNUSED */
#endif
}
static void
archive_xml_version(struct archive_string* str)
{
#if HAVE_LIBXML_XMLVERSION_H && HAVE_LIBXML2
archive_strcat(str, " libxml2/");
archive_strcat(str, archive_libxml2_version());
#elif HAVE_BSDXML_H && HAVE_LIBBSDXML
archive_strcat(str, " bsdxml/");
archive_strcat(str, archive_libbsdxml_version());
#elif HAVE_EXPAT_H && HAVE_LIBEXPAT
archive_strcat(str, " expat/");
archive_strcat(str, archive_libexpat_version());
#else
(void)str; /* UNUSED */
#endif
}
static void
archive_libb2_version(struct archive_string* str)
{
archive_strcat(str, " libb2/");
#if HAVE_BLAKE2_H && HAVE_LIBB2
#if defined(LIBB2_PKGCONFIG_VERSION)
archive_strcat(str, LIBB2_PKGCONFIG_VERSION);
#else
archive_strcat(str, "system");
#endif
#else
archive_strcat(str, "bundled");
#endif
}
static void
archive_crypto_version(struct archive_string* str)
{
#if defined(ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto)
archive_strcat(str, " CommonCrypto/");
archive_strcat(str, archive_commoncrypto_version());
#endif
#if defined(ARCHIVE_CRYPTOR_USE_CNG)
archive_strcat(str, " cng/");
archive_strcat(str, archive_cng_version());
#endif
#if defined(ARCHIVE_CRYPTOR_USE_MBED)
archive_strcat(str, " mbedtls/");
archive_strcat(str, archive_mbedtls_version());
#endif
#if defined(ARCHIVE_CRYPTOR_USE_NETTLE)
archive_strcat(str, " nettle/");
archive_strcat(str, archive_nettle_version());
#endif
#if defined(ARCHIVE_CRYPTOR_USE_OPENSSL)
archive_strcat(str, " openssl/");
archive_strcat(str, archive_openssl_version());
#endif
#if defined(ARCHIVE_CRYPTOR_USE_LIBMD)
archive_strcat(str, " libmd/");
archive_strcat(str, archive_libmd_version());
#endif
#if defined(ARCHIVE_CRYPTOR_USE_WINCRYPT)
archive_strcat(str, " WinCrypt/");
archive_strcat(str, archive_wincrypt_version());
#endif
// Just in case
(void)str; /* UNUSED */
}
const char *
archive_version_details(void)
@@ -62,12 +176,17 @@ archive_version_details(void)
const char *bzlib = archive_bzlib_version();
const char *liblz4 = archive_liblz4_version();
const char *libzstd = archive_libzstd_version();
const char *liblzo = archive_liblzo2_version();
const char *libiconv = archive_libiconv_version();
const char *libacl = archive_libacl_version();
const char *librichacl = archive_librichacl_version();
const char *libattr = archive_libacl_version();
if (!init) {
archive_string_init(&str);
archive_strcat(&str, ARCHIVE_VERSION_STRING);
if (zlib != NULL) {
if (zlib) {
archive_strcat(&str, " zlib/");
archive_strcat(&str, zlib);
}
@@ -91,6 +210,30 @@ archive_version_details(void)
archive_strcat(&str, " libzstd/");
archive_strcat(&str, libzstd);
}
if (liblzo) {
archive_strcat(&str, " liblzo2/");
archive_strcat(&str, liblzo);
}
archive_xml_version(&str);
archive_regex_version(&str);
archive_crypto_version(&str);
archive_libb2_version(&str);
if (librichacl) {
archive_strcat(&str, " librichacl/");
archive_strcat(&str, librichacl);
}
if (libacl) {
archive_strcat(&str, " libacl/");
archive_strcat(&str, libacl);
}
if (libattr) {
archive_strcat(&str, " libattr/");
archive_strcat(&str, libattr);
}
if (libiconv) {
archive_strcat(&str, " libiconv/");
archive_strcat(&str, libiconv);
}
}
return str.s;
}
@@ -98,8 +241,8 @@ archive_version_details(void)
const char *
archive_zlib_version(void)
{
#ifdef HAVE_ZLIB_H
return ZLIB_VERSION;
#if HAVE_ZLIB_H && HAVE_LIBZ
return zlibVersion();
#else
return NULL;
#endif
@@ -108,8 +251,8 @@ archive_zlib_version(void)
const char *
archive_liblzma_version(void)
{
#ifdef HAVE_LZMA_H
return LZMA_VERSION_STRING;
#if HAVE_LZMA_H && HAVE_LIBLZMA
return lzma_version_string();
#else
return NULL;
#endif
@@ -118,7 +261,7 @@ archive_liblzma_version(void)
const char *
archive_bzlib_version(void)
{
#ifdef HAVE_BZLIB_H
#if HAVE_BZLIB_H && HAVE_LIBBZ2
return BZ2_bzlibVersion();
#else
return NULL;
@@ -128,12 +271,22 @@ archive_bzlib_version(void)
const char *
archive_liblz4_version(void)
{
#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4)
#if HAVE_LZ4_H && HAVE_LIBLZ4
#if LZ4_VERSION_NUMBER > 10705
return LZ4_versionString();
#elif LZ4_VERSION_NUMBER > 10300
div_t major = div(LZ4_versionNumber(), 10000);
div_t minor = div(major.rem, 100);
static char lz4_version[9];
snprintf(lz4_version, 9, "%d.%d.%d", major.quot, minor.quot, minor.rem);
return lz4_version;
#else
#define str(s) #s
#define NUMBER(x) str(x)
return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
#undef NUMBER
#undef str
#endif
#else
return NULL;
#endif
@@ -143,7 +296,243 @@ const char *
archive_libzstd_version(void)
{
#if HAVE_ZSTD_H && HAVE_LIBZSTD
return ZSTD_VERSION_STRING;
#if ZSTD_VERSION_NUMBER > 10300
return ZSTD_versionString();
#else
div_t major = div(ZSTD_versionNumber(), 10000);
div_t minor = div(major.rem, 100);
static char zstd_version[9];
snprintf(zstd_version, 9, "%d.%d.%d", major.quot, minor.quot, minor.rem);
return zstd_version;
#endif
#else
return NULL;
#endif
}
const char *
archive_liblzo2_version(void)
{
#if HAVE_LZO_LZOCONF_H && HAVE_LIBLZO2
return LZO_VERSION_STRING;
#else
return NULL;
#endif
}
const char *
archive_libbsdxml_version(void)
{
#if HAVE_BSDXML_H && HAVE_LIBBSDXML
return XML_ExpatVersion();
#else
return NULL;
#endif
}
const char *
archive_libxml2_version(void)
{
#if HAVE_LIBXML_XMLREADER_H && HAVE_LIBXML2
return LIBXML_DOTTED_VERSION;
#else
return NULL;
#endif
}
const char *
archive_libexpat_version(void)
{
#if HAVE_EXPAT_H && HAVE_LIBEXPAT
return XML_ExpatVersion();
#else
return NULL;
#endif
}
const char *
archive_mbedtls_version(void)
{
#if defined(ARCHIVE_CRYPTOR_USE_MBED) || defined(ARCHIVE_CRYPTO_MBED)
static char mbed_version[9];
mbedtls_version_get_string(mbed_version);
return mbed_version;
#else
return NULL;
#endif
}
const char *
archive_nettle_version(void)
{
#if defined(ARCHIVE_CRYPTOR_USE_NETTLE) || defined(ARCHIVE_CRYPTO_NETTLE)
static char nettle_version[6];
snprintf(nettle_version, 6, "%d.%d", nettle_version_major(), nettle_version_minor());
return nettle_version;
#else
return NULL;
#endif
}
const char *
archive_openssl_version(void)
{
#if defined(ARCHIVE_CRYPTOR_USE_OPENSSL) || defined(ARCHIVE_CRYPTO_OPENSSL)
#ifdef OPENSSL_VERSION_STR
return OPENSSL_VERSION_STR;
#else
#define OPENSSL_MAJOR (OPENSSL_VERSION_NUMBER >> 28)
#define OPENSSL_MINOR ((OPENSSL_VERSION_NUMBER >> 20) & 0xFF)
static char openssl_version[6];
snprintf(openssl_version, 6, "%ld.%ld", OPENSSL_MAJOR, OPENSSL_MINOR);
return openssl_version;
#undef OPENSSL_MAJOR
#undef OPENSSL_MINOR
#endif
#else
return NULL;
#endif
}
const char *
archive_libmd_version(void)
{
#if defined(ARCHIVE_CRYPTOR_USE_LIBMD) || defined(ARCHIVE_CRYPTO_LIBMD)
return "system";
#else
return NULL;
#endif
}
const char *
archive_commoncrypto_version(void)
{
#if defined(ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto) || defined(ARCHIVE_CRYPTO_CommonCrypto)
return "system";
#else
return NULL;
#endif
}
const char *
archive_cng_version(void)
{
#if defined(ARCHIVE_CRYPTOR_USE_CNG) || defined(ARCHIVE_CRYPTO_CNG)
#ifdef BCRYPT_HASH_INTERFACE_MAJORVERSION_2
return "2.0";
#else
return "1.0";
#endif
#else
return NULL;
#endif
}
const char *
archive_wincrypt_version(void)
{
#if defined(ARCHIVE_CRYPTOR_USE_WINCRYPT) || defined(ARCHIVE_CRYPTO_WINCRYPT)
HCRYPTPROV prov;
if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
if (GetLastError() != (DWORD)NTE_BAD_KEYSET)
return NULL;
if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
return NULL;
}
DWORD version, length = sizeof(version);
if (!CryptGetProvParam(prov, PP_VERSION, (BYTE *)&version, &length, 0)) {
return NULL;
} else {
char major = (version >> 8) & 0xFF;
char minor = version & 0xFF;
static char wincrypt_version[6];
snprintf(wincrypt_version, 6, "%hhd.%hhd", major, minor);
return wincrypt_version;
}
#else
return NULL;
#endif
}
const char *
archive_librichacl_version(void)
{
#if HAVE_LIBRICHACL
#if defined(LIBRICHACL_PKGCONFIG_VERSION)
return LIBRICHACL_PKGCONFIG_VERSION;
#else
return "system";
#endif
#else
return NULL;
#endif
}
const char *
archive_libacl_version(void)
{
#if HAVE_LIBACL
#if defined(LIBACL_PKGCONFIG_VERSION)
return LIBACL_PKGCONFIG_VERSION;
#else
return "system";
#endif
#else
return NULL;
#endif
}
const char *
archive_libattr_version(void)
{
#if HAVE_LIBATTR
#if defined(LIBATTR_PKGCONFIG_VERSION)
return LIBATTR_PKGCONFIG_VERSION;
#else
return "system";
#endif
#else
return NULL;
#endif
}
const char *
archive_libiconv_version(void)
{
#if HAVE_LIBCHARSET && HAVE_ICONV_H
char major = _libiconv_version >> 8;
char minor = _libiconv_version & 0xFF;
static char charset_version[6];
snprintf(charset_version, 6, "%hhd.%hhd", major, minor);
return charset_version;
#else
return NULL;
#endif
}
const char *
archive_libpcre_version(void)
{
#if HAVE_LIBPCREPOSIX && HAVE_PCRE_H
#define str(s) #s
#define NUMBER(x) str(x)
return NUMBER(PCRE_MAJOR) "." NUMBER(PCRE_MINOR);
#undef NUMBER
#undef str
#else
return NULL;
#endif
}
const char *
archive_libpcre2_version(void)
{
#if HAVE_LIBPCRE2POSIX && HAVE_PCRE2_H
#define str(s) #s
#define NUMBER(x) str(x)
return NUMBER(PCRE2_MAJOR) "." NUMBER(PCRE2_MINOR);
#undef NUMBER
#undef str
#else
return NULL;
#endif
@@ -283,7 +283,7 @@ __archive_write_filters_open(struct archive_write *a)
}
/*
* Close all filtes
* Close all filters
*/
static int
__archive_write_filters_close(struct archive_write *a)
@@ -166,7 +166,7 @@ archive_filter_b64encode_open(struct archive_write_filter *f)
}
archive_string_sprintf(&state->encoded_buff, "begin-base64 %o %s\n",
state->mode, state->name.s);
(unsigned int)state->mode, state->name.s);
f->data = state;
return (0);
@@ -58,6 +58,7 @@ archive_write_set_compression_gzip(struct archive *a)
struct private_data {
int compression_level;
int timestamp;
char *original_filename;
#ifdef HAVE_ZLIB_H
z_stream stream;
int64_t total_in;
@@ -113,6 +114,8 @@ archive_write_add_filter_gzip(struct archive *_a)
f->free = &archive_compressor_gzip_free;
f->code = ARCHIVE_FILTER_GZIP;
f->name = "gzip";
data->original_filename = NULL;
#ifdef HAVE_ZLIB_H
data->compression_level = Z_DEFAULT_COMPRESSION;
return (ARCHIVE_OK);
@@ -140,6 +143,7 @@ archive_compressor_gzip_free(struct archive_write_filter *f)
#else
__archive_write_program_free(data->pdata);
#endif
free((void*)data->original_filename);
free(data);
f->data = NULL;
return (ARCHIVE_OK);
@@ -165,6 +169,13 @@ archive_compressor_gzip_options(struct archive_write_filter *f, const char *key,
data->timestamp = (value == NULL)?-1:1;
return (ARCHIVE_OK);
}
if (strcmp(key, "original-filename") == 0) {
free((void*)data->original_filename);
data->original_filename = NULL;
if (value)
data->original_filename = strdup(value);
return (ARCHIVE_OK);
}
/* Note: The "warn" return is just to inform the options
* supervisor that we didn't handle it. It will generate
@@ -210,7 +221,7 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
data->compressed[0] = 0x1f; /* GZip signature bytes */
data->compressed[1] = 0x8b;
data->compressed[2] = 0x08; /* "Deflate" compression */
data->compressed[3] = 0; /* No options */
data->compressed[3] = data->original_filename == NULL ? 0 : 0x8;
if (data->timestamp >= 0) {
time_t t = time(NULL);
data->compressed[4] = (uint8_t)(t)&0xff; /* Timestamp */
@@ -229,6 +240,12 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
data->stream.next_out += 10;
data->stream.avail_out -= 10;
if (data->original_filename != NULL) {
strcpy((char*)data->compressed + 10, data->original_filename);
data->stream.next_out += strlen(data->original_filename) + 1;
data->stream.avail_out -= strlen(data->original_filename) + 1;
}
f->write = archive_compressor_gzip_write;
/* Initialize compression library. */
@@ -155,7 +155,7 @@ archive_filter_uuencode_open(struct archive_write_filter *f)
}
archive_string_sprintf(&state->encoded_buff, "begin %o %s\n",
state->mode, state->name.s);
(unsigned int)state->mode, state->name.s);
f->data = state;
return (0);
@@ -478,9 +478,11 @@ la_verify_filetype(mode_t mode, __LA_MODE_T filetype) {
case AE_IFLNK:
ret = (S_ISLNK(mode));
break;
#ifdef S_ISSOCK
case AE_IFSOCK:
ret = (S_ISSOCK(mode));
break;
#endif
case AE_IFCHR:
ret = (S_ISCHR(mode));
break;
@@ -3605,7 +3607,7 @@ set_time_tru64(int fd, int mode, const char *name,
tstamp.atime.tv_sec = atime;
tstamp.mtime.tv_sec = mtime;
tstamp.ctime.tv_sec = ctime;
#if defined (__hpux) && defined (__ia64)
#if defined (__hpux) && ( defined (__ia64) || defined (__hppa) )
tstamp.atime.tv_nsec = atime_nsec;
tstamp.mtime.tv_nsec = mtime_nsec;
tstamp.ctime.tv_nsec = ctime_nsec;
@@ -3788,7 +3790,7 @@ set_mode(struct archive_write_disk *a, int mode)
* permissions on symlinks, so a failure here has no
* impact.
*/
if (lchmod(a->name, mode) != 0) {
if (lchmod(a->name, (mode_t)mode) != 0) {
switch (errno) {
case ENOTSUP:
case ENOSYS:
@@ -3803,7 +3805,8 @@ set_mode(struct archive_write_disk *a, int mode)
break;
default:
archive_set_error(&a->archive, errno,
"Can't set permissions to 0%o", (int)mode);
"Can't set permissions to 0%o",
(unsigned int)mode);
r = ARCHIVE_WARN;
}
}
@@ -3817,16 +3820,16 @@ set_mode(struct archive_write_disk *a, int mode)
*/
#ifdef HAVE_FCHMOD
if (a->fd >= 0)
r2 = fchmod(a->fd, mode);
r2 = fchmod(a->fd, (mode_t)mode);
else
#endif
/* If this platform lacks fchmod(), then
* we'll just use chmod(). */
r2 = chmod(a->name, mode);
r2 = chmod(a->name, (mode_t)mode);
if (r2 != 0) {
archive_set_error(&a->archive, errno,
"Can't set permissions to 0%o", (int)mode);
"Can't set permissions to 0%o", (unsigned int)mode);
r = ARCHIVE_WARN;
}
}
@@ -118,7 +118,7 @@ open_filename(struct archive *a, int mbs_fn, const void *filename)
(const char *)filename);
else
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Can't convert '%S' to MBS",
"Can't convert '%ls' to MBS",
(const wchar_t *)filename);
return (ARCHIVE_FAILED);
}
@@ -170,7 +170,7 @@ file_open(struct archive *a, void *client_data)
else {
archive_mstring_get_wcs(a, &mine->filename, &wcs);
archive_set_error(a, errno,
"Can't convert '%S' to MBS", wcs);
"Can't convert '%ls' to MBS", wcs);
}
return (ARCHIVE_FATAL);
}
@@ -181,7 +181,7 @@ file_open(struct archive *a, void *client_data)
if (mbs != NULL)
archive_set_error(a, errno, "Failed to open '%s'", mbs);
else
archive_set_error(a, errno, "Failed to open '%S'", wcs);
archive_set_error(a, errno, "Failed to open '%ls'", wcs);
return (ARCHIVE_FATAL);
}
@@ -189,7 +189,7 @@ file_open(struct archive *a, void *client_data)
if (mbs != NULL)
archive_set_error(a, errno, "Couldn't stat '%s'", mbs);
else
archive_set_error(a, errno, "Couldn't stat '%S'", wcs);
archive_set_error(a, errno, "Couldn't stat '%ls'", wcs);
return (ARCHIVE_FATAL);
}
@@ -28,7 +28,12 @@
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_BZLIB_H
#include <bzlib.h>
#endif
@@ -38,6 +43,9 @@
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#endif
#ifdef HAVE_ZSTD_H
#include <zstd.h>
#endif
#include "archive.h"
#ifndef HAVE_ZLIB_H
@@ -50,6 +58,7 @@
#include "archive_private.h"
#include "archive_rb.h"
#include "archive_string.h"
#include "archive_time_private.h"
#include "archive_write_private.h"
#include "archive_write_set_format_private.h"
@@ -63,6 +72,8 @@
#define _7Z_BZIP2 0x040202
#define _7Z_PPMD 0x030401
#define _7Z_ZSTD 0x4F71101 /* Copied from https://github.com/mcmilk/7-Zip-zstd.git */
/*
* 7-Zip header property IDs.
*/
@@ -110,6 +121,9 @@
// the attr field along with the unix permissions.
#define FILE_ATTRIBUTE_UNIX_EXTENSION 0x8000
// Many systems define min or MIN, but not all.
#define sevenzipmin(a,b) ((a) < (b) ? (a) : (b))
enum la_zaction {
ARCHIVE_Z_FINISH,
ARCHIVE_Z_RUN
@@ -209,7 +223,11 @@ struct _7zip {
#define ENCODED_CRC32 2
unsigned opt_compression;
int opt_compression_level;
int opt_zstd_compression_level; // This requires a different default value.
int opt_threads;
struct la_zstream stream;
struct coder coder;
@@ -285,12 +303,19 @@ static int compression_code_lzma(struct archive *,
static int compression_end_lzma(struct archive *, struct la_zstream *);
#endif
static int compression_init_encoder_ppmd(struct archive *,
struct la_zstream *, unsigned, uint32_t);
struct la_zstream *, uint8_t, uint32_t);
static int compression_code_ppmd(struct archive *,
struct la_zstream *, enum la_zaction);
static int compression_end_ppmd(struct archive *, struct la_zstream *);
static int _7z_compression_init_encoder(struct archive_write *, unsigned,
int);
static int compression_init_encoder_zstd(struct archive *,
struct la_zstream *, int, int);
#if defined(HAVE_ZSTD_H)
static int compression_code_zstd(struct archive *,
struct la_zstream *, enum la_zaction);
static int compression_end_zstd(struct archive *, struct la_zstream *);
#endif
static int compression_code(struct archive *,
struct la_zstream *, enum la_zaction);
static int compression_end(struct archive *,
@@ -301,6 +326,21 @@ static int make_header(struct archive_write *, uint64_t, uint64_t,
static int make_streamsInfo(struct archive_write *, uint64_t, uint64_t,
uint64_t, int, struct coder *, int, uint32_t);
static int
string_to_number(const char *string, intmax_t *numberp)
{
char *end;
if (string == NULL || *string == '\0')
return (ARCHIVE_WARN);
*numberp = strtoimax(string, &end, 10);
if (end == string || *end != '\0' || errno == EOVERFLOW) {
*numberp = 0;
return (ARCHIVE_WARN);
}
return (ARCHIVE_OK);
}
int
archive_write_set_format_7zip(struct archive *_a)
{
@@ -335,11 +375,24 @@ archive_write_set_format_7zip(struct archive *_a)
zip->opt_compression = _7Z_BZIP2;
#elif defined(HAVE_ZLIB_H)
zip->opt_compression = _7Z_DEFLATE;
#elif HAVE_ZSTD_H
zip->opt_compression = _7Z_ZSTD;
#else
zip->opt_compression = _7Z_COPY;
#endif
zip->opt_compression_level = 6;
#ifdef ZSTD_CLEVEL_DEFAULT
// Zstandard compression needs a different default
// value than other encoders.
zip->opt_zstd_compression_level = ZSTD_CLEVEL_DEFAULT;
#else
zip->opt_zstd_compression_level = 3;
#endif
zip->opt_threads = 1;
a->format_data = zip;
a->format_name = "7zip";
@@ -397,6 +450,13 @@ _7z_options(struct archive_write *a, const char *key, const char *value)
zip->opt_compression = _7Z_LZMA2;
#else
name = "lzma2";
#endif
else if (strcmp(value, "zstd") == 0 ||
strcmp(value, "ZSTD") == 0)
#if HAVE_ZSTD_H
zip->opt_compression = _7Z_ZSTD;
#else
name = "zstd";
#endif
else if (strcmp(value, "ppmd") == 0 ||
strcmp(value, "PPMD") == 0 ||
@@ -420,16 +480,68 @@ _7z_options(struct archive_write *a, const char *key, const char *value)
return (ARCHIVE_OK);
}
if (strcmp(key, "compression-level") == 0) {
if (value == NULL ||
!(value[0] >= '0' && value[0] <= '9') ||
value[1] != '\0') {
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC,
"Illegal value `%s'",
value);
if (value == NULL || *value == '\0') {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"Invalid compression-level option value `%s'", value);
return (ARCHIVE_FAILED);
}
zip->opt_compression_level = value[0] - '0';
char *end = NULL;
long lvl = strtol(value, &end, 10);
if (end == NULL || *end != '\0') {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"parsing compression-level option value failed `%s'", value);
return (ARCHIVE_FAILED);
}
#if HAVE_ZSTD_H && HAVE_ZSTD_compressStream && HAVE_ZSTD_minCLevel
int min_level = sevenzipmin(0, ZSTD_minCLevel());
#else
const int min_level = 0;
#endif
#if HAVE_ZSTD_H && HAVE_ZSTD_compressStream
int max_level = ZSTD_maxCLevel();
#else
const int max_level = 9;
#endif
if (lvl < min_level || lvl > max_level) {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"compression-level option value `%ld' out of range", lvl);
return (ARCHIVE_FAILED);
}
// Note: we don't know here if this value is for zstd (negative to ~22),
// or zlib-style 0-9. If zstd is enabled but not in use, we will need to
// validate opt_compression_level before use.
zip->opt_compression_level = (int)lvl;
zip->opt_zstd_compression_level = (int)lvl;
return (ARCHIVE_OK);
}
if (strcmp(key, "threads") == 0) {
intmax_t threads;
if (string_to_number(value, &threads) != ARCHIVE_OK) {
return (ARCHIVE_WARN);
}
if (threads < 0) {
return (ARCHIVE_WARN);
}
if (threads == 0) {
#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
threads = sysconf(_SC_NPROCESSORS_ONLN);
#elif !defined(__CYGWIN__) && defined(_WIN32_WINNT) && \
_WIN32_WINNT >= 0x0601 /* _WIN32_WINNT_WIN7 */
DWORD winCores = GetActiveProcessorCount(
ALL_PROCESSOR_GROUPS);
threads = (intmax_t)winCores;
#else
threads = 1;
#endif
}
zip->opt_threads = (int)threads;
return (ARCHIVE_OK);
}
@@ -495,8 +607,20 @@ _7z_write_header(struct archive_write *a, struct archive_entry *entry)
* Init compression.
*/
if ((zip->total_number_entry - zip->total_number_empty_entry) == 1) {
r = _7z_compression_init_encoder(a, zip->opt_compression,
zip->opt_compression_level);
int level = zip->opt_compression_level;
#if HAVE_ZSTD_H
if (zip->opt_compression == _7Z_ZSTD) {
level = zip->opt_zstd_compression_level;
} else if (level < 0 || level > 9) {
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
"compression-level option value `%d' out of range 0-9", level);
file_free(file);
return (ARCHIVE_FATAL);
}
#endif
r = _7z_compression_init_encoder(a, zip->opt_compression, level);
if (r < 0) {
file_free(file);
return (ARCHIVE_FATAL);
@@ -785,8 +909,12 @@ _7z_close(struct archive_write *a)
#else
header_compression = _7Z_COPY;
#endif
r = _7z_compression_init_encoder(a, header_compression,
zip->opt_compression_level);
int level = zip->opt_compression_level;
if (level < 0) level = 0;
else if (level > 9) level = 9;
r = _7z_compression_init_encoder(a, header_compression, level);
if (r < 0)
return (r);
zip->crc32flg = PRECODE_CRC32;
@@ -844,7 +972,7 @@ _7z_close(struct archive_write *a)
header_offset = header_size = 0;
header_crc32 = 0;
}
length = zip->temp_offset;
/*
@@ -1164,20 +1292,6 @@ make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size,
return (ARCHIVE_OK);
}
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
static uint64_t
utcToFiletime(time_t t, long ns)
{
uint64_t fileTime;
fileTime = t;
fileTime *= 10000000;
fileTime += ns / 100;
fileTime += EPOC_TIME;
return (fileTime);
}
static int
make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
{
@@ -1249,7 +1363,6 @@ make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
if (r < 0)
return (r);
/*
* Make Times.
*/
@@ -1257,7 +1370,7 @@ make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
for (;file != NULL; file = file->next) {
if ((file->flg & flg) == 0)
continue;
archive_le64enc(filetime, utcToFiletime(file->times[ti].time,
archive_le64enc(filetime, unix_to_ntfs(file->times[ti].time,
file->times[ti].time_ns));
r = (int)compress_out(a, filetime, 8, ARCHIVE_Z_RUN);
if (r < 0)
@@ -1504,7 +1617,7 @@ file_cmp_node(const struct archive_rb_node *n1,
return (memcmp(f1->utf16name, f2->utf16name, f1->name_len));
return (f1->name_len > f2->name_len)?1:-1;
}
static int
file_cmp_key(const struct archive_rb_node *n, const void *key)
{
@@ -1646,7 +1759,8 @@ file_init_register_empty(struct _7zip *zip)
}
#if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\
!defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
!defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H) ||\
!(HAVE_ZSTD_H && HAVE_ZSTD_compressStream)
static int
compression_unsupported_encoder(struct archive *a,
struct la_zstream *lastrm, const char *name)
@@ -2159,7 +2273,7 @@ ppmd_write(void *p, Byte b)
static int
compression_init_encoder_ppmd(struct archive *a,
struct la_zstream *lastrm, unsigned maxOrder, uint32_t msize)
struct la_zstream *lastrm, uint8_t maxOrder, uint32_t msize)
{
struct ppmd_stream *strm;
uint8_t *props;
@@ -2279,6 +2393,117 @@ compression_end_ppmd(struct archive *a, struct la_zstream *lastrm)
return (ARCHIVE_OK);
}
#if HAVE_ZSTD_H && HAVE_ZSTD_compressStream
static int
compression_init_encoder_zstd(struct archive *a, struct la_zstream *lastrm, int level, int threads)
{
if (lastrm->valid)
compression_end(a, lastrm);
ZSTD_CStream *strm = ZSTD_createCStream();
if (strm == NULL) {
archive_set_error(a, ENOMEM,
"Can't allocate memory for zstd stream");
return (ARCHIVE_FATAL);
}
if (ZSTD_isError(ZSTD_initCStream(strm, level))) {
ZSTD_freeCStream(strm);
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Internal error initializing zstd compressor object");
return (ARCHIVE_FATAL);
}
ZSTD_CCtx_setParameter(strm, ZSTD_c_nbWorkers, threads);
// p7zip-zstd fails to unpack archives that don't have prop_size 5.
// 7-Zip-zstd fails to unpack archives that don't have prop_size 3 or 5.
// So let's use 5...
lastrm->prop_size = 5;
lastrm->props = calloc(5, 1);
if (lastrm->props == NULL) {
ZSTD_freeCStream(strm);
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Internal error initializing zstd compressor properties");
return (ARCHIVE_FATAL);
}
// Refer to the DProps struct in 7-Zip-zstd's ZstdDecoder.h:
// https://github.com/mcmilk/7-Zip-zstd/blob/79b2c78e9e7735ddf90147129b75cf2797ff6522/CPP/7zip/Compress/ZstdDecoder.h#L34S
lastrm->props[0] = ZSTD_VERSION_MAJOR;
lastrm->props[1] = ZSTD_VERSION_MINOR;
lastrm->props[2] = level;
// lastrm->props[3] and lastrm->props[4] are reserved. Leave them as 0.
lastrm->real_stream = strm;
lastrm->valid = 1;
lastrm->code = compression_code_zstd;
lastrm->end = compression_end_zstd;
return (ARCHIVE_OK);
}
static int
compression_code_zstd(struct archive *a,
struct la_zstream *lastrm, enum la_zaction action)
{
ZSTD_CStream *strm = (ZSTD_CStream *)lastrm->real_stream;
ZSTD_outBuffer out = { .dst = lastrm->next_out, .size = lastrm->avail_out, .pos = 0 };
ZSTD_inBuffer in = { .src = lastrm->next_in, .size = lastrm->avail_in, .pos = 0 };
size_t zret;
ZSTD_EndDirective mode = (action == ARCHIVE_Z_RUN) ? ZSTD_e_continue : ZSTD_e_end;
zret = ZSTD_compressStream2(strm, &out, &in, mode);
if (ZSTD_isError(zret)) {
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"zstd compression failed, ZSTD_compressStream2 returned: %s",
ZSTD_getErrorName(zret));
return (ARCHIVE_FATAL);
}
lastrm->next_in += in.pos;
lastrm->avail_in -= in.pos;
lastrm->total_in += in.pos;
lastrm->next_out += out.pos;
lastrm->avail_out -= out.pos;
lastrm->total_out += out.pos;
if (action == ARCHIVE_Z_FINISH && zret == 0)
return (ARCHIVE_EOF); // All done.
return (ARCHIVE_OK); // More work to do.
}
static int
compression_end_zstd(struct archive *a, struct la_zstream *lastrm)
{
ZSTD_CStream *strm;
(void)a; /* UNUSED */
strm = (ZSTD_CStream *)lastrm->real_stream;
ZSTD_freeCStream(strm);
lastrm->valid = 0;
lastrm->real_stream = NULL;
return (ARCHIVE_OK);
}
#else
static int
compression_init_encoder_zstd(struct archive *a, struct la_zstream *lastrm, int level, int threads)
{
(void) level; /* UNUSED */
(void) threads; /* UNUSED */
if (lastrm->valid)
compression_end(a, lastrm);
return (compression_unsupported_encoder(a, lastrm, "zstd"));
}
#endif
/*
* Universal compressor initializer.
*/
@@ -2316,6 +2541,11 @@ _7z_compression_init_encoder(struct archive_write *a, unsigned compression,
&(a->archive), &(zip->stream),
PPMD7_DEFAULT_ORDER, PPMD7_DEFAULT_MEM_SIZE);
break;
case _7Z_ZSTD:
r = compression_init_encoder_zstd(
&(a->archive), &(zip->stream),
compression_level, zip->opt_threads);
break;
case _7Z_COPY:
default:
r = compression_init_encoder_copy(
@@ -2352,5 +2582,3 @@ compression_end(struct archive *a, struct la_zstream *lastrm)
}
return (ARCHIVE_OK);
}
@@ -153,7 +153,7 @@ static const char template_header[] = {
static int archive_write_gnutar_options(struct archive_write *,
const char *, const char *);
static int archive_format_gnutar_header(struct archive_write *, char h[512],
struct archive_entry *, int tartype);
struct archive_entry *, char tartype);
static int archive_write_gnutar_header(struct archive_write *,
struct archive_entry *entry);
static ssize_t archive_write_gnutar_data(struct archive_write *a, const void *buff,
@@ -274,7 +274,7 @@ archive_write_gnutar_header(struct archive_write *a,
{
char buff[512];
int r, ret, ret2 = ARCHIVE_OK;
int tartype;
char tartype;
struct gnutar *gnutar;
struct archive_string_conv *sconv;
struct archive_entry *entry_main;
@@ -504,7 +504,7 @@ archive_write_gnutar_header(struct archive_write *a,
archive_entry_set_uname(temp, "root");
archive_entry_set_gname(temp, "wheel");
archive_entry_set_pathname(temp, "././@LongLink");
archive_entry_set_pathname(temp, "././@LongName");
archive_entry_set_size(temp, length);
ret = archive_format_gnutar_header(a, buff, temp, 'L');
archive_entry_free(temp);
@@ -562,7 +562,7 @@ exit_write_header:
static int
archive_format_gnutar_header(struct archive_write *a, char h[512],
struct archive_entry *entry, int tartype)
struct archive_entry *entry, char tartype)
{
unsigned int checksum;
int i, ret;
@@ -640,7 +640,7 @@ archive_format_gnutar_header(struct archive_write *a, char h[512],
if (format_number(archive_entry_uid(entry), h + GNUTAR_uid_offset,
GNUTAR_uid_size, GNUTAR_uid_max_size)) {
archive_set_error(&a->archive, ERANGE,
"Numeric user ID %jd too large",
"Numeric user ID %jd too large for gnutar format",
(intmax_t)archive_entry_uid(entry));
ret = ARCHIVE_FAILED;
}
@@ -649,7 +649,7 @@ archive_format_gnutar_header(struct archive_write *a, char h[512],
if (format_number(archive_entry_gid(entry), h + GNUTAR_gid_offset,
GNUTAR_gid_size, GNUTAR_gid_max_size)) {
archive_set_error(&a->archive, ERANGE,
"Numeric group ID %jd too large",
"Numeric group ID %jd too large for gnutar format",
(intmax_t)archive_entry_gid(entry));
ret = ARCHIVE_FAILED;
}
@@ -672,7 +672,7 @@ archive_format_gnutar_header(struct archive_write *a, char h[512],
h + GNUTAR_rdevmajor_offset,
GNUTAR_rdevmajor_size)) {
archive_set_error(&a->archive, ERANGE,
"Major device number too large");
"Major device number too large for gnutar format");
ret = ARCHIVE_FAILED;
}
@@ -680,7 +680,7 @@ archive_format_gnutar_header(struct archive_write *a, char h[512],
h + GNUTAR_rdevminor_offset,
GNUTAR_rdevminor_size)) {
archive_set_error(&a->archive, ERANGE,
"Minor device number too large");
"Minor device number too large for gnutar format");
ret = ARCHIVE_FAILED;
}
}
@@ -911,7 +911,7 @@ static int iso9660_finish_entry(struct archive_write *);
static int iso9660_close(struct archive_write *);
static int iso9660_free(struct archive_write *);
static void get_system_identitier(char *, size_t);
static void get_system_identifier(char *, size_t);
static void set_str(unsigned char *, const char *, size_t, char,
const char *);
static inline int joliet_allowed_char(unsigned char, unsigned char);
@@ -1167,7 +1167,12 @@ archive_write_set_format_iso9660(struct archive *_a)
iso9660->primary.rootent->parent = iso9660->primary.rootent;
iso9660->cur_dirent = iso9660->primary.rootent;
archive_string_init(&(iso9660->cur_dirstr));
archive_string_ensure(&(iso9660->cur_dirstr), 1);
if (archive_string_ensure(&(iso9660->cur_dirstr), 1) == NULL) {
free(iso9660);
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory");
return (ARCHIVE_FATAL);
}
iso9660->cur_dirstr.s[0] = 0;
iso9660->sconv_to_utf16be = NULL;
iso9660->sconv_from_utf16be = NULL;
@@ -2166,7 +2171,7 @@ iso9660_free(struct archive_write *a)
* Get the System Identifier
*/
static void
get_system_identitier(char *system_id, size_t size)
get_system_identifier(char *system_id, size_t size)
{
#if defined(HAVE_SYS_UTSNAME_H)
struct utsname u;
@@ -3872,7 +3877,7 @@ write_VD(struct archive_write *a, struct vdd *vdd)
/* Unused Field */
set_unused_field_bp(bp, 8, 8);
/* System Identifier */
get_system_identitier(identifier, sizeof(identifier));
get_system_identifier(identifier, sizeof(identifier));
r = set_str_a_characters_bp(a, bp, 9, 40, identifier, vdc);
if (r != ARCHIVE_OK)
return (r);
@@ -4037,7 +4042,7 @@ set_option_info(struct archive_string *info, int *opt, const char *key,
case KEY_HEX:
d = va_arg(ap, int);
archive_string_sprintf(info, "%c%s=%x",
prefix, key, d);
prefix, key, (unsigned int)d);
break;
}
va_end(ap);
@@ -5666,9 +5671,15 @@ isoent_tree(struct archive_write *a, struct isoent **isoentpp)
* inserted. */
iso9660->cur_dirent = dent;
archive_string_empty(&(iso9660->cur_dirstr));
archive_string_ensure(&(iso9660->cur_dirstr),
if (archive_string_ensure(&(iso9660->cur_dirstr),
archive_strlen(&(dent->file->parentdir)) +
archive_strlen(&(dent->file->basename)) + 2);
archive_strlen(&(dent->file->basename)) + 2) == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory");
_isoent_free(isoent);
*isoentpp = NULL;
return (ARCHIVE_FATAL);
}
if (archive_strlen(&(dent->file->parentdir)) +
archive_strlen(&(dent->file->basename)) == 0)
iso9660->cur_dirstr.s[0] = 0;
@@ -54,7 +54,7 @@ struct attr_counter {
int count;
};
struct att_counter_set {
struct attr_counter_set {
struct attr_counter *uid_list;
struct attr_counter *gid_list;
struct attr_counter *mode_list;
@@ -82,6 +82,7 @@ struct dir_info {
struct reg_info {
int compute_sum;
uint32_t crc;
uint_least32_t mset_digest;
struct ae_digest digest;
};
@@ -141,7 +142,7 @@ struct mtree_writer {
unsigned long fflags_set;
unsigned long fflags_clear;
} set;
struct att_counter_set acs;
struct attr_counter_set acs;
int classic;
int depth;
@@ -437,7 +438,7 @@ write_global(struct mtree_writer *mtree)
{
struct archive_string setstr;
struct archive_string unsetstr;
struct att_counter_set *acs;
struct attr_counter_set *acs;
int keys, oldkeys, effkeys;
archive_string_init(&setstr);
@@ -638,7 +639,7 @@ static int
attr_counter_set_collect(struct mtree_writer *mtree, struct mtree_entry *me)
{
struct attr_counter *ac, *last;
struct att_counter_set *acs = &mtree->acs;
struct attr_counter_set *acs = &mtree->acs;
int keys = mtree->keys;
if (keys & (F_UNAME | F_UID)) {
@@ -714,7 +715,7 @@ attr_counter_set_collect(struct mtree_writer *mtree, struct mtree_entry *me)
static void
attr_counter_set_free(struct mtree_writer *mtree)
{
struct att_counter_set *acs = &mtree->acs;
struct attr_counter_set *acs = &mtree->acs;
attr_counter_free(&acs->uid_list);
attr_counter_free(&acs->gid_list);
@@ -862,6 +863,50 @@ mtree_entry_free(struct mtree_entry *me)
free(me);
}
static void
mtree_copy_ae_digests(struct reg_info *reg, struct archive_entry *entry, int compute_sum)
{
reg->compute_sum = compute_sum;
reg->mset_digest = entry->mset_digest;
if ((reg->compute_sum & F_MD5)
&& (reg->mset_digest & AE_MSET_DIGEST_MD5)) {
memcpy(&reg->digest.md5, entry->digest.md5,
sizeof(reg->digest.md5));
}
if ((reg->compute_sum & F_RMD160)
&& (reg->mset_digest & AE_MSET_DIGEST_RMD160)) {
memcpy(&reg->digest.rmd160, entry->digest.rmd160,
sizeof(reg->digest.rmd160));
}
if ((reg->compute_sum & F_SHA1)
&& (reg->mset_digest & AE_MSET_DIGEST_SHA1)) {
memcpy(&reg->digest.sha1, entry->digest.sha1,
sizeof(reg->digest.sha1));
}
if ((reg->compute_sum & F_SHA256)
&& (reg->mset_digest & AE_MSET_DIGEST_SHA256)) {
memcpy(&reg->digest.sha256, entry->digest.sha256,
sizeof(reg->digest.sha256));
}
if ((reg->compute_sum & F_SHA384)
&& (reg->mset_digest & AE_MSET_DIGEST_SHA384)) {
memcpy(&reg->digest.sha384, entry->digest.sha384,
sizeof(reg->digest.sha384));
}
if ((reg->compute_sum & F_SHA512)
&& (reg->mset_digest & AE_MSET_DIGEST_SHA512)) {
memcpy(&reg->digest.sha512, entry->digest.sha512,
sizeof(reg->digest.sha512));
}
}
static int
archive_write_mtree_header(struct archive_write *a,
struct archive_entry *entry)
@@ -896,8 +941,12 @@ archive_write_mtree_header(struct archive_write *a,
/* If the current file is a regular file, we have to
* compute the sum of its content.
* Initialize a bunch of checksum context. */
if (mtree_entry->reg_info)
if (mtree_entry->reg_info) {
sum_init(mtree);
/* honor archive_entry_set_digest() calls. These values will be
* overwritten if archive_write_mtree_data() is called */
mtree_copy_ae_digests(mtree_entry->reg_info, entry, mtree->compute_sum);
}
return (r2);
}
@@ -1516,28 +1565,46 @@ sum_update(struct mtree_writer *mtree, const void *buff, size_t n)
mtree->crc_len += n;
}
#ifdef ARCHIVE_HAS_MD5
if (mtree->compute_sum & F_MD5)
if (mtree->compute_sum & F_MD5) {
archive_md5_update(&mtree->md5ctx, buff, n);
mtree->mtree_entry->reg_info->mset_digest &=
~AE_MSET_DIGEST_MD5;
}
#endif
#ifdef ARCHIVE_HAS_RMD160
if (mtree->compute_sum & F_RMD160)
if (mtree->compute_sum & F_RMD160) {
archive_rmd160_update(&mtree->rmd160ctx, buff, n);
mtree->mtree_entry->reg_info->mset_digest &=
~AE_MSET_DIGEST_RMD160;
}
#endif
#ifdef ARCHIVE_HAS_SHA1
if (mtree->compute_sum & F_SHA1)
if (mtree->compute_sum & F_SHA1) {
archive_sha1_update(&mtree->sha1ctx, buff, n);
mtree->mtree_entry->reg_info->mset_digest &=
~AE_MSET_DIGEST_SHA1;
}
#endif
#ifdef ARCHIVE_HAS_SHA256
if (mtree->compute_sum & F_SHA256)
if (mtree->compute_sum & F_SHA256) {
archive_sha256_update(&mtree->sha256ctx, buff, n);
mtree->mtree_entry->reg_info->mset_digest &=
~AE_MSET_DIGEST_SHA256;
}
#endif
#ifdef ARCHIVE_HAS_SHA384
if (mtree->compute_sum & F_SHA384)
if (mtree->compute_sum & F_SHA384) {
archive_sha384_update(&mtree->sha384ctx, buff, n);
mtree->mtree_entry->reg_info->mset_digest &=
~AE_MSET_DIGEST_SHA384;
}
#endif
#ifdef ARCHIVE_HAS_SHA512
if (mtree->compute_sum & F_SHA512)
if (mtree->compute_sum & F_SHA512) {
archive_sha512_update(&mtree->sha512ctx, buff, n);
mtree->mtree_entry->reg_info->mset_digest &=
~AE_MSET_DIGEST_SHA512;
}
#endif
}
@@ -1553,27 +1620,39 @@ sum_final(struct mtree_writer *mtree, struct reg_info *reg)
reg->crc = ~mtree->crc;
}
#ifdef ARCHIVE_HAS_MD5
if (mtree->compute_sum & F_MD5)
if ((mtree->compute_sum & F_MD5)
&& !(reg->mset_digest & AE_MSET_DIGEST_MD5))
archive_md5_final(&mtree->md5ctx, reg->digest.md5);
#endif
#ifdef ARCHIVE_HAS_RMD160
if (mtree->compute_sum & F_RMD160)
if ((mtree->compute_sum & F_RMD160)
&& !(reg->mset_digest & AE_MSET_DIGEST_RMD160))
archive_rmd160_final(&mtree->rmd160ctx, reg->digest.rmd160);
#endif
#ifdef ARCHIVE_HAS_SHA1
if (mtree->compute_sum & F_SHA1)
if ((mtree->compute_sum & F_SHA1)
&& !(reg->mset_digest & AE_MSET_DIGEST_SHA1))
archive_sha1_final(&mtree->sha1ctx, reg->digest.sha1);
#endif
#ifdef ARCHIVE_HAS_SHA256
if (mtree->compute_sum & F_SHA256)
if ((mtree->compute_sum & F_SHA256)
&& !(reg->mset_digest & AE_MSET_DIGEST_SHA256))
archive_sha256_final(&mtree->sha256ctx, reg->digest.sha256);
#endif
#ifdef ARCHIVE_HAS_SHA384
if (mtree->compute_sum & F_SHA384)
if ((mtree->compute_sum & F_SHA384)
&& !(reg->mset_digest & AE_MSET_DIGEST_SHA384))
archive_sha384_final(&mtree->sha384ctx, reg->digest.sha384);
#endif
#ifdef ARCHIVE_HAS_SHA512
if (mtree->compute_sum & F_SHA512)
if ((mtree->compute_sum & F_SHA512)
&& !(reg->mset_digest & AE_MSET_DIGEST_SHA512))
archive_sha512_final(&mtree->sha512ctx, reg->digest.sha512);
#endif
/* Save what types of sum are computed. */
@@ -2130,9 +2209,13 @@ mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep)
* inserted. */
mtree->cur_dirent = dent;
archive_string_empty(&(mtree->cur_dirstr));
archive_string_ensure(&(mtree->cur_dirstr),
if (archive_string_ensure(&(mtree->cur_dirstr),
archive_strlen(&(dent->parentdir)) +
archive_strlen(&(dent->basename)) + 2);
archive_strlen(&(dent->basename)) + 2) == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory");
return (ARCHIVE_FATAL);
}
if (archive_strlen(&(dent->parentdir)) +
archive_strlen(&(dent->basename)) == 0)
mtree->cur_dirstr.s[0] = 0;
@@ -1414,7 +1414,7 @@ archive_write_pax_header(struct archive_write *a,
struct archive_entry *pax_attr_entry;
time_t s;
int64_t uid, gid;
int mode;
__LA_MODE_T mode;
pax_attr_entry = archive_entry_new2(&a->archive);
p = entry_name.s;
@@ -1571,7 +1571,7 @@ build_ustar_entry_name(char *dest, const char *src, size_t src_length,
const char *filename, *filename_end;
char *p;
int need_slash = 0; /* Was there a trailing slash? */
size_t suffix_length = 99;
size_t suffix_length = 98; /* 99 - 1 for trailing slash */
size_t insert_length;
/* Length of additional dir element to be added. */
@@ -1623,7 +1623,7 @@ build_ustar_entry_name(char *dest, const char *src, size_t src_length,
/* Step 2: Locate the "prefix" section of the dirname, including
* trailing '/'. */
prefix = src;
prefix_end = prefix + 155;
prefix_end = prefix + 154 /* 155 - 1 for trailing / */;
if (prefix_end > filename)
prefix_end = filename;
while (prefix_end > prefix && *prefix_end != '/')
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -263,7 +263,7 @@ decimal integer specifying log2 window size in bytes. Values from
The value is interpreted as a decimal integer specifying the
number of threads for multi-threaded zstd compression.
If set to 0, zstd will attempt to detect and use the number
of physical CPU cores.
of active physical CPU cores.
.El
.It Format 7zip
.Bl -tag -compact -width indent
@@ -274,9 +274,10 @@ The value is one of
.Dq deflate ,
.Dq bzip2 ,
.Dq lzma1 ,
.Dq lzma2
.Dq lzma2 ,
.Dq ppmd ,
or
.Dq ppmd
.Dq zstd
to indicate how the following entries should be compressed.
The values
.Dq store
@@ -289,9 +290,16 @@ and other special entries.
The value is interpreted as a decimal integer specifying the
compression level.
Values between 0 and 9 are supported, with the exception of bzip2
which only supports values between 1 and 9.
which only supports values between 1 and 9, and zstd which may
support negative values depending on the library version and
commonly used values 1 through 22.
The interpretation of the compression level depends on the chosen
compression method.
.It Cm threads
The value is interpreted as a decimal integer specifying the
number of threads for multi-threaded compression (for compressors
like zstd that support it). If set to 0, an attempt will be made
to discover the number of CPU cores.
.El
.It Format bin
.Bl -tag -compact -width indent
@@ -632,9 +640,13 @@ and
.Bl -tag -compact -width indent
.It Cm compression
The value is either
.Dq store
.Dq store ,
.Dq deflate ,
.Dq bzip2 ,
.Dq lzma ,
.Dq xz ,
or
.Dq deflate
.Dq zstd
to indicate how the following entries should be compressed.
Note that this setting is ignored for directories, symbolic links,
and other special entries.
@@ -645,8 +657,23 @@ Values between 0 and 9 are supported.
A compression level of 0 switches the compression method to
.Dq store ,
other values will enable
.Dq deflate
compression with the given level.
.Dq deflate ,
.Dq bzip2 ,
.Dq lzma ,
or
.Dq zstd
compression (in order of priority, depending on what libraries
are linked) with the given level.
.It Cm threads
The value is interpreted as a decimal integer specifying the
number of threads to use for compression.
It is supported only for
.Dq xz
or
.Dq zstd
compression and ignored for any other.
A threads value of 0 is a special one requesting to detect and use as
many threads as the number of active physical CPU cores.
.It Cm encryption
Enable encryption using traditional zip encryption.
.It Cm encryption Ns = Ns Ar type
@@ -327,10 +327,26 @@ by the usual environment variables.
Libarchive can read and write zip format archives that have
uncompressed entries and entries compressed with the
.Dq deflate
,
.Dq LZMA
,
.Dq XZ
,
.Dq BZIP2
and
.Dq ZSTD
algorithms.
Libarchive can also read, but not write, zip format archives that
have entries compressed with the
.Dq PPMd
algorithm.
Other zip compression algorithms are not supported.
It can extract jar archives, archives that use Zip64 extensions and
self-extracting zip archives.
The extensions supported by libarchive are Zip64, Libarchive's
extensions to better support streaming, PKZIP's traditional
ZIP encryption, Info-ZIP's Unix extra fields, extra time, and
Unicode path, as well as WinZIP's AES encryption.
It can extract jar archives, __MACOSX resource forks extension
for OS X, and self-extracting zip archives.
Libarchive can use either of two different strategies for
reading Zip archives:
a streaming strategy which is fast and can handle extremely
@@ -167,7 +167,7 @@ memory_read_skip(struct archive *a, void *client_data, int64_t skip)
(void)a; /* UNUSED */
/* We can't skip by more than is available. */
if ((off_t)skip > (off_t)(mine->end - mine->p))
if (skip > mine->end - mine->p)
skip = mine->end - mine->p;
/* Always do small skips by prime amounts. */
if (skip > 71)
@@ -1,100 +1,100 @@
/*
* Copyright (c) 2003-2018
* 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
* in this position and unchanged.
* 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(S) ``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(S) 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.
*/
#include "test.h"
DEFINE_TEST(test_7zip_filename_encoding_UTF16_win)
{
#if !defined(_WIN32) || defined(__CYGWIN__)
skipping("This test is meant to verify unicode string handling"
" on Windows with UTF-16 names");
return;
#else
struct archive *a;
struct archive_entry *entry;
char buff[4096];
size_t used;
/*
* Don't call setlocale because we're verifying that the '_w' functions
* work as expected
*/
a = archive_write_new();
assertEqualInt(ARCHIVE_OK, archive_write_set_format_7zip(a));
assertEqualInt(ARCHIVE_OK,
archive_write_open_memory(a, buff, sizeof(buff), &used));
/* Part 1: file */
entry = archive_entry_new2(a);
archive_entry_copy_pathname_w(entry, L"\u8868.txt");
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_size(entry, 0);
assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
/* Part 2: directory */
archive_entry_clear(entry);
archive_entry_copy_pathname_w(entry, L"\u8868");
archive_entry_set_filetype(entry, AE_IFDIR);
archive_entry_set_size(entry, 0);
assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
/* Part 3: symlink */
archive_entry_clear(entry);
archive_entry_set_pathname(entry, "link.txt");
archive_entry_copy_symlink_w(entry, L"\u8868.txt");
archive_entry_set_filetype(entry, AE_IFLNK);
archive_entry_set_symlink_type(entry, AE_SYMLINK_TYPE_FILE);
archive_entry_set_size(entry, 0);
assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
/* NOTE: 7zip does not support hardlinks */
archive_entry_free(entry);
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
/* Ensure that the archive contents can be read properly */
/* NOTE: 7zip file contents are not in the order we wrote them! */
a = archive_read_new();
archive_read_support_format_all(a);
archive_read_support_filter_all(a);
assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7));
/* Read part 3: symlink */
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &entry));
assertEqualWString(L"\u8868.txt", archive_entry_symlink_w(entry));
/* Read part 1: file */
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &entry));
assertEqualWString(L"\u8868.txt", archive_entry_pathname_w(entry));
/* Read part 2: directory */
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &entry));
/* NOTE: Trailing slash added automatically for us */
assertEqualWString(L"\u8868/", archive_entry_pathname_w(entry));
archive_read_free(a);
#endif
}
/*
* Copyright (c) 2003-2018
* 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
* in this position and unchanged.
* 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(S) ``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(S) 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.
*/
#include "test.h"
DEFINE_TEST(test_7zip_filename_encoding_UTF16_win)
{
#if !defined(_WIN32) || defined(__CYGWIN__)
skipping("This test is meant to verify unicode string handling"
" on Windows with UTF-16 names");
return;
#else
struct archive *a;
struct archive_entry *entry;
char buff[4096];
size_t used;
/*
* Don't call setlocale because we're verifying that the '_w' functions
* work as expected
*/
a = archive_write_new();
assertEqualInt(ARCHIVE_OK, archive_write_set_format_7zip(a));
assertEqualInt(ARCHIVE_OK,
archive_write_open_memory(a, buff, sizeof(buff), &used));
/* Part 1: file */
entry = archive_entry_new2(a);
archive_entry_copy_pathname_w(entry, L"\u8868.txt");
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_size(entry, 0);
assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
/* Part 2: directory */
archive_entry_clear(entry);
archive_entry_copy_pathname_w(entry, L"\u8868");
archive_entry_set_filetype(entry, AE_IFDIR);
archive_entry_set_size(entry, 0);
assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
/* Part 3: symlink */
archive_entry_clear(entry);
archive_entry_set_pathname(entry, "link.txt");
archive_entry_copy_symlink_w(entry, L"\u8868.txt");
archive_entry_set_filetype(entry, AE_IFLNK);
archive_entry_set_symlink_type(entry, AE_SYMLINK_TYPE_FILE);
archive_entry_set_size(entry, 0);
assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
/* NOTE: 7zip does not support hardlinks */
archive_entry_free(entry);
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
/* Ensure that the archive contents can be read properly */
/* NOTE: 7zip file contents are not in the order we wrote them! */
a = archive_read_new();
archive_read_support_format_all(a);
archive_read_support_filter_all(a);
assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7));
/* Read part 3: symlink */
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &entry));
assertEqualWString(L"\u8868.txt", archive_entry_symlink_w(entry));
/* Read part 1: file */
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &entry));
assertEqualWString(L"\u8868.txt", archive_entry_pathname_w(entry));
/* Read part 2: directory */
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &entry));
/* NOTE: Trailing slash added automatically for us */
assertEqualWString(L"\u8868/", archive_entry_pathname_w(entry));
archive_read_free(a);
#endif
}
@@ -287,7 +287,7 @@ DEFINE_TEST(test_acl_pax_posix1e)
failure("Basic ACLs shouldn't be stored as extended ACLs");
assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
failure("Basic ACLs should set mode to 0142, not %04o",
archive_entry_mode(ae)&0777);
(unsigned int)archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0142);
/* Second item has a few ACLs */
@@ -297,7 +297,7 @@ DEFINE_TEST(test_acl_pax_posix1e)
assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0142);
failure("Basic ACLs should set mode to 0142, not %04o",
archive_entry_mode(ae)&0777);
(unsigned int)archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0142);
/* Third item has pretty extensive ACLs */
@@ -307,7 +307,7 @@ DEFINE_TEST(test_acl_pax_posix1e)
assertEntryCompareAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0543);
failure("Basic ACLs should set mode to 0543, not %04o",
archive_entry_mode(ae)&0777);
(unsigned int)archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0543);
/* Fourth item has no ACLs */
@@ -315,7 +315,7 @@ DEFINE_TEST(test_acl_pax_posix1e)
failure("Basic ACLs shouldn't be stored as extended ACLs");
assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
failure("Basic ACLs should set mode to 0142, not %04o",
archive_entry_mode(ae)&0777);
(unsigned int)archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0142);
/* Close the archive. */
@@ -424,7 +424,7 @@ acl_flagset_to_bitmap(acl_flagset_t opaque_fs)
#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
if (flags & perms[i].machine)
#else
if (acl_get_flag_np(opaque_fs, perms[i].machine))
if (acl_get_flag_np(opaque_fs, (acl_flag_t)perms[i].machine))
#endif
flagset |= perms[i].portable;
return flagset;
@@ -772,7 +772,8 @@ compare_acls(
failure(" ACL entry %d missing from %s: "
"type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
marker[i], filename,
myacls[marker[i]].type, myacls[marker[i]].permset,
(unsigned int)myacls[marker[i]].type,
(unsigned int)myacls[marker[i]].permset,
myacls[marker[i]].tag, myacls[marker[i]].qual,
myacls[marker[i]].name);
assert(0); /* Record this as a failure. */
@@ -824,7 +825,7 @@ compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char
failure("ACL entry on file that shouldn't be there: "
"type=%#010x,permset=%#010x,tag=%d,qual=%d",
type,permset,tag,qual);
(unsigned int)type, (unsigned int)permset, tag, qual);
assert(matched == 1);
}
@@ -833,7 +834,8 @@ compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char
failure(" ACL entry %d missing from %s: "
"type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
marker[i], filename,
myacls[marker[i]].type, myacls[marker[i]].permset,
(unsigned int)myacls[marker[i]].type,
(unsigned int)myacls[marker[i]].permset,
myacls[marker[i]].tag, myacls[marker[i]].qual,
myacls[marker[i]].name);
assert(0); /* Record this as a failure. */
@@ -274,7 +274,8 @@ compare_acls(
for (i = 0; i < n; ++i) {
failure(" ACL entry missing from file: "
"type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
myacls[marker[i]].type, myacls[marker[i]].permset,
(unsigned int)myacls[marker[i]].type,
(unsigned int)myacls[marker[i]].permset,
myacls[marker[i]].tag, myacls[marker[i]].qual,
myacls[marker[i]].name);
assert(0); /* Record this as a failure. */
@@ -119,7 +119,7 @@ DEFINE_TEST(test_acl_posix1e)
failure("Basic ACLs shouldn't be stored as extended ACLs");
assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
failure("Basic ACLs should set mode to 0142, not %04o",
archive_entry_mode(ae)&0777);
(unsigned int)archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0142);
/* With any extended ACL entry, we should read back a full set. */
@@ -136,7 +136,7 @@ DEFINE_TEST(test_acl_posix1e)
assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0142);
failure("Basic ACLs should set mode to 0142, not %04o",
archive_entry_mode(ae)&0777);
(unsigned int)archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0142);
@@ -146,7 +146,7 @@ DEFINE_TEST(test_acl_posix1e)
assertEntryCompareAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]),
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0543);
failure("Basic ACLs should set mode to 0543, not %04o",
archive_entry_mode(ae)&0777);
(unsigned int)archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0543);
/*
@@ -157,7 +157,7 @@ DEFINE_TEST(test_acl_posix1e)
failure("Basic ACLs shouldn't be stored as extended ACLs");
assert(0 == archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
failure("Basic ACLs should set mode to 0142, not %04o",
archive_entry_mode(ae)&0777);
(unsigned int)archive_entry_mode(ae)&0777);
assert((archive_entry_mode(ae) & 0777) == 0142);
/*
@@ -132,7 +132,7 @@ static struct archive_test_acl_t acls1[] = {
ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" },
};
const char* acltext[] = {
static const char* acltext[] = {
"user::rwx\n"
"group::r-x\n"
"other::r-x\n"
@@ -25,8 +25,7 @@
#include "test.h"
#define __LIBARCHIVE_BUILD 1
#include "archive_getdate.h"
#define parse_date archive_parse_date
static void
test_newer_time(void)
@@ -102,27 +101,27 @@ test_newer_time_str(void)
/* Test1: Allow newer time. */
archive_entry_copy_pathname(ae, "file1");
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
t = parse_date(now, "1980/2/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should be excluded");
assertEqualInt(1, archive_match_time_excluded(m, ae));
assertEqualInt(1, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
t = parse_date(now, "1980/1/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should be excluded");
assertEqualInt(1, archive_match_time_excluded(m, ae));
assertEqualInt(1, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/2/1 0:0:1 UTC");
t = parse_date(now, "1980/2/1 0:0:1 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should not be excluded");
assertEqualInt(0, archive_match_time_excluded(m, ae));
assertEqualInt(0, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
t = parse_date(now, "1980/2/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 1);
archive_entry_set_ctime(ae, t, 0);
failure("Its mtime should be excluded");
@@ -143,20 +142,20 @@ test_newer_time_str(void)
"1980/2/1 0:0:0 UTC"));
archive_entry_copy_pathname(ae, "file1");
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
t = parse_date(now, "1980/2/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should not be excluded");
assertEqualInt(0, archive_match_time_excluded(m, ae));
assertEqualInt(0, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
t = parse_date(now, "1980/1/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should be excluded");
assertEqualInt(1, archive_match_time_excluded(m, ae));
assertEqualInt(1, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/2/1 0:0:1 UTC");
t = parse_date(now, "1980/2/1 0:0:1 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should not be excluded");
@@ -190,27 +189,27 @@ test_newer_time_str_w(void)
/* Test1: Allow newer time. */
archive_entry_copy_pathname(ae, "file1");
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
t = parse_date(now, "1980/2/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should be excluded");
assertEqualInt(1, archive_match_time_excluded(m, ae));
assertEqualInt(1, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
t = parse_date(now, "1980/1/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should be excluded");
assertEqualInt(1, archive_match_time_excluded(m, ae));
assertEqualInt(1, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/2/1 0:0:1 UTC");
t = parse_date(now, "1980/2/1 0:0:1 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should not be excluded");
assertEqualInt(0, archive_match_time_excluded(m, ae));
assertEqualInt(0, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
t = parse_date(now, "1980/2/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 1);
archive_entry_set_ctime(ae, t, 0);
failure("Its mtime should be excluded");
@@ -231,20 +230,20 @@ test_newer_time_str_w(void)
L"1980/2/1 0:0:0 UTC"));
archive_entry_copy_pathname(ae, "file1");
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
t = parse_date(now, "1980/2/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should not be excluded");
assertEqualInt(0, archive_match_time_excluded(m, ae));
assertEqualInt(0, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
t = parse_date(now, "1980/1/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should be excluded");
assertEqualInt(1, archive_match_time_excluded(m, ae));
assertEqualInt(1, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/2/1 0:0:1 UTC");
t = parse_date(now, "1980/2/1 0:0:1 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should not be excluded");
@@ -569,37 +568,37 @@ test_older_time_str(void)
ARCHIVE_MATCH_OLDER, "1980/2/1 0:0:0 UTC"));
archive_entry_copy_pathname(ae, "file1");
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
t = parse_date(now, "1980/2/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should be excluded");
assertEqualInt(1, archive_match_time_excluded(m, ae));
assertEqualInt(1, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
t = parse_date(now, "1980/1/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should not be excluded");
assertEqualInt(0, archive_match_time_excluded(m, ae));
assertEqualInt(0, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/3/1 0:0:0 UTC");
t = parse_date(now, "1980/3/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should be excluded");
assertEqualInt(1, archive_match_time_excluded(m, ae));
assertEqualInt(1, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/3/1 0:0:0 UTC");
t = parse_date(now, "1980/3/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
t = parse_date(now, "1980/1/1 0:0:0 UTC");
archive_entry_set_ctime(ae, t, 0);
failure("Its mtime should be excluded");
assertEqualInt(1, archive_match_time_excluded(m, ae));
assertEqualInt(1, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
t = parse_date(now, "1980/1/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
t = __archive_get_date(now, "1980/3/1 0:0:0 UTC");
t = parse_date(now, "1980/3/1 0:0:0 UTC");
archive_entry_set_ctime(ae, t, 0);
failure("Its ctime should be excluded");
assertEqualInt(1, archive_match_time_excluded(m, ae));
@@ -612,20 +611,20 @@ test_older_time_str(void)
"1980/2/1 0:0:0 UTC"));
archive_entry_copy_pathname(ae, "file1");
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
t = parse_date(now, "1980/2/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should not be excluded");
assertEqualInt(0, archive_match_time_excluded(m, ae));
assertEqualInt(0, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
t = parse_date(now, "1980/1/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should not be excluded");
assertEqualInt(0, archive_match_time_excluded(m, ae));
assertEqualInt(0, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/3/1 0:0:0 UTC");
t = parse_date(now, "1980/3/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should be excluded");
@@ -659,37 +658,37 @@ test_older_time_str_w(void)
ARCHIVE_MATCH_OLDER, L"1980/2/1 0:0:0 UTC"));
archive_entry_copy_pathname(ae, "file1");
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
t = parse_date(now, "1980/2/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should be excluded");
assertEqualInt(1, archive_match_time_excluded(m, ae));
assertEqualInt(1, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
t = parse_date(now, "1980/1/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should not be excluded");
assertEqualInt(0, archive_match_time_excluded(m, ae));
assertEqualInt(0, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/3/1 0:0:0 UTC");
t = parse_date(now, "1980/3/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should be excluded");
assertEqualInt(1, archive_match_time_excluded(m, ae));
assertEqualInt(1, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/3/1 0:0:0 UTC");
t = parse_date(now, "1980/3/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
t = parse_date(now, "1980/1/1 0:0:0 UTC");
archive_entry_set_ctime(ae, t, 0);
failure("Its mtime should be excluded");
assertEqualInt(1, archive_match_time_excluded(m, ae));
assertEqualInt(1, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
t = parse_date(now, "1980/1/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
t = __archive_get_date(now, "1980/3/1 0:0:0 UTC");
t = parse_date(now, "1980/3/1 0:0:0 UTC");
archive_entry_set_ctime(ae, t, 0);
failure("Its ctime should be excluded");
assertEqualInt(1, archive_match_time_excluded(m, ae));
@@ -702,20 +701,20 @@ test_older_time_str_w(void)
L"1980/2/1 0:0:0 UTC"));
archive_entry_copy_pathname(ae, "file1");
t = __archive_get_date(now, "1980/2/1 0:0:0 UTC");
t = parse_date(now, "1980/2/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should not be excluded");
assertEqualInt(0, archive_match_time_excluded(m, ae));
assertEqualInt(0, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/1/1 0:0:0 UTC");
t = parse_date(now, "1980/1/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should not be excluded");
assertEqualInt(0, archive_match_time_excluded(m, ae));
assertEqualInt(0, archive_match_excluded(m, ae));
t = __archive_get_date(now, "1980/3/1 0:0:0 UTC");
t = parse_date(now, "1980/3/1 0:0:0 UTC");
archive_entry_set_mtime(ae, t, 0);
archive_entry_set_ctime(ae, t, 0);
failure("Both Its mtime and ctime should be excluded");
@@ -26,16 +26,13 @@
#include <time.h>
#define __LIBARCHIVE_BUILD 1
#include "archive_getdate.h"
/*
* Verify that the getdate() function works.
* Verify that the archive_parse_date() function works.
*/
#define get_date __archive_get_date
#define get_date archive_parse_date
DEFINE_TEST(test_archive_getdate)
DEFINE_TEST(test_archive_parse_date)
{
time_t now = time(NULL);
@@ -84,5 +81,17 @@ DEFINE_TEST(test_archive_getdate)
/* "last tuesday" is one week before "tuesday" */
assertEqualInt(get_date(now, "last tuesday UTC"),
now - 6 * 24 * 60 * 60);
/* Unix epoch timestamps */
assertEqualInt(get_date(now, "@0"), 0);
assertEqualInt(get_date(now, "@100"), 100);
assertEqualInt(get_date(now, "@+100"), 100);
assertEqualInt(get_date(now, "@"), -1);
assertEqualInt(get_date(now, "@-"), -1);
assertEqualInt(get_date(now, "@+"), -1);
assertEqualInt(get_date(now, "@tenth"), -1);
assertEqualInt(get_date(now, "@100 tomorrow"), -1);
/* TODO: Lots more tests here. */
}
@@ -91,7 +91,7 @@ unicode_to_utf16be(char *p, uint32_t uc)
archive_be16enc(utf16+2, (uc & 0x3ff) + 0xDC00);
return (4);
} else {
archive_be16enc(utf16, uc);
archive_be16enc(utf16, (uint16_t)uc);
return (2);
}
}
@@ -118,7 +118,7 @@ unicode_to_utf16le(char *p, uint32_t uc)
archive_le16enc(utf16+2, (uc & 0x3ff) + 0xDC00);
return (4);
} else {
archive_le16enc(utf16, uc);
archive_le16enc(utf16, (uint16_t)uc);
return (2);
}
}
@@ -0,0 +1,224 @@
/*-
* Copyright (c) 2003-2024 Tim Kientzle
* 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(S) ``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(S) 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.
*/
#include "test.h"
/*
* Verify reading a GNU tar pax format archive with >8GB entry.
*
* Sample data created with GNU tar 1.35:
* $ dd if=/dev/zero of=test.bin bs=1048576 count=8192
* $ gnutar --format=posix -cvf test.tar test.bin
* $ hexdump -C -v test.tar | head -n 96
*/
static const unsigned char test_compat_gtar_large_data[] = {
/* 00000000 */ 0x2e, 0x2f, 0x50, 0x61, 0x78, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x2f, 0x74, 0x65, 0x73, /* |./PaxHeaders/tes| */
/* 00000010 */ 0x74, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |t.bin...........| */
/* 00000020 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000030 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000040 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000050 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000060 */ 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x36, 0x34, 0x34, 0x00, 0x30, 0x30, 0x30, 0x30, /* |....0000644.0000| */
/* 00000070 */ 0x30, 0x30, 0x30, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x30, 0x30, 0x30, /* |000.0000000.0000| */
/* 00000080 */ 0x30, 0x30, 0x30, 0x30, 0x31, 0x35, 0x35, 0x00, 0x31, 0x34, 0x37, 0x31, 0x31, 0x35, 0x36, 0x36, /* |0000155.14711566| */
/* 00000090 */ 0x30, 0x31, 0x33, 0x00, 0x30, 0x31, 0x31, 0x37, 0x35, 0x33, 0x00, 0x20, 0x78, 0x00, 0x00, 0x00, /* |013.011753. x...| */
/* 000000a0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000000b0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000000c0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000000d0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000000e0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000000f0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000100 */ 0x00, 0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |.ustar.00.......| */
/* 00000110 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000130 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000140 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000150 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000170 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000180 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000190 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000001a0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000001b0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000001c0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000001d0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000001e0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000001f0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000200 */ 0x31, 0x39, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3d, 0x38, 0x35, 0x38, 0x39, 0x39, 0x33, 0x34, 0x35, /* |19 size=85899345| */
/* 00000210 */ 0x39, 0x32, 0x0a, 0x33, 0x30, 0x20, 0x6d, 0x74, 0x69, 0x6d, 0x65, 0x3d, 0x31, 0x37, 0x33, 0x30, /* |92.30 mtime=1730| */
/* 00000220 */ 0x36, 0x30, 0x34, 0x30, 0x34, 0x33, 0x2e, 0x30, 0x34, 0x36, 0x38, 0x33, 0x33, 0x30, 0x31, 0x31, /* |604043.046833011| */
/* 00000230 */ 0x0a, 0x33, 0x30, 0x20, 0x61, 0x74, 0x69, 0x6d, 0x65, 0x3d, 0x31, 0x37, 0x33, 0x30, 0x36, 0x30, /* |.30 atime=173060| */
/* 00000240 */ 0x34, 0x30, 0x33, 0x39, 0x2e, 0x38, 0x30, 0x37, 0x30, 0x38, 0x31, 0x33, 0x31, 0x39, 0x0a, 0x33, /* |4039.807081319.3| */
/* 00000250 */ 0x30, 0x20, 0x63, 0x74, 0x69, 0x6d, 0x65, 0x3d, 0x31, 0x37, 0x33, 0x30, 0x36, 0x30, 0x34, 0x30, /* |0 ctime=17306040| */
/* 00000260 */ 0x34, 0x33, 0x2e, 0x30, 0x34, 0x36, 0x38, 0x33, 0x33, 0x30, 0x31, 0x31, 0x0a, 0x00, 0x00, 0x00, /* |43.046833011....| */
/* 00000270 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000280 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000290 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000002a0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000002b0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000002c0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000002d0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000002e0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000002f0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000300 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000310 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000320 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000330 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000340 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000350 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000360 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000370 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000380 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000390 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000003a0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000003b0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000003c0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000003d0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000003e0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000003f0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000400 */ 0x74, 0x65, 0x73, 0x74, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |test.bin........| */
/* 00000410 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000420 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000430 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000440 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000450 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000460 */ 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x36, 0x34, 0x34, 0x00, 0x30, 0x30, 0x30, 0x30, /* |....0000644.0000| */
/* 00000470 */ 0x37, 0x36, 0x35, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x34, 0x00, 0x30, 0x30, 0x30, 0x30, /* |765.0000024.0000| */
/* 00000480 */ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x31, 0x34, 0x37, 0x31, 0x31, 0x35, 0x36, 0x36, /* |0000000.14711566| */
/* 00000490 */ 0x30, 0x31, 0x33, 0x00, 0x30, 0x31, 0x31, 0x32, 0x33, 0x35, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, /* |013.011235. 0...| */
/* 000004a0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000004b0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000004c0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000004d0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000004e0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000004f0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000500 */ 0x00, 0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30, 0x74, 0x69, 0x6d, 0x00, 0x00, 0x00, 0x00, /* |.ustar.00tim....| */
/* 00000510 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000520 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x66, 0x66, 0x00, 0x00, /* |.........staff..| */
/* 00000530 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000540 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000550 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000560 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000570 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000580 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 00000590 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000005a0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000005b0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000005c0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000005d0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000005e0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
/* 000005f0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |................| */
};
/*
* Followed by 16777218 blocks, each consisting of 512 zeros:
* Entry is 8GB = 2^24 = 16777216 blocks
* Plus 2 zero blocks for end-of-archive
*/
struct my_reader {
const void *prefix;
int prefix_length;
int zero_blocks_remaining;
void *zero_block;
};
/*
* Custom reader returns first the prefix, then
* the expected number of zero blocks, then EOF.
*/
static ssize_t
myread(struct archive *a, void *client_data, const void **buff)
{
struct my_reader *reader = client_data;
(void)a; /* UNUSED */
if (reader->prefix != NULL) {
*buff = reader->prefix;
reader->prefix = NULL;
return reader->prefix_length;
} else if (reader->zero_blocks_remaining > 0) {
*buff = reader->zero_block;
reader->zero_blocks_remaining -= 1;
return 512;
} else {
return 0;
}
}
/*
* test_compat_gtar_large verifies that we can read
* the archive encoded above.
*/
DEFINE_TEST(test_compat_gtar_large)
{
struct archive *a;
struct archive_entry *ae;
struct my_reader reader = {
test_compat_gtar_large_data,
sizeof(test_compat_gtar_large_data),
16777218, /* 2^24 + 2 ; See above */
NULL
};
int r;
reader.zero_block = calloc(1, 512);
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(a, &reader, NULL, myread, NULL));
/* Read first entry. */
assertEqualIntA(a, ARCHIVE_OK, r = archive_read_next_header(a, &ae));
if (r != ARCHIVE_OK) {
archive_read_free(a);
return;
}
assertEqualString("test.bin", archive_entry_pathname(ae));
assertEqualInt(1730604043, archive_entry_mtime(ae));
assertEqualInt(501, archive_entry_uid(ae));
assertEqualString("tim", archive_entry_uname(ae));
assertEqualInt(20, archive_entry_gid(ae));
assertEqualString("staff", archive_entry_gname(ae));
assertEqualInt(0100644, archive_entry_mode(ae));
assertEqualInt(8589934592LL, archive_entry_size(ae));
/* TODO: Read and verify contents: 8GB of zeros */
/* Verify the end-of-archive. */
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
/* Verify that the format detection worked. */
assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE);
assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE);
/* Verify that the reader actually read to the end of data */
assertEqualInt(reader.zero_blocks_remaining, 0);
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
free(reader.zero_block);
}
Loaded 100 of 3275 files, more files were not shown because too many files have changed in this diff. Show more