From 7f82f563527da836d05ab712702be3840dd55eb2 Mon Sep 17 00:00:00 2001 From: Wong Hoi Sing Edison Date: Wed, 19 Jul 2023 15:31:49 +0800 Subject: [PATCH] alvistack/v3.7.0 git clean -xdf ./build/autogen.sh && ./configure && make clean && git clean -xdf tar zcvf ../libarchive_3.7.0.orig.tar.gz --exclude=.git . debuild -uc -us cp libarchive.spec ../libarchive_3.7.0-1.spec cp ../libarchive*3.7.0*.{gz,xz,spec,dsc} /osc/home\:alvistack/libarchive-libarchive-3.7.0/ rm -rf ../libarchive*3.7.0*.* See https://github.com/libarchive/libarchive/pull/1723 See https://github.com/libarchive/libarchive/issues/1919 See https://github.com/libarchive/libarchive/issues/1920 See https://github.com/libarchive/libarchive/issues/1921 Signed-off-by: Wong Hoi Sing Edison --- build/pkgconfig/libarchive.pc.in | 1 - configure.ac | 8 +- debian/.gitignore | 9 + debian/changelog | 5 + debian/control | 136 ++++ debian/copyright | 21 + debian/libarchive-dev.install | 6 + debian/libarchive-dev.lintian-overrides | 4 + debian/libarchive-tools.install | 2 + debian/libarchive-tools.lintian-overrides | 3 + debian/libarchive13.install | 1 + debian/libarchive13.lintian-overrides | 3 + debian/libarchive13.symbols | 424 +++++++++++ debian/rules | 26 + debian/source/format | 1 + debian/source/lintian-overrides | 4 + libarchive.spec | 267 +++++++ unzip/bsdunzip.c | 44 +- unzip/la_queue.h | 840 ++++++++++++++++++++++ 19 files changed, 1795 insertions(+), 10 deletions(-) create mode 100644 debian/.gitignore create mode 100644 debian/changelog create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/libarchive-dev.install create mode 100644 debian/libarchive-dev.lintian-overrides create mode 100644 debian/libarchive-tools.install create mode 100644 debian/libarchive-tools.lintian-overrides create mode 100644 debian/libarchive13.install create mode 100644 debian/libarchive13.lintian-overrides create mode 100644 debian/libarchive13.symbols create mode 100755 debian/rules create mode 100644 debian/source/format create mode 100644 debian/source/lintian-overrides create mode 100644 libarchive.spec create mode 100644 unzip/la_queue.h diff --git a/build/pkgconfig/libarchive.pc.in b/build/pkgconfig/libarchive.pc.in index 1f51e77f16..4b631e635c 100644 --- a/build/pkgconfig/libarchive.pc.in +++ b/build/pkgconfig/libarchive.pc.in @@ -10,4 +10,3 @@ Cflags: -I${includedir} Cflags.private: -DLIBARCHIVE_STATIC Libs: -L${libdir} -larchive Libs.private: @LIBS@ -Requires.private: @LIBSREQUIRED@ diff --git a/configure.ac b/configure.ac index 7f5dbdf3b9..aefe4feb33 100644 --- a/configure.ac +++ b/configure.ac @@ -12,7 +12,7 @@ m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S()) m4_define([BSDCPIO_VERSION_S],LIBARCHIVE_VERSION_S()) m4_define([BSDCAT_VERSION_S],LIBARCHIVE_VERSION_S()) -AC_PREREQ([2.71]) +AC_PREREQ([2.69]) # # Now starts the "real" configure script. @@ -429,9 +429,6 @@ if test "x$with_iconv" != "xno"; then AC_CHECK_HEADERS([localcharset.h]) am_save_LIBS="$LIBS" LIBS="${LIBS} ${LIBICONV}" - if test -n "$LIBICONV"; then - LIBSREQUIRED="$LIBSREQUIRED${LIBSREQUIRED:+ }iconv" - fi AC_CHECK_FUNCS([locale_charset]) LIBS="${am_save_LIBS}" if test "x$ac_cv_func_locale_charset" != "xyes"; then @@ -1297,7 +1294,6 @@ fi if test "x$with_openssl" != "xno"; then AC_CHECK_HEADERS([openssl/evp.h]) saved_LIBS=$LIBS - LIBSREQUIRED="$LIBSREQUIRED${LIBSREQUIRED:+ }libcrypto" AC_CHECK_LIB(crypto,OPENSSL_config) CRYPTO_CHECK(MD5, OPENSSL, md5) CRYPTO_CHECK(RMD160, OPENSSL, rmd160) @@ -1308,8 +1304,6 @@ if test "x$with_openssl" != "xno"; then AC_CHECK_FUNCS([PKCS5_PBKDF2_HMAC_SHA1]) fi -AC_SUBST(LIBSREQUIRED) - # Probe libmd AFTER OpenSSL/libcrypto. # The two are incompatible and OpenSSL is more complete. AC_CHECK_HEADERS([md5.h ripemd.h sha.h sha256.h sha512.h]) diff --git a/debian/.gitignore b/debian/.gitignore new file mode 100644 index 0000000000..dcfb827afa --- /dev/null +++ b/debian/.gitignore @@ -0,0 +1,9 @@ +*.substvars +*debhelper* +.debhelper +autoreconf.* +files +libarchive-dev +libarchive-tools +libarchive13 +tmp diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000000..26abfcae58 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +libarchive (100:3.7.0-1) UNRELEASED; urgency=medium + + * https://github.com/libarchive/libarchive/releases/tag/v3.7.0 + + -- Wong Hoi Sing Edison Wed, 19 Jul 2023 12:38:16 +0800 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000000..0eb25d6d50 --- /dev/null +++ b/debian/control @@ -0,0 +1,136 @@ +Source: libarchive +Section: libs +Priority: optional +Standards-Version: 4.5.0 +Maintainer: Wong Hoi Sing Edison +Homepage: https://github.com/libarchive/libarchive/tags +Vcs-Browser: https://github.com/alvistack/libarchive-libarchive +Vcs-Git: https://github.com/alvistack/libarchive-libarchive.git +Build-Depends: + debhelper, + debhelper-compat (= 10), + libacl1-dev, + libbz2-dev, + libext2fs-dev, + liblz4-dev, + liblzma-dev, + libssl-dev, + libxml2-dev, + libzstd-dev, + locales | locales-all , + nettle-dev, + pkg-config, + sharutils , + zlib1g-dev, + +Package: libarchive-dev +Section: libdevel +Architecture: amd64 +Description: Multi-format archive and compression library (development files) + The libarchive library provides a flexible interface for reading and writing + archives in various formats such as tar and cpio. libarchive also supports + reading and writing archives compressed using various compression filters such + as gzip and bzip2. The library is inherently stream-oriented; readers serially + iterate through the archive, writers serially add things to the archive. + . + Archive formats supported are: + . + * tar (read and write, including GNU extensions) + * pax (read and write, including GNU and star extensions) + * cpio (read and write, including odc and newc variants) + * iso9660 (read and write, including Joliet and Rockridge extensions, with + some limitations) + * zip (read only, with some limitations, uses zlib) + * mtree (read and write) + * shar (write only) + * ar (read and write, including BSD and GNU/SysV variants) + * empty (read only; in particular, note that no other format will accept an + empty file) + * raw (read only) + * xar (read only) + * rar (read only, with some limitations) + * 7zip (read and write, with some limitations) + . + Filters supported are: + . + * gzip (read and write, uses zlib) + * bzip2 (read and write, uses bzlib) + * compress (read and write, uses an internal implementation) + * uudecode (read only) + * separate command-line compressors with fixed-signature auto-detection + * xz and lzma (read and write using liblzma) + * zstandard (read and write using libzstd) + . + This package provides the files necessary for development with libarchive. +Depends: + ${shlibs:Depends}, + ${misc:Depends}, + libarchive13 (= ${source:Version}), + +Package: libarchive13 +Architecture: amd64 +Description: Multi-format archive and compression library (shared library) + The libarchive library provides a flexible interface for reading and writing + archives in various formats such as tar and cpio. libarchive also supports + reading and writing archives compressed using various compression filters such + as gzip and bzip2. The library is inherently stream-oriented; readers serially + iterate through the archive, writers serially add things to the archive. + . + Archive formats supported are: + . + * tar (read and write, including GNU extensions) + * pax (read and write, including GNU and star extensions) + * cpio (read and write, including odc and newc variants) + * iso9660 (read and write, including Joliet and Rockridge extensions, with + some limitations) + * zip (read only, with some limitations, uses zlib) + * mtree (read and write) + * shar (write only) + * ar (read and write, including BSD and GNU/SysV variants) + * empty (read only; in particular, note that no other format will accept an + empty file) + * raw (read only) + * xar (read only) + * rar (read only, with some limitations) + * 7zip (read and write, with some limitations) + . + Filters supported are: + . + * gzip (read and write, uses zlib) + * bzip2 (read and write, uses bzlib) + * compress (read and write, uses an internal implementation) + * uudecode (read only) + * separate command-line compressors with fixed-signature auto-detection + * xz and lzma (read and write using liblzma) + * zstandard (read and write using libzstd) + . + This package provides the libarchive shared library. +Depends: + ${misc:Depends}, + ${shlibs:Depends}, +Suggests: + lrzip, + +Package: libarchive-tools +Architecture: amd64 +Section: utils +Description: FreeBSD implementations of 'tar' and 'cpio' and other archive tools + This package contains several command-line tools based on the libarchive + library. + . + The bsdtar program is the default system 'tar' program used on FreeBSD. bsdtar + uses the libarchive library as a backend which does all of the work for reading + and writing archives in various formats. + . + The bsdcpio program is the default system 'cpio' program used on FreeBSD. + bsdcpio uses the libarchive library as a backend which does all of the work for + reading and writing archives in various formats. + . + The bsdcat program reads archived data from files or from its standard input + and uses the libarchive library to decompresses it to its standard output. + It may be used for viewing the contents of archives or for passing it to other + tools for further processing. +Depends: + ${misc:Depends}, + ${shlibs:Depends}, + libarchive13 (= ${source:Version}), diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000000..dcb9a24485 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,21 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ + +Files: debian/* +Copyright: 2023 Wong Hoi Sing Edison +License: Apache-2.0 + +License: Apache-2.0 + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + . + http://www.apache.org/licenses/LICENSE-2.0 + . + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + . + The complete text of the Apache version 2.0 license + can be found in "/usr/share/common-licenses/Apache-2.0". diff --git a/debian/libarchive-dev.install b/debian/libarchive-dev.install new file mode 100644 index 0000000000..d1014778cf --- /dev/null +++ b/debian/libarchive-dev.install @@ -0,0 +1,6 @@ +usr/include +usr/lib/*/lib*.a +usr/lib/*/lib*.so +usr/lib/*/pkgconfig/* +usr/share/man/man3/* +usr/share/man/man5/* diff --git a/debian/libarchive-dev.lintian-overrides b/debian/libarchive-dev.lintian-overrides new file mode 100644 index 0000000000..7bb1a86578 --- /dev/null +++ b/debian/libarchive-dev.lintian-overrides @@ -0,0 +1,4 @@ +libarchive-dev: copyright-without-copyright-notice +libarchive-dev: groff-message +libarchive-dev: initial-upload-closes-no-bugs +libarchive-dev: zero-byte-file-in-doc-directory diff --git a/debian/libarchive-tools.install b/debian/libarchive-tools.install new file mode 100644 index 0000000000..68671debc0 --- /dev/null +++ b/debian/libarchive-tools.install @@ -0,0 +1,2 @@ +usr/bin/* +usr/share/man/man1/* diff --git a/debian/libarchive-tools.lintian-overrides b/debian/libarchive-tools.lintian-overrides new file mode 100644 index 0000000000..3ee3a08a15 --- /dev/null +++ b/debian/libarchive-tools.lintian-overrides @@ -0,0 +1,3 @@ +libarchive-tools: copyright-without-copyright-notice +libarchive-tools: initial-upload-closes-no-bugs +libarchive-tools: zero-byte-file-in-doc-directory diff --git a/debian/libarchive13.install b/debian/libarchive13.install new file mode 100644 index 0000000000..3ddde58419 --- /dev/null +++ b/debian/libarchive13.install @@ -0,0 +1 @@ +usr/lib/*/lib*.so.* diff --git a/debian/libarchive13.lintian-overrides b/debian/libarchive13.lintian-overrides new file mode 100644 index 0000000000..ea16b94edc --- /dev/null +++ b/debian/libarchive13.lintian-overrides @@ -0,0 +1,3 @@ +libarchive13: copyright-without-copyright-notice +libarchive13: initial-upload-closes-no-bugs +libarchive13: zero-byte-file-in-doc-directory diff --git a/debian/libarchive13.symbols b/debian/libarchive13.symbols new file mode 100644 index 0000000000..31c1cd72af --- /dev/null +++ b/debian/libarchive13.symbols @@ -0,0 +1,424 @@ +libarchive.so.13 libarchive13 #MINVER# +* Build-Depends-Package: libarchive-dev +# these optional symbols should be removed once libarchive stops leaking private symbols, see https://github.com/libarchive/libarchive/pull/738 + archive_bzlib_version@Base 3.2.1 + archive_clear_error@Base 3.0.4 + archive_compression@Base 3.0.4 + archive_compression_name@Base 3.0.4 + archive_copy_error@Base 3.0.4 + archive_entry_acl@Base 3.0.4 + archive_entry_acl_add_entry@Base 3.0.4 + archive_entry_acl_add_entry_w@Base 3.0.4 + archive_entry_acl_clear@Base 3.0.4 + archive_entry_acl_count@Base 3.0.4 + archive_entry_acl_from_text@Base 3.3.3 + archive_entry_acl_from_text_w@Base 3.3.3 + archive_entry_acl_next@Base 3.0.4 + archive_entry_acl_reset@Base 3.0.4 + archive_entry_acl_text@Base 3.0.4 + archive_entry_acl_text_w@Base 3.0.4 + archive_entry_acl_to_text@Base 3.3.3 + archive_entry_acl_to_text_w@Base 3.3.3 + archive_entry_acl_types@Base 3.3.3 + archive_entry_atime@Base 3.0.4 + archive_entry_atime_is_set@Base 3.0.4 + archive_entry_atime_nsec@Base 3.0.4 + archive_entry_birthtime@Base 3.0.4 + archive_entry_birthtime_is_set@Base 3.0.4 + archive_entry_birthtime_nsec@Base 3.0.4 + archive_entry_clear@Base 3.0.4 + archive_entry_clone@Base 3.0.4 + archive_entry_copy_fflags_text@Base 3.0.4 + archive_entry_copy_fflags_text_w@Base 3.0.4 + archive_entry_copy_gname@Base 3.0.4 + archive_entry_copy_gname_w@Base 3.0.4 + archive_entry_copy_hardlink@Base 3.0.4 + archive_entry_copy_hardlink_w@Base 3.0.4 + archive_entry_copy_link@Base 3.0.4 + archive_entry_copy_link_w@Base 3.0.4 + archive_entry_copy_mac_metadata@Base 3.0.4 + archive_entry_copy_pathname@Base 3.0.4 + archive_entry_copy_pathname_w@Base 3.0.4 + archive_entry_copy_sourcepath@Base 3.0.4 + archive_entry_copy_sourcepath_w@Base 3.0.4 + archive_entry_copy_stat@Base 3.0.4 + archive_entry_copy_symlink@Base 3.0.4 + archive_entry_copy_symlink_w@Base 3.0.4 + archive_entry_copy_uname@Base 3.0.4 + archive_entry_copy_uname_w@Base 3.0.4 + archive_entry_ctime@Base 3.0.4 + archive_entry_ctime_is_set@Base 3.0.4 + archive_entry_ctime_nsec@Base 3.0.4 + archive_entry_dev@Base 3.0.4 + archive_entry_dev_is_set@Base 3.0.4 + archive_entry_devmajor@Base 3.0.4 + archive_entry_devminor@Base 3.0.4 + archive_entry_digest@Base 3.5.0 + archive_entry_fflags@Base 3.0.4 + archive_entry_fflags_text@Base 3.0.4 + archive_entry_filetype@Base 3.0.4 + archive_entry_free@Base 3.0.4 + archive_entry_gid@Base 3.0.4 + archive_entry_gname@Base 3.0.4 + archive_entry_gname_utf8@Base 3.2.1 + archive_entry_gname_w@Base 3.0.4 + archive_entry_hardlink@Base 3.0.4 + archive_entry_hardlink_utf8@Base 3.2.1 + archive_entry_hardlink_w@Base 3.0.4 + archive_entry_ino64@Base 3.0.4 + archive_entry_ino@Base 3.0.4 + archive_entry_ino_is_set@Base 3.0.4 + archive_entry_is_data_encrypted@Base 3.2.1 + archive_entry_is_encrypted@Base 3.2.1 + archive_entry_is_metadata_encrypted@Base 3.2.1 + archive_entry_linkify@Base 3.0.4 + archive_entry_linkresolver_free@Base 3.0.4 + archive_entry_linkresolver_new@Base 3.0.4 + archive_entry_linkresolver_set_strategy@Base 3.0.4 + archive_entry_mac_metadata@Base 3.0.4 + archive_entry_mode@Base 3.0.4 + archive_entry_mtime@Base 3.0.4 + archive_entry_mtime_is_set@Base 3.0.4 + archive_entry_mtime_nsec@Base 3.0.4 + archive_entry_new2@Base 3.0.4 + archive_entry_new@Base 3.0.4 + archive_entry_nlink@Base 3.0.4 + archive_entry_partial_links@Base 3.0.4 + archive_entry_pathname@Base 3.0.4 + archive_entry_pathname_utf8@Base 3.2.1 + archive_entry_pathname_w@Base 3.0.4 + archive_entry_perm@Base 3.0.4 + archive_entry_rdev@Base 3.0.4 + archive_entry_rdevmajor@Base 3.0.4 + archive_entry_rdevminor@Base 3.0.4 + archive_entry_set_atime@Base 3.0.4 + archive_entry_set_birthtime@Base 3.0.4 + archive_entry_set_ctime@Base 3.0.4 + archive_entry_set_dev@Base 3.0.4 + archive_entry_set_devmajor@Base 3.0.4 + archive_entry_set_devminor@Base 3.0.4 + archive_entry_set_fflags@Base 3.0.4 + archive_entry_set_filetype@Base 3.0.4 + archive_entry_set_gid@Base 3.0.4 + archive_entry_set_gname@Base 3.0.4 + archive_entry_set_gname_utf8@Base 3.2.1 + archive_entry_set_hardlink@Base 3.0.4 + archive_entry_set_hardlink_utf8@Base 3.2.1 + archive_entry_set_ino64@Base 3.0.4 + archive_entry_set_ino@Base 3.0.4 + archive_entry_set_is_data_encrypted@Base 3.2.1 + archive_entry_set_is_metadata_encrypted@Base 3.2.1 + archive_entry_set_link@Base 3.0.4 + archive_entry_set_link_utf8@Base 3.2.1 + archive_entry_set_mode@Base 3.0.4 + archive_entry_set_mtime@Base 3.0.4 + archive_entry_set_nlink@Base 3.0.4 + archive_entry_set_pathname@Base 3.0.4 + archive_entry_set_pathname_utf8@Base 3.2.1 + archive_entry_set_perm@Base 3.0.4 + archive_entry_set_rdev@Base 3.0.4 + archive_entry_set_rdevmajor@Base 3.0.4 + archive_entry_set_rdevminor@Base 3.0.4 + archive_entry_set_size@Base 3.0.4 + archive_entry_set_symlink@Base 3.0.4 + archive_entry_set_symlink_type@Base 3.4.0 + archive_entry_set_symlink_utf8@Base 3.2.1 + archive_entry_set_uid@Base 3.0.4 + archive_entry_set_uname@Base 3.0.4 + archive_entry_set_uname_utf8@Base 3.2.1 + archive_entry_size@Base 3.0.4 + archive_entry_size_is_set@Base 3.0.4 + archive_entry_sourcepath@Base 3.0.4 + archive_entry_sourcepath_w@Base 3.0.4 + archive_entry_sparse_add_entry@Base 3.0.4 + archive_entry_sparse_clear@Base 3.0.4 + archive_entry_sparse_count@Base 3.0.4 + archive_entry_sparse_next@Base 3.0.4 + archive_entry_sparse_reset@Base 3.0.4 + archive_entry_stat@Base 3.0.4 + archive_entry_strmode@Base 3.0.4 + archive_entry_symlink@Base 3.0.4 + archive_entry_symlink_type@Base 3.4.0 + archive_entry_symlink_utf8@Base 3.2.1 + archive_entry_symlink_w@Base 3.0.4 + archive_entry_uid@Base 3.0.4 + archive_entry_uname@Base 3.0.4 + archive_entry_uname_utf8@Base 3.2.1 + archive_entry_uname_w@Base 3.0.4 + archive_entry_unset_atime@Base 3.0.4 + archive_entry_unset_birthtime@Base 3.0.4 + archive_entry_unset_ctime@Base 3.0.4 + archive_entry_unset_mtime@Base 3.0.4 + archive_entry_unset_size@Base 3.0.4 + archive_entry_update_gname_utf8@Base 3.0.4 + archive_entry_update_hardlink_utf8@Base 3.0.4 + archive_entry_update_link_utf8@Base 3.0.4 + archive_entry_update_pathname_utf8@Base 3.0.4 + archive_entry_update_symlink_utf8@Base 3.0.4 + archive_entry_update_uname_utf8@Base 3.0.4 + archive_entry_xattr_add_entry@Base 3.0.4 + archive_entry_xattr_clear@Base 3.0.4 + archive_entry_xattr_count@Base 3.0.4 + archive_entry_xattr_next@Base 3.0.4 + archive_entry_xattr_reset@Base 3.0.4 + archive_errno@Base 3.0.4 + archive_error_string@Base 3.0.4 + archive_file_count@Base 3.0.4 + archive_filter_bytes@Base 3.0.4 + archive_filter_code@Base 3.0.4 + archive_filter_count@Base 3.0.4 + archive_filter_name@Base 3.0.4 + archive_format@Base 3.0.4 + archive_format_name@Base 3.0.4 + archive_free@Base 3.2.1 + archive_liblz4_version@Base 3.2.1 + archive_liblzma_version@Base 3.2.1 + archive_libzstd_version@Base 3.3.3 + archive_match_exclude_entry@Base 3.0.4 + archive_match_exclude_pattern@Base 3.0.4 + archive_match_exclude_pattern_from_file@Base 3.0.4 + archive_match_exclude_pattern_from_file_w@Base 3.0.4 + archive_match_exclude_pattern_w@Base 3.0.4 + archive_match_excluded@Base 3.0.4 + archive_match_free@Base 3.0.4 + archive_match_include_date@Base 3.0.4 + archive_match_include_date_w@Base 3.0.4 + archive_match_include_file_time@Base 3.0.4 + archive_match_include_file_time_w@Base 3.0.4 + archive_match_include_gid@Base 3.0.4 + archive_match_include_gname@Base 3.0.4 + archive_match_include_gname_w@Base 3.0.4 + archive_match_include_pattern@Base 3.0.4 + archive_match_include_pattern_from_file@Base 3.0.4 + archive_match_include_pattern_from_file_w@Base 3.0.4 + archive_match_include_pattern_w@Base 3.0.4 + archive_match_include_time@Base 3.0.4 + archive_match_include_uid@Base 3.0.4 + archive_match_include_uname@Base 3.0.4 + archive_match_include_uname_w@Base 3.0.4 + archive_match_new@Base 3.0.4 + archive_match_owner_excluded@Base 3.0.4 + archive_match_path_excluded@Base 3.0.4 + archive_match_path_unmatched_inclusions@Base 3.0.4 + archive_match_path_unmatched_inclusions_next@Base 3.0.4 + archive_match_path_unmatched_inclusions_next_w@Base 3.0.4 + archive_match_set_inclusion_recursion@Base 3.4.0 + archive_match_time_excluded@Base 3.0.4 + archive_position_compressed@Base 3.0.4 + archive_position_uncompressed@Base 3.0.4 + archive_read_add_callback_data@Base 3.1.2 + archive_read_add_passphrase@Base 3.2.1 + archive_read_append_callback_data@Base 3.1.2 + archive_read_append_filter@Base 3.1.2 + archive_read_append_filter_program@Base 3.1.2 + archive_read_append_filter_program_signature@Base 3.1.2 + archive_read_close@Base 3.0.4 + archive_read_data@Base 3.0.4 + archive_read_data_block@Base 3.0.4 + archive_read_data_into_fd@Base 3.0.4 + archive_read_data_skip@Base 3.0.4 + archive_read_disk_can_descend@Base 3.0.4 + archive_read_disk_current_filesystem@Base 3.0.4 + archive_read_disk_current_filesystem_is_remote@Base 3.0.4 + archive_read_disk_current_filesystem_is_synthetic@Base 3.0.4 + archive_read_disk_descend@Base 3.0.4 + archive_read_disk_entry_from_file@Base 3.0.4 + archive_read_disk_gname@Base 3.0.4 + archive_read_disk_new@Base 3.0.4 + archive_read_disk_open@Base 3.0.4 + archive_read_disk_open_w@Base 3.0.4 + archive_read_disk_set_atime_restored@Base 3.0.4 + archive_read_disk_set_behavior@Base 3.0.4 + archive_read_disk_set_gname_lookup@Base 3.0.4 + archive_read_disk_set_matching@Base 3.0.4 + archive_read_disk_set_metadata_filter_callback@Base 3.0.4 + archive_read_disk_set_standard_lookup@Base 3.0.4 + archive_read_disk_set_symlink_hybrid@Base 3.0.4 + archive_read_disk_set_symlink_logical@Base 3.0.4 + archive_read_disk_set_symlink_physical@Base 3.0.4 + archive_read_disk_set_uname_lookup@Base 3.0.4 + archive_read_disk_uname@Base 3.0.4 + archive_read_extract2@Base 3.0.4 + archive_read_extract@Base 3.0.4 + archive_read_extract_set_progress_callback@Base 3.0.4 + archive_read_extract_set_skip_file@Base 3.0.4 + archive_read_finish@Base 3.0.4 + archive_read_format_capabilities@Base 3.2.1 + archive_read_free@Base 3.0.4 + archive_read_has_encrypted_entries@Base 3.2.1 + archive_read_header_position@Base 3.0.4 + archive_read_new@Base 3.0.4 + archive_read_next_header2@Base 3.0.4 + archive_read_next_header@Base 3.0.4 + archive_read_open1@Base 3.0.4 + archive_read_open2@Base 3.0.4 + archive_read_open@Base 3.0.4 + archive_read_open_FILE@Base 3.0.4 + archive_read_open_fd@Base 3.0.4 + archive_read_open_file@Base 3.0.4 + archive_read_open_filename@Base 3.0.4 + archive_read_open_filename_w@Base 3.0.4 + archive_read_open_filenames@Base 3.1.2 + archive_read_open_memory2@Base 3.0.4 + archive_read_open_memory@Base 3.0.4 + archive_read_prepend_callback_data@Base 3.1.2 + archive_read_set_callback_data2@Base 3.1.2 + archive_read_set_callback_data@Base 3.0.4 + archive_read_set_close_callback@Base 3.0.4 + archive_read_set_filter_option@Base 3.0.4 + archive_read_set_format@Base 3.1.2 + archive_read_set_format_option@Base 3.0.4 + archive_read_set_open_callback@Base 3.0.4 + archive_read_set_option@Base 3.0.4 + archive_read_set_options@Base 3.0.4 + archive_read_set_passphrase_callback@Base 3.2.1 + archive_read_set_read_callback@Base 3.0.4 + archive_read_set_seek_callback@Base 3.0.4 + archive_read_set_skip_callback@Base 3.0.4 + archive_read_set_switch_callback@Base 3.1.2 + archive_read_support_compression_all@Base 3.0.4 + archive_read_support_compression_bzip2@Base 3.0.4 + archive_read_support_compression_compress@Base 3.0.4 + archive_read_support_compression_gzip@Base 3.0.4 + archive_read_support_compression_lzip@Base 3.0.4 + archive_read_support_compression_lzma@Base 3.0.4 + archive_read_support_compression_none@Base 3.0.4 + archive_read_support_compression_program@Base 3.0.4 + archive_read_support_compression_program_signature@Base 3.0.4 + archive_read_support_compression_rpm@Base 3.0.4 + archive_read_support_compression_uu@Base 3.0.4 + archive_read_support_compression_xz@Base 3.0.4 + archive_read_support_filter_all@Base 3.0.4 + archive_read_support_filter_by_code@Base 3.5.0 + archive_read_support_filter_bzip2@Base 3.0.4 + archive_read_support_filter_compress@Base 3.0.4 + archive_read_support_filter_grzip@Base 3.1.2 + archive_read_support_filter_gzip@Base 3.0.4 + archive_read_support_filter_lrzip@Base 3.1.2 + archive_read_support_filter_lz4@Base 3.2.1 + archive_read_support_filter_lzip@Base 3.0.4 + archive_read_support_filter_lzma@Base 3.0.4 + archive_read_support_filter_lzop@Base 3.1.2 + archive_read_support_filter_none@Base 3.0.4 + archive_read_support_filter_program@Base 3.0.4 + archive_read_support_filter_program_signature@Base 3.0.4 + archive_read_support_filter_rpm@Base 3.0.4 + archive_read_support_filter_uu@Base 3.0.4 + archive_read_support_filter_xz@Base 3.0.4 + archive_read_support_filter_zstd@Base 3.3.3 + archive_read_support_format_7zip@Base 3.0.4 + archive_read_support_format_all@Base 3.0.4 + archive_read_support_format_ar@Base 3.0.4 + archive_read_support_format_by_code@Base 3.0.4 + archive_read_support_format_cab@Base 3.0.4 + archive_read_support_format_cpio@Base 3.0.4 + archive_read_support_format_empty@Base 3.0.4 + archive_read_support_format_gnutar@Base 3.0.4 + archive_read_support_format_iso9660@Base 3.0.4 + archive_read_support_format_lha@Base 3.0.4 + archive_read_support_format_mtree@Base 3.0.4 + archive_read_support_format_rar5@Base 3.4.0 + archive_read_support_format_rar@Base 3.0.4 + archive_read_support_format_raw@Base 3.0.4 + archive_read_support_format_tar@Base 3.0.4 + archive_read_support_format_warc@Base 3.2.1 + archive_read_support_format_xar@Base 3.0.4 + archive_read_support_format_zip@Base 3.0.4 + archive_read_support_format_zip_seekable@Base 3.0.4 + archive_read_support_format_zip_streamable@Base 3.0.4 + archive_seek_data@Base 3.1.2 + archive_set_error@Base 3.0.4 + archive_utility_string_sort@Base 3.2.1 + archive_version_details@Base 3.2.1 + archive_version_number@Base 3.0.4 + archive_version_string@Base 3.0.4 + archive_write_add_filter@Base 3.0.4 + archive_write_add_filter_b64encode@Base 3.1.2 + archive_write_add_filter_by_name@Base 3.1.2 + archive_write_add_filter_bzip2@Base 3.0.4 + archive_write_add_filter_compress@Base 3.0.4 + archive_write_add_filter_grzip@Base 3.1.2 + archive_write_add_filter_gzip@Base 3.0.4 + archive_write_add_filter_lrzip@Base 3.1.2 + archive_write_add_filter_lz4@Base 3.2.1 + archive_write_add_filter_lzip@Base 3.0.4 + archive_write_add_filter_lzma@Base 3.0.4 + archive_write_add_filter_lzop@Base 3.1.2 + archive_write_add_filter_none@Base 3.0.4 + archive_write_add_filter_program@Base 3.0.4 + archive_write_add_filter_uuencode@Base 3.1.2 + archive_write_add_filter_xz@Base 3.0.4 + archive_write_add_filter_zstd@Base 3.3.3 + archive_write_close@Base 3.0.4 + archive_write_data@Base 3.0.4 + archive_write_data_block@Base 3.0.4 + archive_write_disk_gid@Base 3.0.4 + archive_write_disk_new@Base 3.0.4 + archive_write_disk_set_group_lookup@Base 3.0.4 + archive_write_disk_set_options@Base 3.0.4 + archive_write_disk_set_skip_file@Base 3.0.4 + archive_write_disk_set_standard_lookup@Base 3.0.4 + archive_write_disk_set_user_lookup@Base 3.0.4 + archive_write_disk_uid@Base 3.0.4 + archive_write_fail@Base 3.1.2 + archive_write_finish@Base 3.0.4 + archive_write_finish_entry@Base 3.0.4 + archive_write_free@Base 3.0.4 + archive_write_get_bytes_in_last_block@Base 3.0.4 + archive_write_get_bytes_per_block@Base 3.0.4 + archive_write_header@Base 3.0.4 + archive_write_new@Base 3.0.4 + archive_write_open2@Base 3.5.0 + archive_write_open@Base 3.0.4 + archive_write_open_FILE@Base 3.0.4 + archive_write_open_fd@Base 3.0.4 + archive_write_open_file@Base 3.0.4 + archive_write_open_filename@Base 3.0.4 + archive_write_open_filename_w@Base 3.0.4 + archive_write_open_memory@Base 3.0.4 + archive_write_set_bytes_in_last_block@Base 3.0.4 + archive_write_set_bytes_per_block@Base 3.0.4 + archive_write_set_compression_bzip2@Base 3.0.4 + archive_write_set_compression_compress@Base 3.0.4 + archive_write_set_compression_gzip@Base 3.0.4 + archive_write_set_compression_lzip@Base 3.0.4 + archive_write_set_compression_lzma@Base 3.0.4 + archive_write_set_compression_none@Base 3.0.4 + archive_write_set_compression_program@Base 3.0.4 + archive_write_set_compression_xz@Base 3.0.4 + archive_write_set_filter_option@Base 3.0.4 + archive_write_set_format@Base 3.0.4 + archive_write_set_format_7zip@Base 3.0.4 + archive_write_set_format_ar_bsd@Base 3.0.4 + archive_write_set_format_ar_svr4@Base 3.0.4 + archive_write_set_format_by_name@Base 3.0.4 + archive_write_set_format_cpio@Base 3.0.4 + archive_write_set_format_cpio_bin@Base 3.5.2 + archive_write_set_format_cpio_newc@Base 3.0.4 + archive_write_set_format_cpio_odc@Base 3.5.2 + archive_write_set_format_cpio_pwb@Base 3.5.2 + archive_write_set_format_filter_by_ext@Base 3.2.1 + archive_write_set_format_filter_by_ext_def@Base 3.2.1 + archive_write_set_format_gnutar@Base 3.0.4 + archive_write_set_format_iso9660@Base 3.0.4 + archive_write_set_format_mtree@Base 3.0.4 + archive_write_set_format_mtree_classic@Base 3.1.2 + archive_write_set_format_option@Base 3.0.4 + archive_write_set_format_pax@Base 3.0.4 + archive_write_set_format_pax_restricted@Base 3.0.4 + archive_write_set_format_raw@Base 3.2.1 + archive_write_set_format_shar@Base 3.0.4 + archive_write_set_format_shar_dump@Base 3.0.4 + archive_write_set_format_ustar@Base 3.0.4 + archive_write_set_format_v7tar@Base 3.1.2 + archive_write_set_format_warc@Base 3.2.1 + archive_write_set_format_xar@Base 3.0.4 + archive_write_set_format_zip@Base 3.0.4 + archive_write_set_option@Base 3.0.4 + archive_write_set_options@Base 3.0.4 + archive_write_set_passphrase@Base 3.2.1 + archive_write_set_passphrase_callback@Base 3.2.1 + archive_write_set_skip_file@Base 3.0.4 + archive_write_zip_set_compression_deflate@Base 3.1.2 + archive_write_zip_set_compression_store@Base 3.1.2 + archive_zlib_version@Base 3.2.1 diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000000..476d42c935 --- /dev/null +++ b/debian/rules @@ -0,0 +1,26 @@ +#!/usr/bin/make -f + +SHELL := /bin/bash + +export DEB_CFLAGS_MAINT_APPEND=$(shell dpkg-buildflags --get CPPFLAGS) -fPIC +export DEB_CXXFLAGS_MAINT_APPEND=$(shell dpkg-buildflags --get CPPFLAGS) +export DEB_LDFLAGS_MAINT_APPEND=-Wl,--as-needed + +override_dh_autoreconf: + dh_autoreconf build/autogen.sh + +override_dh_auto_configure: + dh_auto_configure + +override_dh_makeshlibs: + dh_makeshlibs -- -c4 + +execute_before_dh_install: + find debian -name '*.la' -delete + +override_dh_auto_test: + +override_dh_auto_clean: + +%: + dh $@ diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000000..163aaf8d82 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/debian/source/lintian-overrides b/debian/source/lintian-overrides new file mode 100644 index 0000000000..3d7682494d --- /dev/null +++ b/debian/source/lintian-overrides @@ -0,0 +1,4 @@ +libarchive source: file-without-copyright-information +libarchive source: no-debian-changes +libarchive source: not-binnmuable-any-depends-any +libarchive source: weak-library-dev-dependency diff --git a/libarchive.spec b/libarchive.spec new file mode 100644 index 0000000000..2e168b0fa6 --- /dev/null +++ b/libarchive.spec @@ -0,0 +1,267 @@ +# Copyright 2023 Wong Hoi Sing Edison +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +%global debug_package %{nil} + +%global _lto_cflags %{?_lto_cflags} -ffat-lto-objects + +Name: libarchive +Epoch: 100 +Version: 3.7.0 +Release: 1%{?dist} +Summary: A library for handling streaming archive formats +License: BSD-3-Clause +URL: https://github.com/libarchive/libarchive/tags +Source0: %{name}_%{version}.orig.tar.gz +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: bison +BuildRequires: bzip2-devel +BuildRequires: e2fsprogs-devel +BuildRequires: gcc +BuildRequires: libacl-devel +BuildRequires: libattr-devel +BuildRequires: libtool +BuildRequires: libxml2-devel +BuildRequires: libzstd-devel +BuildRequires: lz4-devel +BuildRequires: lzo-devel +BuildRequires: make +BuildRequires: nettle-devel +BuildRequires: openssl-devel +BuildRequires: pkgconfig +BuildRequires: sharutils +BuildRequires: xz-devel +BuildRequires: zlib-devel + +%description +Libarchive is a programming library that can create and read several different +streaming archive formats, including most popular tar variants, several cpio +formats, and both BSD and GNU ar variants. It can also write shar archives and +read ISO9660 CDROM images and ZIP archives. + +%prep +%autosetup -T -c -n %{name}_%{version}-%{release} +tar -zx -f %{S:0} --strip-components=1 -C . + +%build +./build/autogen.sh +export CFLAGS="%{optflags} -fPIC" +%configure +%make_build + +%install +%make_install +find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';' + +%check + +%if 0%{?suse_version} > 1500 || 0%{?sle_version} > 150000 +%package -n bsdtar +Summary: Utility to read several different streaming archive formats +Group: Productivity/Archiving/Compression +Requires: libarchive13 >= %{epoch}:%{version}-%{release} + +%description -n bsdtar +This package contains the bsdtar cmdline utility. + +%package -n libarchive13 +Summary: Library to work with several different streaming archive formats +Group: System/Libraries + +%description -n libarchive13 +Libarchive is a programming library that can create and read several +different streaming archive formats, including most popular tar +variants and several cpio formats. It can also write shar archives and +read ISO-9660 CDROM images. The bsdtar program is an implementation of +tar(1) that is built on top of libarchive. It started as a test +harness, but has grown and is now the standard system tar for FreeBSD 5 +and 6. + +The libarchive library offers a number of features that make it both +very flexible and very powerful. + +- Automatic format detection: libarchive can automatically determine + both the compression and the archive format, regardless of the + data source. Most tar implementations do not automatically detect + the compression format, few implementation that can correctly do + this when reading from stdin or a socket. (The tar program + included with Gunnar Ritter's heirloom collection also does full + automatic format detection.) + +- Writes POSIX formats: libarchive writes POSIX-standard formats, + including "ustar," "pax interchange format," and the POSIX "cpio" + format. + +- Supports pax interchange format: Pax interchange format (which, + despite the name, is really an extended tar format) eliminates + almost all limitations of historic tar formats and provides a + standard method for incorporating vendor-specific extensions. + libarchive exploits this extension mechanism to support ACLs and + file flags, for example. (Joerg Schilling's star archiver is + another open-source tar program that supports pax interchange + format.) + +- Reads popular formats: libarchive can read GNU tar, ustar, pax + interchange format, cpio, and older tar variants. The internal + architecture is easily extensible. The only requirement for + support is that it be possible to read the format without seeking + in the file. (For example, a format that includes a compressed + size field before the data cannot be correctly written without + seeking.) + +- High-Level API: the libarchive API makes it fairly simple to build + an archive from a list of filenames or to extract the entries + from an archive. However, the API also provides extreme + flexibility with regards to data sources. For example, there are + generic hooks that allow you to write an archive to a socket or + read data from an archive entry into a memory buffer. + +- Extensible. The internal design uses generic interfaces for +compression, archive format detection and decoding, and archive data +I/O. It should be very easy to add new formats, new compression +methods, or new ways of reading/writing archives. + +%package -n libarchive-devel +Summary: Development files for libarchive +Group: Development/Libraries/C and C++ +Requires: libarchive13 = %{epoch}:%{version}-%{release} +Requires: glibc-devel + +%description -n libarchive-devel +Libarchive is a programming library that can create and read several +different streaming archive formats, including most popular tar +variants and several cpio formats. It can also write shar archives and +read ISO-9660 CDROM images. The bsdtar program is an implementation of +tar(1) that is built on top of libarchive. It started as a test +harness, but has grown and is now the standard system tar for FreeBSD 5 +and 6. + +This package contains the development files. + +%package static-devel +Summary: Static library for libarchive +Group: Development/Libraries/C and C++ +Requires: libarchive-devel = %{epoch}:%{version}-%{release} + +%description static-devel +Static library for libarchive + +%post -n libarchive13 -p /sbin/ldconfig +%postun -n libarchive13 -p /sbin/ldconfig + +%files -n bsdtar +%{_bindir}/* +%{_mandir}/man1/* +%{_mandir}/man5/* + +%files -n libarchive13 +%license COPYING +%{_libdir}/libarchive.so.* + +%files -n libarchive-devel +%doc examples/ +%{_mandir}/man3/* +%{_libdir}/libarchive.so +%{_includedir}/archive* +%{_libdir}/pkgconfig/libarchive.pc + +%files static-devel +%{_libdir}/libarchive.a +%endif + +%if !(0%{?suse_version} > 1500) && !(0%{?sle_version} > 150000) +%package devel +Summary: Development files for libarchive +Requires: libarchive = %{epoch}:%{version}-%{release} + +%description devel +The libarchive-devel package contains libraries and header files for +developing applications that use libarchive. + +%package -n bsdtar +Summary: Manipulate tape archives +Requires: libarchive = %{epoch}:%{version}-%{release} + +%description -n bsdtar +The bsdtar package contains standalone bsdtar utility split off regular +libarchive packages. + +%package -n bsdcpio +Summary: Copy files to and from archives +Requires: libarchive = %{epoch}:%{version}-%{release} + +%description -n bsdcpio +The bsdcpio package contains standalone bsdcpio utility split off +regular libarchive packages. + +%package -n bsdcat +Summary: Expand files to standard output +Requires: libarchive = %{epoch}:%{version}-%{release} + +%description -n bsdcat +The bsdcat program typically takes a filename as an argument or reads +standard input when used in a pipe. In both cases decompressed data it +written to standard output. + +%package -n bsdunzip +Summary: Extract files from a ZIP archive +Requires: libarchive = %{epoch}:%{version}-%{release} + +%description -n bsdunzip +The bsdunzip utility aims to be sufficiently compatible with other +implementations to serve as a drop-in replacement in the context of the +ports(7) system. No attempt has been made to replicate functionality +which is not required for that purpose. + +%post -p /sbin/ldconfig +%postun -p /sbin/ldconfig + +%files +%license COPYING +%{_libdir}/libarchive.so.13* +%{_mandir}/*/cpio.* +%{_mandir}/*/mtree.* +%{_mandir}/*/tar.* + +%files devel +%{_includedir}/*.h +%{_libdir}/libarchive.a +%{_libdir}/libarchive.so +%{_libdir}/pkgconfig/libarchive.pc +%{_mandir}/*/archive* +%{_mandir}/*/libarchive* + +%files -n bsdtar +%license COPYING +%{_bindir}/bsdtar +%{_mandir}/*/bsdtar* + +%files -n bsdcpio +%license COPYING +%{_bindir}/bsdcpio +%{_mandir}/*/bsdcpio* + +%files -n bsdcat +%license COPYING +%{_bindir}/bsdcat +%{_mandir}/*/bsdcat* + +%files -n bsdunzip +%license COPYING +%{_bindir}/bsdunzip +%{_mandir}/*/bsdunzip* +%endif + +%changelog diff --git a/unzip/bsdunzip.c b/unzip/bsdunzip.c index 469c69fd6e..c8572df971 100644 --- a/unzip/bsdunzip.c +++ b/unzip/bsdunzip.c @@ -40,6 +40,8 @@ #ifdef HAVE_SYS_QUEUE_H #include +#else +#include "la_queue.h" #endif #ifdef HAVE_SYS_STAT_H #include @@ -70,6 +72,12 @@ #ifdef HAVE_UNISTD_H #include #endif +#if ((!defined(HAVE_UTIMENSAT) && defined(HAVE_LUTIMES)) || \ + (!defined(HAVE_FUTIMENS) && defined(HAVE_FUTIMES))) +# ifdef HAVE_SYS_TIME_H +#include +# endif +#endif #include #include @@ -628,9 +636,15 @@ extract_file(struct archive *a, struct archive_entry *e, char **path) int mode; struct timespec mtime; struct stat sb; - struct timespec ts[2]; int fd, check, text; const char *linkname; +#if defined(HAVE_UTIMENSAT) || defined(HAVE_FUTIMENS) + struct timespec ts[2]; +#endif +#if ((!defined(HAVE_UTIMENSAT) && defined(HAVE_LUTIMES)) || \ + (!defined(HAVE_FUTIMENS) && defined(HAVE_FUTIMES))) + struct timeval times[2]; +#endif mode = archive_entry_mode(e) & 0777; if (mode == 0) @@ -684,9 +698,18 @@ extract_file(struct archive *a, struct archive_entry *e, char **path) return; } +#if defined(HAVE_UTIMENSAT) || defined(HAVE_FUTIMENS) ts[0].tv_sec = 0; ts[0].tv_nsec = UTIME_NOW; ts[1] = mtime; +#endif +#if ((!defined(HAVE_UTIMENSAT) && defined(HAVE_LUTIMES)) || \ + (!defined(HAVE_FUTIMENS) && defined(HAVE_FUTIMES))) + times[0].tv_sec = 0; + times[0].tv_usec = -1; + times[1].tv_sec = mtime.tv_sec; + times[1].tv_usec = mtime.tv_nsec / 1000; +#endif /* process symlinks */ linkname = archive_entry_symlink(e); @@ -694,11 +717,19 @@ extract_file(struct archive *a, struct archive_entry *e, char **path) if (symlink(linkname, *path) != 0) error("symlink('%s')", *path); info(" extracting: %s -> %s\n", *path, linkname); +#ifdef HAVE_LCHMOD if (lchmod(*path, mode) != 0) warning("Cannot set mode for '%s'", *path); +#endif /* set access and modification time */ +#if defined(HAVE_UTIMENSAT) if (utimensat(AT_FDCWD, *path, ts, AT_SYMLINK_NOFOLLOW) != 0) warning("utimensat('%s')", *path); +#elif defined(HAVE_LUTIMES) + gettimeofday(×[0], NULL); + if (lutimes(*path, times) != 0) + warning("lutimes('%s')", *path); +#endif return; } @@ -716,8 +747,14 @@ extract_file(struct archive *a, struct archive_entry *e, char **path) info("\n"); /* set access and modification time */ +#if defined(HAVE_FUTIMENS) if (futimens(fd, ts) != 0) error("futimens('%s')", *path); +#elif defined(HAVE_FUTIMES) + gettimeofday(×[0], NULL); + if (futimes(fd, times) != 0) + error("futimes('%s')", *path); +#endif if (close(fd) != 0) error("close('%s')", *path); } @@ -1053,7 +1090,10 @@ getopts(int argc, char *argv[]) { int opt; - optreset = optind = 1; + optind = 1; +#ifdef HAVE_GETOPT_OPTRESET + optreset = 1; +#endif while ((opt = getopt(argc, argv, "aCcd:fjLlnopP:qtuvx:yZ1")) != -1) switch (opt) { case '1': diff --git a/unzip/la_queue.h b/unzip/la_queue.h new file mode 100644 index 0000000000..917526531b --- /dev/null +++ b/unzip/la_queue.h @@ -0,0 +1,840 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +/* + * This file defines four types of data structures: singly-linked lists, + * singly-linked tail queues, lists and tail queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may be traversed in either direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * Below is a summary of implemented functions where: + * + means the macro is available + * - means the macro is not available + * s means the macro is available but is slow (runs in O(n) time) + * + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _CLASS_HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _CLASS_ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - + - + + * _LAST - - + + + * _LAST_FAST - - - + + * _FOREACH + + + + + * _FOREACH_FROM + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_FROM_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_FROM - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _FOREACH_REVERSE_FROM_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT s s + + + * _REMOVE_AFTER + - + - + * _REMOVE_HEAD + - + - + * _REMOVE s + s + + * _SWAP + + + + + */ +#ifdef QUEUE_MACRO_DEBUG +#warn Use QUEUE_MACRO_DEBUG_TRACE and/or QUEUE_MACRO_DEBUG_TRASH +#define QUEUE_MACRO_DEBUG_TRACE +#define QUEUE_MACRO_DEBUG_TRASH +#endif + +#ifdef QUEUE_MACRO_DEBUG_TRACE +/* Store the last 2 places the queue element or head was altered */ +struct qm_trace { + unsigned long lastline; + unsigned long prevline; + const char *lastfile; + const char *prevfile; +}; + +#define TRACEBUF struct qm_trace trace; +#define TRACEBUF_INITIALIZER { __LINE__, 0, __FILE__, NULL } , + +#define QMD_TRACE_HEAD(head) do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ +} while (0) + +#define QMD_TRACE_ELEM(elem) do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ +} while (0) + +#else /* !QUEUE_MACRO_DEBUG_TRACE */ +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define TRACEBUF +#define TRACEBUF_INITIALIZER +#endif /* QUEUE_MACRO_DEBUG_TRACE */ + +#ifdef QUEUE_MACRO_DEBUG_TRASH +#define QMD_SAVELINK(name, link) void **name = (void *)&(link) +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) +#define QMD_IS_TRASHED(x) ((x) == (void *)(intptr_t)-1) +#else /* !QUEUE_MACRO_DEBUG_TRASH */ +#define QMD_SAVELINK(name, link) +#define TRASHIT(x) +#define QMD_IS_TRASHED(x) 0 +#endif /* QUEUE_MACRO_DEBUG_TRASH */ + +#ifdef __cplusplus +/* + * In C++ there can be structure lists and class lists: + */ +#define QUEUE_TYPEOF(type) type +#else +#define QUEUE_TYPEOF(type) struct type +#endif + +/* + * Singly-linked List declarations. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_CLASS_HEAD(name, type) \ +struct name { \ + class type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +#define SLIST_CLASS_ENTRY(type) \ +struct { \ + class type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) do { \ + if (*(prevp) != (elm)) \ + panic("Bad prevptr *(%p) == %p != %p", \ + (prevp), *(prevp), (elm)); \ +} while (0) +#else +#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) +#endif + +#define SLIST_CONCAT(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head1); \ + if (curelm == NULL) { \ + if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL) \ + SLIST_INIT(head2); \ + } else if (SLIST_FIRST(head2) != NULL) { \ + while (SLIST_NEXT(curelm, field) != NULL) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_NEXT(curelm, field) = SLIST_FIRST(head2); \ + SLIST_INIT(head2); \ + } \ +} while (0) + +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) + +#define SLIST_INIT(head) do { \ + SLIST_FIRST((head)) = NULL; \ +} while (0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ +} while (0) + +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head); \ + while (SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_REMOVE_AFTER(curelm, field); \ + } \ + TRASHIT(*oldnext); \ +} while (0) + +#define SLIST_REMOVE_AFTER(elm, field) do { \ + SLIST_NEXT(elm, field) = \ + SLIST_NEXT(SLIST_NEXT(elm, field), field); \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ +} while (0) + +#define SLIST_REMOVE_PREVPTR(prevp, elm, field) do { \ + QMD_SLIST_CHECK_PREVPTR(prevp, elm); \ + *(prevp) = SLIST_NEXT(elm, field); \ + TRASHIT((elm)->field.sle_next); \ +} while (0) + +#define SLIST_SWAP(head1, head2, type) do { \ + QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1); \ + SLIST_FIRST(head1) = SLIST_FIRST(head2); \ + SLIST_FIRST(head2) = swap_first; \ +} while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first;/* first element */ \ + struct type **stqh_last;/* addr of last next element */ \ +} + +#define STAILQ_CLASS_HEAD(name, type) \ +struct name { \ + class type *stqh_first; /* first element */ \ + class type **stqh_last; /* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +#define STAILQ_CLASS_ENTRY(type) \ +struct { \ + class type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define STAILQ_FIRST(head) ((head)->stqh_first) + +#define STAILQ_FOREACH(var, head, field) \ + for((var) = STAILQ_FIRST((head)); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + +#define STAILQ_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? NULL : \ + __containerof((head)->stqh_last, \ + QUEUE_TYPEOF(type), field.stqe_next)) + +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } \ + else { \ + QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + STAILQ_REMOVE_AFTER(head, curelm, field); \ + } \ + TRASHIT(*oldnext); \ +} while (0) + +#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ + if ((STAILQ_NEXT(elm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_SWAP(head1, head2, type) do { \ + QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1); \ + QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last; \ + STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_FIRST(head2) = swap_first; \ + (head2)->stqh_last = swap_last; \ + if (STAILQ_EMPTY(head1)) \ + (head1)->stqh_last = &STAILQ_FIRST(head1); \ + if (STAILQ_EMPTY(head2)) \ + (head2)->stqh_last = &STAILQ_FIRST(head2); \ +} while (0) + + +/* + * List declarations. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_CLASS_HEAD(name, type) \ +struct name { \ + class type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +#define LIST_CLASS_ENTRY(type) \ +struct { \ + class type *le_next; /* next element */ \ + class type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ + +#if (defined(_KERNEL) && defined(INVARIANTS)) +/* + * QMD_LIST_CHECK_HEAD(LIST_HEAD *head, LIST_ENTRY NAME) + * + * If the list is non-empty, validates that the first element of the list + * points back at 'head.' + */ +#define QMD_LIST_CHECK_HEAD(head, field) do { \ + if (LIST_FIRST((head)) != NULL && \ + LIST_FIRST((head))->field.le_prev != \ + &LIST_FIRST((head))) \ + panic("Bad list head %p first->prev != head", (head)); \ +} while (0) + +/* + * QMD_LIST_CHECK_NEXT(TYPE *elm, LIST_ENTRY NAME) + * + * If an element follows 'elm' in the list, validates that the next element + * points back at 'elm.' + */ +#define QMD_LIST_CHECK_NEXT(elm, field) do { \ + if (LIST_NEXT((elm), field) != NULL && \ + LIST_NEXT((elm), field)->field.le_prev != \ + &((elm)->field.le_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +/* + * QMD_LIST_CHECK_PREV(TYPE *elm, LIST_ENTRY NAME) + * + * Validates that the previous element (or head of the list) points to 'elm.' + */ +#define QMD_LIST_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.le_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_LIST_CHECK_HEAD(head, field) +#define QMD_LIST_CHECK_NEXT(elm, field) +#define QMD_LIST_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define LIST_CONCAT(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *curelm = LIST_FIRST(head1); \ + if (curelm == NULL) { \ + if ((LIST_FIRST(head1) = LIST_FIRST(head2)) != NULL) { \ + LIST_FIRST(head2)->field.le_prev = \ + &LIST_FIRST((head1)); \ + LIST_INIT(head2); \ + } \ + } else if (LIST_FIRST(head2) != NULL) { \ + while (LIST_NEXT(curelm, field) != NULL) \ + curelm = LIST_NEXT(curelm, field); \ + LIST_NEXT(curelm, field) = LIST_FIRST(head2); \ + LIST_FIRST(head2)->field.le_prev = &LIST_NEXT(curelm, field); \ + LIST_INIT(head2); \ + } \ +} while (0) + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_INIT(head) do { \ + LIST_FIRST((head)) = NULL; \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + QMD_LIST_CHECK_NEXT(listelm, field); \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_LIST_CHECK_PREV(listelm, field); \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + QMD_LIST_CHECK_HEAD((head), field); \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ +} while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_PREV(elm, head, type, field) \ + ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \ + __containerof((elm)->field.le_prev, \ + QUEUE_TYPEOF(type), field.le_next)) + +#define LIST_REMOVE(elm, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.le_next); \ + QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ + QMD_LIST_CHECK_NEXT(elm, field); \ + QMD_LIST_CHECK_PREV(elm, field); \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ +} while (0) + +#define LIST_SWAP(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1); \ + LIST_FIRST((head1)) = LIST_FIRST((head2)); \ + LIST_FIRST((head2)) = swap_tmp; \ + if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ + if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ +} while (0) + +/* + * Tail queue declarations. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_CLASS_HEAD(name, type) \ +struct name { \ + class type *tqh_first; /* first element */ \ + class type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +#define TAILQ_CLASS_ENTRY(type) \ +struct { \ + class type *tqe_next; /* next element */ \ + class type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +/* + * Tail queue functions. + */ +#if (defined(_KERNEL) && defined(INVARIANTS)) +/* + * QMD_TAILQ_CHECK_HEAD(TAILQ_HEAD *head, TAILQ_ENTRY NAME) + * + * If the tailq is non-empty, validates that the first element of the tailq + * points back at 'head.' + */ +#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ + if (!TAILQ_EMPTY(head) && \ + TAILQ_FIRST((head))->field.tqe_prev != \ + &TAILQ_FIRST((head))) \ + panic("Bad tailq head %p first->prev != head", (head)); \ +} while (0) + +/* + * QMD_TAILQ_CHECK_TAIL(TAILQ_HEAD *head, TAILQ_ENTRY NAME) + * + * Validates that the tail of the tailq is a pointer to pointer to NULL. + */ +#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ + if (*(head)->tqh_last != NULL) \ + panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ +} while (0) + +/* + * QMD_TAILQ_CHECK_NEXT(TYPE *elm, TAILQ_ENTRY NAME) + * + * If an element follows 'elm' in the tailq, validates that the next element + * points back at 'elm.' + */ +#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ + if (TAILQ_NEXT((elm), field) != NULL && \ + TAILQ_NEXT((elm), field)->field.tqe_prev != \ + &((elm)->field.tqe_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +/* + * QMD_TAILQ_CHECK_PREV(TYPE *elm, TAILQ_ENTRY NAME) + * + * Validates that the previous element (or head of the tailq) points to 'elm.' + */ +#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.tqe_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_TAILQ_CHECK_HEAD(head, field) +#define QMD_TAILQ_CHECK_TAIL(head, headname) +#define QMD_TAILQ_CHECK_NEXT(elm, field) +#define QMD_TAILQ_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + QMD_TRACE_HEAD(head1); \ + QMD_TRACE_HEAD(head2); \ + } \ +} while (0) + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \ + for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \ + for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QMD_TAILQ_CHECK_NEXT(listelm, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&(listelm)->field); \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_TAILQ_CHECK_PREV(listelm, field); \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&(listelm)->field); \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + QMD_TAILQ_CHECK_HEAD(head, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + QMD_TAILQ_CHECK_TAIL(head, field); \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +/* + * The FAST function is fast in that it causes no data access other + * then the access to the head. The standard LAST function above + * will cause a data access of both the element you want and + * the previous element. FAST is very useful for instances when + * you may want to prefetch the last data element. + */ +#define TAILQ_LAST_FAST(head, type, field) \ + (TAILQ_EMPTY(head) ? NULL : __containerof((head)->tqh_last, QUEUE_TYPEOF(type), field.tqe_next)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_PREV_FAST(elm, head, type, field) \ + ((elm)->field.tqe_prev == &(head)->tqh_first ? NULL : \ + __containerof((elm)->field.tqe_prev, QUEUE_TYPEOF(type), field.tqe_next)) + +#define TAILQ_REMOVE(head, elm, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ + QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ + QMD_TAILQ_CHECK_NEXT(elm, field); \ + QMD_TAILQ_CHECK_PREV(elm, field); \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_SWAP(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first; \ + QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last; \ + (head1)->tqh_first = (head2)->tqh_first; \ + (head1)->tqh_last = (head2)->tqh_last; \ + (head2)->tqh_first = swap_first; \ + (head2)->tqh_last = swap_last; \ + if ((swap_first = (head1)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head1)->tqh_first; \ + else \ + (head1)->tqh_last = &(head1)->tqh_first; \ + if ((swap_first = (head2)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head2)->tqh_first; \ + else \ + (head2)->tqh_last = &(head2)->tqh_first; \ +} while (0) + +#endif /* !_SYS_QUEUE_H_ */