diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/.gitattributes b/packages/libarchive-c/opengnsys-libarchive-c-5.1/.gitattributes
new file mode 100644
index 0000000..f571202
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/.gitattributes
@@ -0,0 +1 @@
+version.py export-subst
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/.github/FUNDING.yml b/packages/libarchive-c/opengnsys-libarchive-c-5.1/.github/FUNDING.yml
new file mode 100644
index 0000000..680194c
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/.github/FUNDING.yml
@@ -0,0 +1 @@
+liberapay: Changaco
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/.github/workflows/main.yml b/packages/libarchive-c/opengnsys-libarchive-c-5.1/.github/workflows/main.yml
new file mode 100644
index 0000000..a715a9d
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/.github/workflows/main.yml
@@ -0,0 +1,36 @@
+name: CI
+on:
+ # Trigger the workflow on push or pull request events but only for the master branch
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+ # Allow running this workflow manually from the Actions tab
+ workflow_dispatch:
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Install libarchive
+ run: sudo apt-get install -y libarchive13
+ - name: Install Python 3.11
+ uses: actions/setup-python@v2
+ with:
+ python-version: '3.11'
+ - name: Install Python 3.10
+ uses: actions/setup-python@v2
+ with:
+ python-version: '3.10'
+ - name: Install Python 3.9
+ uses: actions/setup-python@v2
+ with:
+ python-version: '3.9'
+ - name: Install Python 3.8
+ uses: actions/setup-python@v2
+ with:
+ python-version: '3.8'
+ - name: Install tox
+ run: pip install tox
+ - name: Run the tests
+ run: tox
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/.gitignore b/packages/libarchive-c/opengnsys-libarchive-c-5.1/.gitignore
new file mode 100644
index 0000000..6472f43
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/.gitignore
@@ -0,0 +1,8 @@
+*.egg-info/
+/build/
+/dist/
+/env/
+/htmlcov/
+.coverage
+*.pyc
+.tox/
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/LICENSE.md b/packages/libarchive-c/opengnsys-libarchive-c-5.1/LICENSE.md
new file mode 100644
index 0000000..eebce25
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/LICENSE.md
@@ -0,0 +1 @@
+https://creativecommons.org/publicdomain/zero/1.0/
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/MANIFEST.in b/packages/libarchive-c/opengnsys-libarchive-c-5.1/MANIFEST.in
new file mode 100644
index 0000000..2e92268
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/MANIFEST.in
@@ -0,0 +1 @@
+include version.py
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/PKG-INFO b/packages/libarchive-c/opengnsys-libarchive-c-5.1/PKG-INFO
new file mode 100644
index 0000000..b0fab94
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/PKG-INFO
@@ -0,0 +1,147 @@
+Metadata-Version: 2.1
+Name: libarchive-c
+Version: 5.1
+Summary: Python interface to libarchive
+Home-page: https://github.com/Changaco/python-libarchive-c
+Author: Changaco
+Author-email: changaco@changaco.oy.lc
+License: CC0
+Keywords: archive libarchive 7z tar bz2 zip gz
+Description-Content-Type: text/x-rst
+License-File: LICENSE.md
+
+A Python interface to libarchive. It uses the standard ctypes_ module to
+dynamically load and access the C library.
+
+.. _ctypes: https://docs.python.org/3/library/ctypes.html
+
+Installation
+============
+
+ pip install libarchive-c
+
+Compatibility
+=============
+
+python
+------
+
+python-libarchive-c is currently tested with python 3.8, 3.9, 3.10 and 3.11.
+
+If you find an incompatibility with older versions you can send us a small patch,
+but we won't accept big changes.
+
+libarchive
+----------
+
+python-libarchive-c may not work properly with obsolete versions of libarchive such as the ones included in MacOS. In that case you can install a recent version of libarchive (e.g. with ``brew install libarchive`` on MacOS) and use the ``LIBARCHIVE`` environment variable to point python-libarchive-c to it::
+
+ export LIBARCHIVE=/usr/local/Cellar/libarchive/3.3.3/lib/libarchive.13.dylib
+
+Usage
+=====
+
+Import::
+
+ import libarchive
+
+Extracting archives
+-------------------
+
+To extract an archive, use the ``extract_file`` function::
+
+ os.chdir('/path/to/target/directory')
+ libarchive.extract_file('test.zip')
+
+Alternatively, the ``extract_memory`` function can be used to extract from a buffer,
+and ``extract_fd`` from a file descriptor.
+
+The ``extract_*`` functions all have an integer ``flags`` argument which is passed
+directly to the C function ``archive_write_disk_set_options()``. You can import
+the ``EXTRACT_*`` constants from the ``libarchive.extract`` module and see the
+official description of each flag in the ``archive_write_disk(3)`` man page.
+
+By default, when the ``flags`` argument is ``None``, the ``SECURE_NODOTDOT``,
+``SECURE_NOABSOLUTEPATHS`` and ``SECURE_SYMLINKS`` flags are passed to
+libarchive, unless the current directory is the root (``/``).
+
+Reading archives
+----------------
+
+To read an archive, use the ``file_reader`` function::
+
+ with libarchive.file_reader('test.7z') as archive:
+ for entry in archive:
+ for block in entry.get_blocks():
+ ...
+
+Alternatively, the ``memory_reader`` function can be used to read from a buffer,
+``fd_reader`` from a file descriptor, ``stream_reader`` from a stream object
+(which must support the standard ``readinto`` method), and ``custom_reader``
+from anywhere using callbacks.
+
+To learn about the attributes of the ``entry`` object, see the ``libarchive/entry.py``
+source code or run ``help(libarchive.entry.ArchiveEntry)`` in a Python shell.
+
+Displaying progress
+~~~~~~~~~~~~~~~~~~~
+
+If your program processes large archives, you can keep track of its progress
+with the ``bytes_read`` attribute. Here's an example of a progress bar using
+`tqdm `_::
+
+ with tqdm(total=os.stat(archive_path).st_size, unit='bytes') as pbar, \
+ libarchive.file_reader(archive_path) as archive:
+ for entry in archive:
+ ...
+ pbar.update(archive.bytes_read - pbar.n)
+
+Creating archives
+-----------------
+
+To create an archive, use the ``file_writer`` function::
+
+ from libarchive.entry import FileType
+
+ with libarchive.file_writer('test.tar.gz', 'ustar', 'gzip') as archive:
+ # Add the `libarchive/` directory and everything in it (recursively),
+ # then the `README.rst` file.
+ archive.add_files('libarchive/', 'README.rst')
+ # Add a regular file defined from scratch.
+ data = b'foobar'
+ archive.add_file_from_memory('../escape-test', len(data), data)
+ # Add a directory defined from scratch.
+ early_epoch = (42, 42) # 1970-01-01 00:00:42.000000042
+ archive.add_file_from_memory(
+ 'metadata-test', 0, b'',
+ filetype=FileType.DIRECTORY, permission=0o755, uid=4242, gid=4242,
+ atime=early_epoch, mtime=early_epoch, ctime=early_epoch, birthtime=early_epoch,
+ )
+
+Alternatively, the ``memory_writer`` function can be used to write to a memory buffer,
+``fd_writer`` to a file descriptor, and ``custom_writer`` to a callback function.
+
+For each of those functions, the mandatory second argument is the archive format,
+and the optional third argument is the compression format (called “filter” in
+libarchive). The acceptable values are listed in ``libarchive.ffi.WRITE_FORMATS``
+and ``libarchive.ffi.WRITE_FILTERS``.
+
+File metadata codecs
+--------------------
+
+By default, UTF-8 is used to read and write file attributes from and to archives.
+A different codec can be specified through the ``header_codec`` arguments of the
+``*_reader`` and ``*_writer`` functions. Example::
+
+ with libarchive.file_writer('test.tar', 'ustar', header_codec='cp037') as archive:
+ ...
+ with file_reader('test.tar', header_codec='cp037') as archive:
+ ...
+
+In addition to file paths (``pathname`` and ``linkpath``), the specified codec is
+used to encode and decode user and group names (``uname`` and ``gname``).
+
+License
+=======
+
+`CC0 Public Domain Dedication `_
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/README.rst b/packages/libarchive-c/opengnsys-libarchive-c-5.1/README.rst
new file mode 100644
index 0000000..64bef11
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/README.rst
@@ -0,0 +1,135 @@
+A Python interface to libarchive. It uses the standard ctypes_ module to
+dynamically load and access the C library.
+
+.. _ctypes: https://docs.python.org/3/library/ctypes.html
+
+Installation
+============
+
+ pip install libarchive-c
+
+Compatibility
+=============
+
+python
+------
+
+python-libarchive-c is currently tested with python 3.8, 3.9, 3.10 and 3.11.
+
+If you find an incompatibility with older versions you can send us a small patch,
+but we won't accept big changes.
+
+libarchive
+----------
+
+python-libarchive-c may not work properly with obsolete versions of libarchive such as the ones included in MacOS. In that case you can install a recent version of libarchive (e.g. with ``brew install libarchive`` on MacOS) and use the ``LIBARCHIVE`` environment variable to point python-libarchive-c to it::
+
+ export LIBARCHIVE=/usr/local/Cellar/libarchive/3.3.3/lib/libarchive.13.dylib
+
+Usage
+=====
+
+Import::
+
+ import libarchive
+
+Extracting archives
+-------------------
+
+To extract an archive, use the ``extract_file`` function::
+
+ os.chdir('/path/to/target/directory')
+ libarchive.extract_file('test.zip')
+
+Alternatively, the ``extract_memory`` function can be used to extract from a buffer,
+and ``extract_fd`` from a file descriptor.
+
+The ``extract_*`` functions all have an integer ``flags`` argument which is passed
+directly to the C function ``archive_write_disk_set_options()``. You can import
+the ``EXTRACT_*`` constants from the ``libarchive.extract`` module and see the
+official description of each flag in the ``archive_write_disk(3)`` man page.
+
+By default, when the ``flags`` argument is ``None``, the ``SECURE_NODOTDOT``,
+``SECURE_NOABSOLUTEPATHS`` and ``SECURE_SYMLINKS`` flags are passed to
+libarchive, unless the current directory is the root (``/``).
+
+Reading archives
+----------------
+
+To read an archive, use the ``file_reader`` function::
+
+ with libarchive.file_reader('test.7z') as archive:
+ for entry in archive:
+ for block in entry.get_blocks():
+ ...
+
+Alternatively, the ``memory_reader`` function can be used to read from a buffer,
+``fd_reader`` from a file descriptor, ``stream_reader`` from a stream object
+(which must support the standard ``readinto`` method), and ``custom_reader``
+from anywhere using callbacks.
+
+To learn about the attributes of the ``entry`` object, see the ``libarchive/entry.py``
+source code or run ``help(libarchive.entry.ArchiveEntry)`` in a Python shell.
+
+Displaying progress
+~~~~~~~~~~~~~~~~~~~
+
+If your program processes large archives, you can keep track of its progress
+with the ``bytes_read`` attribute. Here's an example of a progress bar using
+`tqdm `_::
+
+ with tqdm(total=os.stat(archive_path).st_size, unit='bytes') as pbar, \
+ libarchive.file_reader(archive_path) as archive:
+ for entry in archive:
+ ...
+ pbar.update(archive.bytes_read - pbar.n)
+
+Creating archives
+-----------------
+
+To create an archive, use the ``file_writer`` function::
+
+ from libarchive.entry import FileType
+
+ with libarchive.file_writer('test.tar.gz', 'ustar', 'gzip') as archive:
+ # Add the `libarchive/` directory and everything in it (recursively),
+ # then the `README.rst` file.
+ archive.add_files('libarchive/', 'README.rst')
+ # Add a regular file defined from scratch.
+ data = b'foobar'
+ archive.add_file_from_memory('../escape-test', len(data), data)
+ # Add a directory defined from scratch.
+ early_epoch = (42, 42) # 1970-01-01 00:00:42.000000042
+ archive.add_file_from_memory(
+ 'metadata-test', 0, b'',
+ filetype=FileType.DIRECTORY, permission=0o755, uid=4242, gid=4242,
+ atime=early_epoch, mtime=early_epoch, ctime=early_epoch, birthtime=early_epoch,
+ )
+
+Alternatively, the ``memory_writer`` function can be used to write to a memory buffer,
+``fd_writer`` to a file descriptor, and ``custom_writer`` to a callback function.
+
+For each of those functions, the mandatory second argument is the archive format,
+and the optional third argument is the compression format (called “filter” in
+libarchive). The acceptable values are listed in ``libarchive.ffi.WRITE_FORMATS``
+and ``libarchive.ffi.WRITE_FILTERS``.
+
+File metadata codecs
+--------------------
+
+By default, UTF-8 is used to read and write file attributes from and to archives.
+A different codec can be specified through the ``header_codec`` arguments of the
+``*_reader`` and ``*_writer`` functions. Example::
+
+ with libarchive.file_writer('test.tar', 'ustar', header_codec='cp037') as archive:
+ ...
+ with file_reader('test.tar', header_codec='cp037') as archive:
+ ...
+
+In addition to file paths (``pathname`` and ``linkpath``), the specified codec is
+used to encode and decode user and group names (``uname`` and ``gname``).
+
+License
+=======
+
+`CC0 Public Domain Dedication `_
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/__init__.py b/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/__init__.py
new file mode 100644
index 0000000..bb52974
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/__init__.py
@@ -0,0 +1,17 @@
+from .entry import ArchiveEntry
+from .exception import ArchiveError
+from .extract import extract_fd, extract_file, extract_memory
+from .read import (
+ custom_reader, fd_reader, file_reader, memory_reader, stream_reader,
+ seekable_stream_reader
+)
+from .write import custom_writer, fd_writer, file_writer, memory_writer
+
+__all__ = [x.__name__ for x in (
+ ArchiveEntry,
+ ArchiveError,
+ extract_fd, extract_file, extract_memory,
+ custom_reader, fd_reader, file_reader, memory_reader, stream_reader,
+ seekable_stream_reader,
+ custom_writer, fd_writer, file_writer, memory_writer
+)]
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/entry.py b/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/entry.py
new file mode 100644
index 0000000..70701ef
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/entry.py
@@ -0,0 +1,450 @@
+from contextlib import contextmanager
+from ctypes import create_string_buffer
+from enum import IntEnum
+import math
+
+from . import ffi
+
+
+class FileType(IntEnum):
+ NAMED_PIPE = AE_IFIFO = 0o010000 # noqa: E221
+ CHAR_DEVICE = AE_IFCHR = 0o020000 # noqa: E221
+ DIRECTORY = AE_IFDIR = 0o040000 # noqa: E221
+ BLOCK_DEVICE = AE_IFBLK = 0o060000 # noqa: E221
+ REGULAR_FILE = AE_IFREG = 0o100000 # noqa: E221
+ SYMBOLINK_LINK = AE_IFLNK = 0o120000 # noqa: E221
+ SOCKET = AE_IFSOCK = 0o140000 # noqa: E221
+
+
+@contextmanager
+def new_archive_entry():
+ entry_p = ffi.entry_new()
+ try:
+ yield entry_p
+ finally:
+ ffi.entry_free(entry_p)
+
+
+def format_time(seconds, nanos):
+ """ return float of seconds.nanos when nanos set, or seconds when not """
+ if nanos:
+ return float(seconds) + float(nanos) / 1000000000.0
+ return int(seconds)
+
+
+class ArchiveEntry:
+
+ __slots__ = ('_archive_p', '_entry_p', 'header_codec')
+
+ def __init__(self, archive_p=None, header_codec='utf-8', **attributes):
+ """Allocate memory for an `archive_entry` struct.
+
+ The `header_codec` is used to decode and encode file paths and other
+ attributes.
+
+ The `**attributes` are passed to the `modify` method.
+ """
+ self._archive_p = archive_p
+ self._entry_p = ffi.entry_new()
+ self.header_codec = header_codec
+ if attributes:
+ self.modify(**attributes)
+
+ def __del__(self):
+ """Free the C struct"""
+ ffi.entry_free(self._entry_p)
+
+ def __str__(self):
+ """Returns the file's path"""
+ return self.pathname
+
+ def modify(self, header_codec=None, **attributes):
+ """Convenience method to modify the entry's attributes.
+
+ Args:
+ filetype (int): the file's type, see the `FileType` class for values
+ pathname (str): the file's path
+ linkpath (str): the other path of the file, if the file is a link
+ size (int | None): the file's size, in bytes
+ perm (int): the file's permissions in standard Unix format, e.g. 0o640
+ uid (int): the file owner's numerical identifier
+ gid (int): the file group's numerical identifier
+ uname (str | bytes): the file owner's name
+ gname (str | bytes): the file group's name
+ atime (int | Tuple[int, int] | float | None):
+ the file's most recent access time,
+ either in seconds or as a tuple (seconds, nanoseconds)
+ mtime (int | Tuple[int, int] | float | None):
+ the file's most recent modification time,
+ either in seconds or as a tuple (seconds, nanoseconds)
+ ctime (int | Tuple[int, int] | float | None):
+ the file's most recent metadata change time,
+ either in seconds or as a tuple (seconds, nanoseconds)
+ birthtime (int | Tuple[int, int] | float | None):
+ the file's creation time (for archive formats that support it),
+ either in seconds or as a tuple (seconds, nanoseconds)
+ rdev (int | Tuple[int, int]): device number, if the file is a device
+ rdevmajor (int): major part of the device number
+ rdevminor (int): minor part of the device number
+ """
+ if header_codec:
+ self.header_codec = header_codec
+ for name, value in attributes.items():
+ setattr(self, name, value)
+
+ @property
+ def filetype(self):
+ return ffi.entry_filetype(self._entry_p)
+
+ @filetype.setter
+ def filetype(self, value):
+ ffi.entry_set_filetype(self._entry_p, value)
+
+ @property
+ def uid(self):
+ return ffi.entry_uid(self._entry_p)
+
+ @uid.setter
+ def uid(self, uid):
+ ffi.entry_set_uid(self._entry_p, uid)
+
+ @property
+ def gid(self):
+ return ffi.entry_gid(self._entry_p)
+
+ @gid.setter
+ def gid(self, gid):
+ ffi.entry_set_gid(self._entry_p, gid)
+
+ @property
+ def uname(self):
+ uname = ffi.entry_uname_w(self._entry_p)
+ if not uname:
+ uname = ffi.entry_uname(self._entry_p)
+ if uname is not None:
+ try:
+ uname = uname.decode(self.header_codec)
+ except UnicodeError:
+ pass
+ return uname
+
+ @uname.setter
+ def uname(self, value):
+ if not isinstance(value, bytes):
+ value = value.encode(self.header_codec)
+ if self.header_codec == 'utf-8':
+ ffi.entry_update_uname_utf8(self._entry_p, value)
+ else:
+ ffi.entry_copy_uname(self._entry_p, value)
+
+ @property
+ def gname(self):
+ gname = ffi.entry_gname_w(self._entry_p)
+ if not gname:
+ gname = ffi.entry_gname(self._entry_p)
+ if gname is not None:
+ try:
+ gname = gname.decode(self.header_codec)
+ except UnicodeError:
+ pass
+ return gname
+
+ @gname.setter
+ def gname(self, value):
+ if not isinstance(value, bytes):
+ value = value.encode(self.header_codec)
+ if self.header_codec == 'utf-8':
+ ffi.entry_update_gname_utf8(self._entry_p, value)
+ else:
+ ffi.entry_copy_gname(self._entry_p, value)
+
+ def get_blocks(self, block_size=ffi.page_size):
+ """Read the file's content, keeping only one chunk in memory at a time.
+
+ Don't do anything like `list(entry.get_blocks())`, it would silently fail.
+
+ Args:
+ block_size (int): the buffer's size, in bytes
+ """
+ archive_p = self._archive_p
+ if not archive_p:
+ raise TypeError("this entry isn't linked to any content")
+ buf = create_string_buffer(block_size)
+ read = ffi.read_data
+ while 1:
+ r = read(archive_p, buf, block_size)
+ if r == 0:
+ break
+ yield buf.raw[0:r]
+ self.__class__ = ConsumedArchiveEntry
+
+ @property
+ def isblk(self):
+ return self.filetype & 0o170000 == 0o060000
+
+ @property
+ def ischr(self):
+ return self.filetype & 0o170000 == 0o020000
+
+ @property
+ def isdir(self):
+ return self.filetype & 0o170000 == 0o040000
+
+ @property
+ def isfifo(self):
+ return self.filetype & 0o170000 == 0o010000
+
+ @property
+ def islnk(self):
+ return bool(ffi.entry_hardlink_w(self._entry_p) or
+ ffi.entry_hardlink(self._entry_p))
+
+ @property
+ def issym(self):
+ return self.filetype & 0o170000 == 0o120000
+
+ @property
+ def isreg(self):
+ return self.filetype & 0o170000 == 0o100000
+
+ @property
+ def isfile(self):
+ return self.isreg
+
+ @property
+ def issock(self):
+ return self.filetype & 0o170000 == 0o140000
+
+ @property
+ def isdev(self):
+ return self.ischr or self.isblk or self.isfifo or self.issock
+
+ @property
+ def atime(self):
+ if not ffi.entry_atime_is_set(self._entry_p):
+ return None
+ sec_val = ffi.entry_atime(self._entry_p)
+ nsec_val = ffi.entry_atime_nsec(self._entry_p)
+ return format_time(sec_val, nsec_val)
+
+ @atime.setter
+ def atime(self, value):
+ if value is None:
+ ffi.entry_unset_atime(self._entry_p)
+ elif isinstance(value, int):
+ self.set_atime(value)
+ elif isinstance(value, tuple):
+ self.set_atime(*value)
+ else:
+ seconds, fraction = math.modf(value)
+ self.set_atime(int(seconds), int(fraction * 1_000_000_000))
+
+ def set_atime(self, timestamp_sec, timestamp_nsec=0):
+ "Kept for backward compatibility. `entry.atime = ...` is supported now."
+ return ffi.entry_set_atime(self._entry_p, timestamp_sec, timestamp_nsec)
+
+ @property
+ def mtime(self):
+ if not ffi.entry_mtime_is_set(self._entry_p):
+ return None
+ sec_val = ffi.entry_mtime(self._entry_p)
+ nsec_val = ffi.entry_mtime_nsec(self._entry_p)
+ return format_time(sec_val, nsec_val)
+
+ @mtime.setter
+ def mtime(self, value):
+ if value is None:
+ ffi.entry_unset_mtime(self._entry_p)
+ elif isinstance(value, int):
+ self.set_mtime(value)
+ elif isinstance(value, tuple):
+ self.set_mtime(*value)
+ else:
+ seconds, fraction = math.modf(value)
+ self.set_mtime(int(seconds), int(fraction * 1_000_000_000))
+
+ def set_mtime(self, timestamp_sec, timestamp_nsec=0):
+ "Kept for backward compatibility. `entry.mtime = ...` is supported now."
+ return ffi.entry_set_mtime(self._entry_p, timestamp_sec, timestamp_nsec)
+
+ @property
+ def ctime(self):
+ if not ffi.entry_ctime_is_set(self._entry_p):
+ return None
+ sec_val = ffi.entry_ctime(self._entry_p)
+ nsec_val = ffi.entry_ctime_nsec(self._entry_p)
+ return format_time(sec_val, nsec_val)
+
+ @ctime.setter
+ def ctime(self, value):
+ if value is None:
+ ffi.entry_unset_ctime(self._entry_p)
+ elif isinstance(value, int):
+ self.set_ctime(value)
+ elif isinstance(value, tuple):
+ self.set_ctime(*value)
+ else:
+ seconds, fraction = math.modf(value)
+ self.set_ctime(int(seconds), int(fraction * 1_000_000_000))
+
+ def set_ctime(self, timestamp_sec, timestamp_nsec=0):
+ "Kept for backward compatibility. `entry.ctime = ...` is supported now."
+ return ffi.entry_set_ctime(self._entry_p, timestamp_sec, timestamp_nsec)
+
+ @property
+ def birthtime(self):
+ if not ffi.entry_birthtime_is_set(self._entry_p):
+ return None
+ sec_val = ffi.entry_birthtime(self._entry_p)
+ nsec_val = ffi.entry_birthtime_nsec(self._entry_p)
+ return format_time(sec_val, nsec_val)
+
+ @birthtime.setter
+ def birthtime(self, value):
+ if value is None:
+ ffi.entry_unset_birthtime(self._entry_p)
+ elif isinstance(value, int):
+ self.set_birthtime(value)
+ elif isinstance(value, tuple):
+ self.set_birthtime(*value)
+ else:
+ seconds, fraction = math.modf(value)
+ self.set_birthtime(int(seconds), int(fraction * 1_000_000_000))
+
+ def set_birthtime(self, timestamp_sec, timestamp_nsec=0):
+ "Kept for backward compatibility. `entry.birthtime = ...` is supported now."
+ return ffi.entry_set_birthtime(
+ self._entry_p, timestamp_sec, timestamp_nsec
+ )
+
+ @property
+ def pathname(self):
+ path = ffi.entry_pathname_w(self._entry_p)
+ if not path:
+ path = ffi.entry_pathname(self._entry_p)
+ if path is not None:
+ try:
+ path = path.decode(self.header_codec)
+ except UnicodeError:
+ pass
+ return path
+
+ @pathname.setter
+ def pathname(self, value):
+ if not isinstance(value, bytes):
+ value = value.encode(self.header_codec)
+ if self.header_codec == 'utf-8':
+ ffi.entry_update_pathname_utf8(self._entry_p, value)
+ else:
+ ffi.entry_copy_pathname(self._entry_p, value)
+
+ @property
+ def linkpath(self):
+ path = (
+ (
+ ffi.entry_symlink_w(self._entry_p) or
+ ffi.entry_symlink(self._entry_p)
+ ) if self.issym else (
+ ffi.entry_hardlink_w(self._entry_p) or
+ ffi.entry_hardlink(self._entry_p)
+ )
+ )
+ if isinstance(path, bytes):
+ try:
+ path = path.decode(self.header_codec)
+ except UnicodeError:
+ pass
+ return path
+
+ @linkpath.setter
+ def linkpath(self, value):
+ if not isinstance(value, bytes):
+ value = value.encode(self.header_codec)
+ if self.header_codec == 'utf-8':
+ ffi.entry_update_link_utf8(self._entry_p, value)
+ else:
+ ffi.entry_copy_link(self._entry_p, value)
+
+ # aliases for compatibility with the standard `tarfile` module
+ path = property(pathname.fget, pathname.fset, doc="alias of pathname")
+ name = path
+ linkname = property(linkpath.fget, linkpath.fset, doc="alias of linkpath")
+
+ @property
+ def size(self):
+ if ffi.entry_size_is_set(self._entry_p):
+ return ffi.entry_size(self._entry_p)
+
+ @size.setter
+ def size(self, value):
+ if value is None:
+ ffi.entry_unset_size(self._entry_p)
+ else:
+ ffi.entry_set_size(self._entry_p, value)
+
+ @property
+ def mode(self):
+ return ffi.entry_mode(self._entry_p)
+
+ @mode.setter
+ def mode(self, value):
+ ffi.entry_set_mode(self._entry_p, value)
+
+ @property
+ def strmode(self):
+ """The file's mode as a string, e.g. '?rwxrwx---'"""
+ # note we strip the mode because archive_entry_strmode
+ # returns a trailing space: strcpy(bp, "?rwxrwxrwx ");
+ return ffi.entry_strmode(self._entry_p).strip()
+
+ @property
+ def perm(self):
+ return ffi.entry_perm(self._entry_p)
+
+ @perm.setter
+ def perm(self, value):
+ ffi.entry_set_perm(self._entry_p, value)
+
+ @property
+ def rdev(self):
+ return ffi.entry_rdev(self._entry_p)
+
+ @rdev.setter
+ def rdev(self, value):
+ if isinstance(value, tuple):
+ ffi.entry_set_rdevmajor(self._entry_p, value[0])
+ ffi.entry_set_rdevminor(self._entry_p, value[1])
+ else:
+ ffi.entry_set_rdev(self._entry_p, value)
+
+ @property
+ def rdevmajor(self):
+ return ffi.entry_rdevmajor(self._entry_p)
+
+ @rdevmajor.setter
+ def rdevmajor(self, value):
+ ffi.entry_set_rdevmajor(self._entry_p, value)
+
+ @property
+ def rdevminor(self):
+ return ffi.entry_rdevminor(self._entry_p)
+
+ @rdevminor.setter
+ def rdevminor(self, value):
+ ffi.entry_set_rdevminor(self._entry_p, value)
+
+
+class ConsumedArchiveEntry(ArchiveEntry):
+
+ __slots__ = ()
+
+ def get_blocks(self, **kw):
+ raise TypeError("the content of this entry has already been read")
+
+
+class PassedArchiveEntry(ArchiveEntry):
+
+ __slots__ = ()
+
+ def get_blocks(self, **kw):
+ raise TypeError("this entry is passed, it's too late to read its content")
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/exception.py b/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/exception.py
new file mode 100644
index 0000000..e24658c
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/exception.py
@@ -0,0 +1,12 @@
+
+class ArchiveError(Exception):
+
+ def __init__(self, msg, errno=None, retcode=None, archive_p=None):
+ self.msg = msg
+ self.errno = errno
+ self.retcode = retcode
+ self.archive_p = archive_p
+
+ def __str__(self):
+ p = '%s (errno=%s, retcode=%s, archive_p=%s)'
+ return p % (self.msg, self.errno, self.retcode, self.archive_p)
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/extract.py b/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/extract.py
new file mode 100644
index 0000000..bf0c703
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/extract.py
@@ -0,0 +1,88 @@
+from contextlib import contextmanager
+from ctypes import byref, c_longlong, c_size_t, c_void_p
+import os
+
+from .ffi import (
+ write_disk_new, write_disk_set_options, write_free, write_header,
+ read_data_block, write_data_block, write_finish_entry, ARCHIVE_EOF
+)
+from .read import fd_reader, file_reader, memory_reader
+
+
+EXTRACT_OWNER = 0x0001
+EXTRACT_PERM = 0x0002
+EXTRACT_TIME = 0x0004
+EXTRACT_NO_OVERWRITE = 0x0008
+EXTRACT_UNLINK = 0x0010
+EXTRACT_ACL = 0x0020
+EXTRACT_FFLAGS = 0x0040
+EXTRACT_XATTR = 0x0080
+EXTRACT_SECURE_SYMLINKS = 0x0100
+EXTRACT_SECURE_NODOTDOT = 0x0200
+EXTRACT_NO_AUTODIR = 0x0400
+EXTRACT_NO_OVERWRITE_NEWER = 0x0800
+EXTRACT_SPARSE = 0x1000
+EXTRACT_MAC_METADATA = 0x2000
+EXTRACT_NO_HFS_COMPRESSION = 0x4000
+EXTRACT_HFS_COMPRESSION_FORCED = 0x8000
+EXTRACT_SECURE_NOABSOLUTEPATHS = 0x10000
+EXTRACT_CLEAR_NOCHANGE_FFLAGS = 0x20000
+
+PREVENT_ESCAPE = (
+ EXTRACT_SECURE_NOABSOLUTEPATHS |
+ EXTRACT_SECURE_NODOTDOT |
+ EXTRACT_SECURE_SYMLINKS
+)
+
+
+@contextmanager
+def new_archive_write_disk(flags):
+ archive_p = write_disk_new()
+ write_disk_set_options(archive_p, flags)
+ try:
+ yield archive_p
+ finally:
+ write_free(archive_p)
+
+
+def extract_entries(entries, flags=None):
+ """Extracts the given archive entries into the current directory.
+ """
+ if flags is None:
+ if os.getcwd() == '/':
+ # If the current directory is the root, then trying to prevent
+ # escaping is probably undesirable.
+ flags = 0
+ else:
+ flags = PREVENT_ESCAPE
+ buff, size, offset = c_void_p(), c_size_t(), c_longlong()
+ buff_p, size_p, offset_p = byref(buff), byref(size), byref(offset)
+ with new_archive_write_disk(flags) as write_p:
+ for entry in entries:
+ write_header(write_p, entry._entry_p)
+ read_p = entry._archive_p
+ while 1:
+ r = read_data_block(read_p, buff_p, size_p, offset_p)
+ if r == ARCHIVE_EOF:
+ break
+ write_data_block(write_p, buff, size, offset)
+ write_finish_entry(write_p)
+
+
+def extract_fd(fd, flags=None):
+ """Extracts an archive from a file descriptor into the current directory.
+ """
+ with fd_reader(fd) as archive:
+ extract_entries(archive, flags)
+
+
+def extract_file(filepath, flags=None):
+ """Extracts an archive from a file into the current directory."""
+ with file_reader(filepath) as archive:
+ extract_entries(archive, flags)
+
+
+def extract_memory(buffer_, flags=None):
+ """Extracts an archive from memory into the current directory."""
+ with memory_reader(buffer_) as archive:
+ extract_entries(archive, flags)
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/ffi.py b/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/ffi.py
new file mode 100644
index 0000000..1fc321a
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/ffi.py
@@ -0,0 +1,364 @@
+from ctypes import (
+ c_char_p, c_int, c_uint, c_long, c_longlong, c_size_t, c_int64,
+ c_void_p, c_wchar_p, CFUNCTYPE, POINTER,
+)
+
+try:
+ from ctypes import c_ssize_t
+except ImportError:
+ from ctypes import c_longlong as c_ssize_t
+
+import ctypes
+from ctypes.util import find_library
+import logging
+import mmap
+import os
+import sysconfig
+
+from .exception import ArchiveError
+
+
+logger = logging.getLogger('libarchive')
+
+page_size = mmap.PAGESIZE
+
+libarchive_path = os.environ.get('LIBARCHIVE') or find_library('archive')
+libarchive = ctypes.cdll.LoadLibrary(libarchive_path)
+
+
+# Constants
+
+ARCHIVE_EOF = 1 # Found end of archive.
+ARCHIVE_OK = 0 # Operation was successful.
+ARCHIVE_RETRY = -10 # Retry might succeed.
+ARCHIVE_WARN = -20 # Partial success.
+ARCHIVE_FAILED = -25 # Current operation cannot complete.
+ARCHIVE_FATAL = -30 # No more operations are possible.
+
+
+# Callback types
+
+WRITE_CALLBACK = CFUNCTYPE(
+ c_ssize_t, c_void_p, c_void_p, POINTER(c_void_p), c_size_t
+)
+READ_CALLBACK = CFUNCTYPE(
+ c_ssize_t, c_void_p, c_void_p, POINTER(c_void_p)
+)
+SEEK_CALLBACK = CFUNCTYPE(
+ c_longlong, c_void_p, c_void_p, c_longlong, c_int
+)
+OPEN_CALLBACK = CFUNCTYPE(c_int, c_void_p, c_void_p)
+CLOSE_CALLBACK = CFUNCTYPE(c_int, c_void_p, c_void_p)
+
+NO_OPEN_CB = ctypes.cast(None, OPEN_CALLBACK)
+NO_CLOSE_CB = ctypes.cast(None, CLOSE_CALLBACK)
+
+
+# Type aliases, for readability
+
+c_archive_p = c_void_p
+c_archive_entry_p = c_void_p
+
+if sysconfig.get_config_var('SIZEOF_TIME_T') == 8:
+ c_time_t = c_int64
+else:
+ c_time_t = c_long
+
+
+# Helper functions
+
+def _error_string(archive_p):
+ msg = error_string(archive_p)
+ if msg is None:
+ return
+ try:
+ return msg.decode('ascii')
+ except UnicodeDecodeError:
+ return msg
+
+
+def archive_error(archive_p, retcode):
+ msg = _error_string(archive_p)
+ return ArchiveError(msg, errno(archive_p), retcode, archive_p)
+
+
+def check_null(ret, func, args):
+ if ret is None:
+ raise ArchiveError(func.__name__+' returned NULL')
+ return ret
+
+
+def check_int(retcode, func, args):
+ if retcode >= 0:
+ return retcode
+ elif retcode == ARCHIVE_WARN:
+ logger.warning(_error_string(args[0]))
+ return retcode
+ else:
+ raise archive_error(args[0], retcode)
+
+
+def ffi(name, argtypes, restype, errcheck=None):
+ f = getattr(libarchive, 'archive_'+name)
+ f.argtypes = argtypes
+ f.restype = restype
+ if errcheck:
+ f.errcheck = errcheck
+ globals()[name] = f
+ return f
+
+
+def get_read_format_function(format_name):
+ function_name = 'read_support_format_' + format_name
+ func = globals().get(function_name)
+ if func:
+ return func
+ try:
+ return ffi(function_name, [c_archive_p], c_int, check_int)
+ except AttributeError:
+ raise ValueError('the read format %r is not available' % format_name)
+
+
+def get_read_filter_function(filter_name):
+ function_name = 'read_support_filter_' + filter_name
+ func = globals().get(function_name)
+ if func:
+ return func
+ try:
+ return ffi(function_name, [c_archive_p], c_int, check_int)
+ except AttributeError:
+ raise ValueError('the read filter %r is not available' % filter_name)
+
+
+def get_write_format_function(format_name):
+ function_name = 'write_set_format_' + format_name
+ func = globals().get(function_name)
+ if func:
+ return func
+ try:
+ return ffi(function_name, [c_archive_p], c_int, check_int)
+ except AttributeError:
+ raise ValueError('the write format %r is not available' % format_name)
+
+
+def get_write_filter_function(filter_name):
+ function_name = 'write_add_filter_' + filter_name
+ func = globals().get(function_name)
+ if func:
+ return func
+ try:
+ return ffi(function_name, [c_archive_p], c_int, check_int)
+ except AttributeError:
+ raise ValueError('the write filter %r is not available' % filter_name)
+
+
+# FFI declarations
+
+# library version
+version_number = ffi('version_number', [], c_int, check_int)
+
+# archive_util
+
+errno = ffi('errno', [c_archive_p], c_int)
+error_string = ffi('error_string', [c_archive_p], c_char_p)
+ffi('filter_bytes', [c_archive_p, c_int], c_longlong)
+ffi('filter_count', [c_archive_p], c_int)
+ffi('filter_name', [c_archive_p, c_int], c_char_p)
+ffi('format_name', [c_archive_p], c_char_p)
+
+# archive_entry
+
+ffi('entry_new', [], c_archive_entry_p, check_null)
+
+ffi('entry_filetype', [c_archive_entry_p], c_int)
+ffi('entry_atime', [c_archive_entry_p], c_time_t)
+ffi('entry_birthtime', [c_archive_entry_p], c_time_t)
+ffi('entry_mtime', [c_archive_entry_p], c_time_t)
+ffi('entry_ctime', [c_archive_entry_p], c_time_t)
+ffi('entry_atime_nsec', [c_archive_entry_p], c_long)
+ffi('entry_birthtime_nsec', [c_archive_entry_p], c_long)
+ffi('entry_mtime_nsec', [c_archive_entry_p], c_long)
+ffi('entry_ctime_nsec', [c_archive_entry_p], c_long)
+ffi('entry_atime_is_set', [c_archive_entry_p], c_int)
+ffi('entry_birthtime_is_set', [c_archive_entry_p], c_int)
+ffi('entry_mtime_is_set', [c_archive_entry_p], c_int)
+ffi('entry_ctime_is_set', [c_archive_entry_p], c_int)
+ffi('entry_pathname', [c_archive_entry_p], c_char_p)
+ffi('entry_pathname_w', [c_archive_entry_p], c_wchar_p)
+ffi('entry_sourcepath', [c_archive_entry_p], c_char_p)
+ffi('entry_size', [c_archive_entry_p], c_longlong)
+ffi('entry_size_is_set', [c_archive_entry_p], c_int)
+ffi('entry_mode', [c_archive_entry_p], c_int)
+ffi('entry_strmode', [c_archive_entry_p], c_char_p)
+ffi('entry_perm', [c_archive_entry_p], c_int)
+ffi('entry_hardlink', [c_archive_entry_p], c_char_p)
+ffi('entry_hardlink_w', [c_archive_entry_p], c_wchar_p)
+ffi('entry_symlink', [c_archive_entry_p], c_char_p)
+ffi('entry_symlink_w', [c_archive_entry_p], c_wchar_p)
+ffi('entry_rdev', [c_archive_entry_p], c_uint)
+ffi('entry_rdevmajor', [c_archive_entry_p], c_uint)
+ffi('entry_rdevminor', [c_archive_entry_p], c_uint)
+ffi('entry_uid', [c_archive_entry_p], c_longlong)
+ffi('entry_gid', [c_archive_entry_p], c_longlong)
+ffi('entry_uname', [c_archive_entry_p], c_char_p)
+ffi('entry_gname', [c_archive_entry_p], c_char_p)
+ffi('entry_uname_w', [c_archive_entry_p], c_wchar_p)
+ffi('entry_gname_w', [c_archive_entry_p], c_wchar_p)
+
+ffi('entry_set_size', [c_archive_entry_p, c_longlong], None)
+ffi('entry_set_filetype', [c_archive_entry_p, c_uint], None)
+ffi('entry_set_uid', [c_archive_entry_p, c_longlong], None)
+ffi('entry_set_gid', [c_archive_entry_p, c_longlong], None)
+ffi('entry_set_mode', [c_archive_entry_p, c_int], None)
+ffi('entry_set_perm', [c_archive_entry_p, c_int], None)
+ffi('entry_set_atime', [c_archive_entry_p, c_time_t, c_long], None)
+ffi('entry_set_mtime', [c_archive_entry_p, c_time_t, c_long], None)
+ffi('entry_set_ctime', [c_archive_entry_p, c_time_t, c_long], None)
+ffi('entry_set_birthtime', [c_archive_entry_p, c_time_t, c_long], None)
+ffi('entry_set_rdev', [c_archive_entry_p, c_uint], None)
+ffi('entry_set_rdevmajor', [c_archive_entry_p, c_uint], None)
+ffi('entry_set_rdevminor', [c_archive_entry_p, c_uint], None)
+ffi('entry_unset_size', [c_archive_entry_p], None)
+ffi('entry_unset_atime', [c_archive_entry_p], None)
+ffi('entry_unset_mtime', [c_archive_entry_p], None)
+ffi('entry_unset_ctime', [c_archive_entry_p], None)
+ffi('entry_unset_birthtime', [c_archive_entry_p], None)
+
+ffi('entry_copy_pathname', [c_archive_entry_p, c_char_p], None)
+ffi('entry_update_pathname_utf8', [c_archive_entry_p, c_char_p], c_int, check_int)
+ffi('entry_copy_link', [c_archive_entry_p, c_char_p], None)
+ffi('entry_update_link_utf8', [c_archive_entry_p, c_char_p], c_int, check_int)
+ffi('entry_copy_uname', [c_archive_entry_p, c_char_p], None)
+ffi('entry_update_uname_utf8', [c_archive_entry_p, c_char_p], c_int, check_int)
+ffi('entry_copy_gname', [c_archive_entry_p, c_char_p], None)
+ffi('entry_update_gname_utf8', [c_archive_entry_p, c_char_p], c_int, check_int)
+
+ffi('entry_clear', [c_archive_entry_p], c_archive_entry_p)
+ffi('entry_free', [c_archive_entry_p], None)
+
+# archive_read
+
+ffi('read_new', [], c_archive_p, check_null)
+
+READ_FORMATS = set((
+ '7zip', 'all', 'ar', 'cab', 'cpio', 'empty', 'iso9660', 'lha', 'mtree',
+ 'rar', 'raw', 'tar', 'xar', 'zip', 'warc'
+))
+for f_name in list(READ_FORMATS):
+ try:
+ get_read_format_function(f_name)
+ except ValueError as e: # pragma: no cover
+ logger.info(str(e))
+ READ_FORMATS.remove(f_name)
+
+READ_FILTERS = set((
+ 'all', 'bzip2', 'compress', 'grzip', 'gzip', 'lrzip', 'lzip', 'lzma',
+ 'lzop', 'none', 'rpm', 'uu', 'xz', 'lz4', 'zstd'
+))
+for f_name in list(READ_FILTERS):
+ try:
+ get_read_filter_function(f_name)
+ except ValueError as e: # pragma: no cover
+ logger.info(str(e))
+ READ_FILTERS.remove(f_name)
+
+ffi('read_set_seek_callback', [c_archive_p, SEEK_CALLBACK], c_int, check_int)
+
+ffi('read_open',
+ [c_archive_p, c_void_p, OPEN_CALLBACK, READ_CALLBACK, CLOSE_CALLBACK],
+ c_int, check_int)
+ffi('read_open_fd', [c_archive_p, c_int, c_size_t], c_int, check_int)
+ffi('read_open_filename_w', [c_archive_p, c_wchar_p, c_size_t],
+ c_int, check_int)
+ffi('read_open_memory', [c_archive_p, c_void_p, c_size_t], c_int, check_int)
+
+ffi('read_next_header', [c_archive_p, POINTER(c_void_p)], c_int, check_int)
+ffi('read_next_header2', [c_archive_p, c_void_p], c_int, check_int)
+
+ffi('read_close', [c_archive_p], c_int, check_int)
+ffi('read_free', [c_archive_p], c_int, check_int)
+
+# archive_read_disk
+
+ffi('read_disk_new', [], c_archive_p, check_null)
+ffi('read_disk_set_behavior', [c_archive_p, c_int], c_int, check_int)
+ffi('read_disk_set_standard_lookup', [c_archive_p], c_int, check_int)
+ffi('read_disk_open', [c_archive_p, c_char_p], c_int, check_int)
+ffi('read_disk_open_w', [c_archive_p, c_wchar_p], c_int, check_int)
+ffi('read_disk_descend', [c_archive_p], c_int, check_int)
+
+# archive_read_data
+
+ffi('read_data_block',
+ [c_archive_p, POINTER(c_void_p), POINTER(c_size_t), POINTER(c_longlong)],
+ c_int, check_int)
+ffi('read_data', [c_archive_p, c_void_p, c_size_t], c_ssize_t, check_int)
+ffi('read_data_skip', [c_archive_p], c_int, check_int)
+
+# archive_write
+
+ffi('write_new', [], c_archive_p, check_null)
+ffi('write_set_options', [c_archive_p, c_char_p], c_int, check_int)
+
+ffi('write_disk_new', [], c_archive_p, check_null)
+ffi('write_disk_set_options', [c_archive_p, c_int], c_int, check_int)
+
+WRITE_FORMATS = set((
+ '7zip', 'ar_bsd', 'ar_svr4', 'cpio', 'cpio_newc', 'gnutar', 'iso9660',
+ 'mtree', 'mtree_classic', 'pax', 'pax_restricted', 'shar', 'shar_dump',
+ 'ustar', 'v7tar', 'xar', 'zip', 'warc'
+))
+for f_name in list(WRITE_FORMATS):
+ try:
+ get_write_format_function(f_name)
+ except ValueError as e: # pragma: no cover
+ logger.info(str(e))
+ WRITE_FORMATS.remove(f_name)
+
+WRITE_FILTERS = set((
+ 'b64encode', 'bzip2', 'compress', 'grzip', 'gzip', 'lrzip', 'lzip', 'lzma',
+ 'lzop', 'uuencode', 'xz', 'lz4', 'zstd'
+))
+for f_name in list(WRITE_FILTERS):
+ try:
+ get_write_filter_function(f_name)
+ except ValueError as e: # pragma: no cover
+ logger.info(str(e))
+ WRITE_FILTERS.remove(f_name)
+
+ffi('write_open',
+ [c_archive_p, c_void_p, OPEN_CALLBACK, WRITE_CALLBACK, CLOSE_CALLBACK],
+ c_int, check_int)
+ffi('write_open_fd', [c_archive_p, c_int], c_int, check_int)
+ffi('write_open_filename', [c_archive_p, c_char_p], c_int, check_int)
+ffi('write_open_filename_w', [c_archive_p, c_wchar_p], c_int, check_int)
+ffi('write_open_memory',
+ [c_archive_p, c_void_p, c_size_t, POINTER(c_size_t)],
+ c_int, check_int)
+
+ffi('write_get_bytes_in_last_block', [c_archive_p], c_int, check_int)
+ffi('write_get_bytes_per_block', [c_archive_p], c_int, check_int)
+ffi('write_set_bytes_in_last_block', [c_archive_p, c_int], c_int, check_int)
+ffi('write_set_bytes_per_block', [c_archive_p, c_int], c_int, check_int)
+
+ffi('write_header', [c_archive_p, c_void_p], c_int, check_int)
+ffi('write_data', [c_archive_p, c_void_p, c_size_t], c_ssize_t, check_int)
+ffi('write_data_block', [c_archive_p, c_void_p, c_size_t, c_longlong],
+ c_int, check_int)
+ffi('write_finish_entry', [c_archive_p], c_int, check_int)
+
+ffi('write_fail', [c_archive_p], c_int, check_int)
+
+ffi('write_close', [c_archive_p], c_int, check_int)
+ffi('write_free', [c_archive_p], c_int, check_int)
+
+# archive encryption
+
+try:
+ ffi('read_add_passphrase', [c_archive_p, c_char_p], c_int, check_int)
+ ffi('write_set_passphrase', [c_archive_p, c_char_p], c_int, check_int)
+except AttributeError:
+ logger.info(
+ f"the libarchive being used (version {version_number()}, "
+ f"path {libarchive_path}) doesn't support encryption"
+ )
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/flags.py b/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/flags.py
new file mode 100644
index 0000000..6c5b304
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/flags.py
@@ -0,0 +1,7 @@
+READDISK_RESTORE_ATIME = 0x0001
+READDISK_HONOR_NODUMP = 0x0002
+READDISK_MAC_COPYFILE = 0x0004
+READDISK_NO_TRAVERSE_MOUNTS = 0x0008
+READDISK_NO_XATTR = 0x0010
+READDISK_NO_ACL = 0x0020
+READDISK_NO_FFLAGS = 0x0040
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/read.py b/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/read.py
new file mode 100644
index 0000000..3451376
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/read.py
@@ -0,0 +1,176 @@
+from contextlib import contextmanager
+from ctypes import cast, c_void_p, POINTER, create_string_buffer
+from os import fstat, stat
+
+from . import ffi
+from .ffi import (
+ ARCHIVE_EOF, OPEN_CALLBACK, READ_CALLBACK, CLOSE_CALLBACK, SEEK_CALLBACK,
+ NO_OPEN_CB, NO_CLOSE_CB, page_size,
+)
+from .entry import ArchiveEntry, PassedArchiveEntry
+
+
+class ArchiveRead:
+
+ def __init__(self, archive_p, header_codec='utf-8'):
+ self._pointer = archive_p
+ self.header_codec = header_codec
+
+ def __iter__(self):
+ """Iterates through an archive's entries.
+ """
+ archive_p = self._pointer
+ header_codec = self.header_codec
+ read_next_header2 = ffi.read_next_header2
+ while 1:
+ entry = ArchiveEntry(archive_p, header_codec)
+ r = read_next_header2(archive_p, entry._entry_p)
+ if r == ARCHIVE_EOF:
+ return
+ yield entry
+ entry.__class__ = PassedArchiveEntry
+
+ @property
+ def bytes_read(self):
+ return ffi.filter_bytes(self._pointer, -1)
+
+ @property
+ def filter_names(self):
+ count = ffi.filter_count(self._pointer)
+ return [ffi.filter_name(self._pointer, i) for i in range(count - 1)]
+
+ @property
+ def format_name(self):
+ return ffi.format_name(self._pointer)
+
+
+@contextmanager
+def new_archive_read(format_name='all', filter_name='all', passphrase=None):
+ """Creates an archive struct suitable for reading from an archive.
+
+ Returns a pointer if successful. Raises ArchiveError on error.
+ """
+ archive_p = ffi.read_new()
+ try:
+ if passphrase:
+ if not isinstance(passphrase, bytes):
+ passphrase = passphrase.encode('utf-8')
+ try:
+ ffi.read_add_passphrase(archive_p, passphrase)
+ except AttributeError:
+ raise NotImplementedError(
+ f"the libarchive being used (version {ffi.version_number()}, "
+ f"path {ffi.libarchive_path}) doesn't support encryption"
+ )
+ ffi.get_read_filter_function(filter_name)(archive_p)
+ ffi.get_read_format_function(format_name)(archive_p)
+ yield archive_p
+ finally:
+ ffi.read_free(archive_p)
+
+
+@contextmanager
+def custom_reader(
+ read_func, format_name='all', filter_name='all',
+ open_func=None, seek_func=None, close_func=None,
+ block_size=page_size, archive_read_class=ArchiveRead, passphrase=None,
+ header_codec='utf-8',
+):
+ """Read an archive using a custom function.
+ """
+ open_cb = OPEN_CALLBACK(open_func) if open_func else NO_OPEN_CB
+ read_cb = READ_CALLBACK(read_func)
+ close_cb = CLOSE_CALLBACK(close_func) if close_func else NO_CLOSE_CB
+ seek_cb = SEEK_CALLBACK(seek_func)
+ with new_archive_read(format_name, filter_name, passphrase) as archive_p:
+ if seek_func:
+ ffi.read_set_seek_callback(archive_p, seek_cb)
+ ffi.read_open(archive_p, None, open_cb, read_cb, close_cb)
+ yield archive_read_class(archive_p, header_codec)
+
+
+@contextmanager
+def fd_reader(
+ fd, format_name='all', filter_name='all', block_size=4096, passphrase=None,
+ header_codec='utf-8',
+):
+ """Read an archive from a file descriptor.
+ """
+ with new_archive_read(format_name, filter_name, passphrase) as archive_p:
+ try:
+ block_size = fstat(fd).st_blksize
+ except (OSError, AttributeError): # pragma: no cover
+ pass
+ ffi.read_open_fd(archive_p, fd, block_size)
+ yield ArchiveRead(archive_p, header_codec)
+
+
+@contextmanager
+def file_reader(
+ path, format_name='all', filter_name='all', block_size=4096, passphrase=None,
+ header_codec='utf-8',
+):
+ """Read an archive from a file.
+ """
+ with new_archive_read(format_name, filter_name, passphrase) as archive_p:
+ try:
+ block_size = stat(path).st_blksize
+ except (OSError, AttributeError): # pragma: no cover
+ pass
+ ffi.read_open_filename_w(archive_p, path, block_size)
+ yield ArchiveRead(archive_p, header_codec)
+
+
+@contextmanager
+def memory_reader(
+ buf, format_name='all', filter_name='all', passphrase=None,
+ header_codec='utf-8',
+):
+ """Read an archive from memory.
+ """
+ with new_archive_read(format_name, filter_name, passphrase) as archive_p:
+ ffi.read_open_memory(archive_p, cast(buf, c_void_p), len(buf))
+ yield ArchiveRead(archive_p, header_codec)
+
+
+@contextmanager
+def stream_reader(
+ stream, format_name='all', filter_name='all', block_size=page_size,
+ passphrase=None, header_codec='utf-8',
+):
+ """Read an archive from a stream.
+
+ The `stream` object must support the standard `readinto` method.
+
+ If `stream.seekable()` returns `True`, then an appropriate seek callback is
+ passed to libarchive.
+ """
+ buf = create_string_buffer(block_size)
+ buf_p = cast(buf, c_void_p)
+
+ def read_func(archive_p, context, ptrptr):
+ # readinto the buffer, returns number of bytes read
+ length = stream.readinto(buf)
+ # write the address of the buffer into the pointer
+ ptrptr = cast(ptrptr, POINTER(c_void_p))
+ ptrptr[0] = buf_p
+ # tell libarchive how much data was written into the buffer
+ return length
+
+ def seek_func(archive_p, context, offset, whence):
+ stream.seek(offset, whence)
+ # tell libarchive the current position
+ return stream.tell()
+
+ open_cb = NO_OPEN_CB
+ read_cb = READ_CALLBACK(read_func)
+ close_cb = NO_CLOSE_CB
+ seek_cb = SEEK_CALLBACK(seek_func)
+ with new_archive_read(format_name, filter_name, passphrase) as archive_p:
+ if stream.seekable():
+ ffi.read_set_seek_callback(archive_p, seek_cb)
+ ffi.read_open(archive_p, None, open_cb, read_cb, close_cb)
+ yield ArchiveRead(archive_p, header_codec)
+
+
+seekable_stream_reader = stream_reader
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/write.py b/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/write.py
new file mode 100644
index 0000000..7ba191d
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/libarchive/write.py
@@ -0,0 +1,279 @@
+from contextlib import contextmanager
+from ctypes import byref, cast, c_char, c_size_t, c_void_p, POINTER
+from posixpath import join
+import warnings
+
+from . import ffi
+from .entry import ArchiveEntry, FileType
+from .ffi import (
+ OPEN_CALLBACK, WRITE_CALLBACK, CLOSE_CALLBACK, NO_OPEN_CB, NO_CLOSE_CB,
+ ARCHIVE_EOF,
+ page_size, entry_sourcepath, entry_clear, read_disk_new, read_disk_open_w,
+ read_next_header2, read_disk_descend, read_free, write_header, write_data,
+ write_finish_entry,
+ read_disk_set_behavior
+)
+
+
+@contextmanager
+def new_archive_read_disk(path, flags=0, lookup=False):
+ archive_p = read_disk_new()
+ read_disk_set_behavior(archive_p, flags)
+ if lookup:
+ ffi.read_disk_set_standard_lookup(archive_p)
+ read_disk_open_w(archive_p, path)
+ try:
+ yield archive_p
+ finally:
+ read_free(archive_p)
+
+
+class ArchiveWrite:
+
+ def __init__(self, archive_p, header_codec='utf-8'):
+ self._pointer = archive_p
+ self.header_codec = header_codec
+
+ def add_entries(self, entries):
+ """Add the given entries to the archive.
+ """
+ write_p = self._pointer
+ for entry in entries:
+ write_header(write_p, entry._entry_p)
+ for block in entry.get_blocks():
+ write_data(write_p, block, len(block))
+ write_finish_entry(write_p)
+
+ def add_files(
+ self, *paths, flags=0, lookup=False, pathname=None, recursive=True,
+ **attributes
+ ):
+ """Read files through the OS and add them to the archive.
+
+ Args:
+ paths (str): the paths of the files to add to the archive
+ flags (int):
+ passed to the C function `archive_read_disk_set_behavior`;
+ use the `libarchive.flags.READDISK_*` constants
+ lookup (bool):
+ when True, the C function `archive_read_disk_set_standard_lookup`
+ is called to enable the lookup of user and group names
+ pathname (str | None):
+ the path of the file in the archive, defaults to the source path
+ recursive (bool):
+ when False, if a path in `paths` is a directory,
+ only the directory itself is added.
+ attributes (dict): passed to `ArchiveEntry.modify()`
+
+ Raises:
+ ArchiveError: if a file doesn't exist or can't be accessed, or if
+ adding it to the archive fails
+ """
+ write_p = self._pointer
+
+ block_size = ffi.write_get_bytes_per_block(write_p)
+ if block_size <= 0:
+ block_size = 10240 # pragma: no cover
+
+ entry = ArchiveEntry(header_codec=self.header_codec)
+ entry_p = entry._entry_p
+ destination_path = attributes.pop('pathname', None)
+ for path in paths:
+ with new_archive_read_disk(path, flags, lookup) as read_p:
+ while 1:
+ r = read_next_header2(read_p, entry_p)
+ if r == ARCHIVE_EOF:
+ break
+ entry_path = entry.pathname
+ if destination_path:
+ if entry_path == path:
+ entry_path = destination_path
+ else:
+ assert entry_path.startswith(path)
+ entry_path = join(
+ destination_path,
+ entry_path[len(path):].lstrip('/')
+ )
+ entry.pathname = entry_path.lstrip('/')
+ if attributes:
+ entry.modify(**attributes)
+ read_disk_descend(read_p)
+ write_header(write_p, entry_p)
+ if entry.isreg:
+ with open(entry_sourcepath(entry_p), 'rb') as f:
+ while 1:
+ data = f.read(block_size)
+ if not data:
+ break
+ write_data(write_p, data, len(data))
+ write_finish_entry(write_p)
+ entry_clear(entry_p)
+ if not recursive:
+ break
+
+ def add_file(self, path, **kw):
+ "Single-path alias of `add_files()`"
+ return self.add_files(path, **kw)
+
+ def add_file_from_memory(
+ self, entry_path, entry_size, entry_data,
+ filetype=FileType.REGULAR_FILE, permission=0o664,
+ **other_attributes
+ ):
+ """"Add file from memory to archive.
+
+ Args:
+ entry_path (str | bytes): the file's path
+ entry_size (int): the file's size, in bytes
+ entry_data (bytes | Iterable[bytes]): the file's content
+ filetype (int): see `libarchive.entry.ArchiveEntry.modify()`
+ permission (int): see `libarchive.entry.ArchiveEntry.modify()`
+ other_attributes: see `libarchive.entry.ArchiveEntry.modify()`
+ """
+ archive_pointer = self._pointer
+
+ if isinstance(entry_data, bytes):
+ entry_data = (entry_data,)
+ elif isinstance(entry_data, str):
+ raise TypeError(
+ "entry_data: expected bytes, got %r" % type(entry_data)
+ )
+
+ entry = ArchiveEntry(
+ pathname=entry_path, size=entry_size, filetype=filetype,
+ perm=permission, header_codec=self.header_codec,
+ **other_attributes
+ )
+ write_header(archive_pointer, entry._entry_p)
+
+ for chunk in entry_data:
+ if not chunk:
+ break
+ write_data(archive_pointer, chunk, len(chunk))
+
+ write_finish_entry(archive_pointer)
+
+
+@contextmanager
+def new_archive_write(format_name, filter_name=None, options='', passphrase=None):
+ archive_p = ffi.write_new()
+ try:
+ ffi.get_write_format_function(format_name)(archive_p)
+ if filter_name:
+ ffi.get_write_filter_function(filter_name)(archive_p)
+ if passphrase and 'encryption' not in options:
+ if format_name == 'zip':
+ warnings.warn(
+ "The default encryption scheme of zip archives is weak. "
+ "Use `options='encryption=$type'` to specify the encryption "
+ "type you want to use. The supported values are 'zipcrypt' "
+ "(the weak default), 'aes128' and 'aes256'."
+ )
+ options += ',encryption' if options else 'encryption'
+ if options:
+ if not isinstance(options, bytes):
+ options = options.encode('utf-8')
+ ffi.write_set_options(archive_p, options)
+ if passphrase:
+ if not isinstance(passphrase, bytes):
+ passphrase = passphrase.encode('utf-8')
+ try:
+ ffi.write_set_passphrase(archive_p, passphrase)
+ except AttributeError:
+ raise NotImplementedError(
+ f"the libarchive being used (version {ffi.version_number()}, "
+ f"path {ffi.libarchive_path}) doesn't support encryption"
+ )
+ yield archive_p
+ ffi.write_close(archive_p)
+ ffi.write_free(archive_p)
+ except Exception:
+ ffi.write_fail(archive_p)
+ ffi.write_free(archive_p)
+ raise
+
+ @property
+ def bytes_written(self):
+ return ffi.filter_bytes(self._pointer, -1)
+
+
+@contextmanager
+def custom_writer(
+ write_func, format_name, filter_name=None,
+ open_func=None, close_func=None, block_size=page_size,
+ archive_write_class=ArchiveWrite, options='', passphrase=None,
+ header_codec='utf-8',
+):
+ """Create an archive and send it in chunks to the `write_func` function.
+
+ For formats and filters, see `WRITE_FORMATS` and `WRITE_FILTERS` in the
+ `libarchive.ffi` module.
+ """
+
+ def write_cb_internal(archive_p, context, buffer_, length):
+ data = cast(buffer_, POINTER(c_char * length))[0]
+ return write_func(data)
+
+ open_cb = OPEN_CALLBACK(open_func) if open_func else NO_OPEN_CB
+ write_cb = WRITE_CALLBACK(write_cb_internal)
+ close_cb = CLOSE_CALLBACK(close_func) if close_func else NO_CLOSE_CB
+
+ with new_archive_write(format_name, filter_name, options,
+ passphrase) as archive_p:
+ ffi.write_set_bytes_in_last_block(archive_p, 1)
+ ffi.write_set_bytes_per_block(archive_p, block_size)
+ ffi.write_open(archive_p, None, open_cb, write_cb, close_cb)
+ yield archive_write_class(archive_p, header_codec)
+
+
+@contextmanager
+def fd_writer(
+ fd, format_name, filter_name=None,
+ archive_write_class=ArchiveWrite, options='', passphrase=None,
+ header_codec='utf-8',
+):
+ """Create an archive and write it into a file descriptor.
+
+ For formats and filters, see `WRITE_FORMATS` and `WRITE_FILTERS` in the
+ `libarchive.ffi` module.
+ """
+ with new_archive_write(format_name, filter_name, options,
+ passphrase) as archive_p:
+ ffi.write_open_fd(archive_p, fd)
+ yield archive_write_class(archive_p, header_codec)
+
+
+@contextmanager
+def file_writer(
+ filepath, format_name, filter_name=None,
+ archive_write_class=ArchiveWrite, options='', passphrase=None,
+ header_codec='utf-8',
+):
+ """Create an archive and write it into a file.
+
+ For formats and filters, see `WRITE_FORMATS` and `WRITE_FILTERS` in the
+ `libarchive.ffi` module.
+ """
+ with new_archive_write(format_name, filter_name, options,
+ passphrase) as archive_p:
+ ffi.write_open_filename_w(archive_p, filepath)
+ yield archive_write_class(archive_p, header_codec)
+
+
+@contextmanager
+def memory_writer(
+ buf, format_name, filter_name=None,
+ archive_write_class=ArchiveWrite, options='', passphrase=None,
+ header_codec='utf-8',
+):
+ """Create an archive and write it into a buffer.
+
+ For formats and filters, see `WRITE_FORMATS` and `WRITE_FILTERS` in the
+ `libarchive.ffi` module.
+ """
+ with new_archive_write(format_name, filter_name, options,
+ passphrase) as archive_p:
+ used = byref(c_size_t())
+ buf_p = cast(buf, c_void_p)
+ ffi.write_open_memory(archive_p, buf_p, len(buf), used)
+ yield archive_write_class(archive_p, header_codec)
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/setup.cfg b/packages/libarchive-c/opengnsys-libarchive-c-5.1/setup.cfg
new file mode 100644
index 0000000..8998725
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/setup.cfg
@@ -0,0 +1,12 @@
+[wheel]
+universal = 1
+
+[flake8]
+exclude = .?*,env*/
+ignore = E226,E731,W504
+max-line-length = 85
+
+[egg_info]
+tag_build =
+tag_date = 0
+
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/setup.py b/packages/libarchive-c/opengnsys-libarchive-c-5.1/setup.py
new file mode 100644
index 0000000..3100112
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/setup.py
@@ -0,0 +1,25 @@
+import os
+from os.path import join, dirname
+
+from setuptools import setup, find_packages
+
+from version import get_version
+
+os.umask(0o022)
+
+with open(join(dirname(__file__), 'README.rst'), encoding="utf-8") as f:
+ README = f.read()
+
+setup(
+ name='libarchive-c',
+ version=get_version(),
+ description='Python interface to libarchive',
+ author='Changaco',
+ author_email='changaco@changaco.oy.lc',
+ url='https://github.com/Changaco/python-libarchive-c',
+ license='CC0',
+ packages=find_packages(exclude=['tests']),
+ long_description=README,
+ long_description_content_type='text/x-rst',
+ keywords='archive libarchive 7z tar bz2 zip gz',
+)
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/__init__.py b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/__init__.py
new file mode 100644
index 0000000..7a7f583
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/__init__.py
@@ -0,0 +1,136 @@
+from contextlib import closing, contextmanager
+from copy import copy
+from os import chdir, getcwd, stat, walk
+from os.path import abspath, dirname, join
+from stat import S_ISREG
+import tarfile
+try:
+ from stat import filemode
+except ImportError: # Python 2
+ filemode = tarfile.filemode
+
+from libarchive import file_reader
+
+
+data_dir = join(dirname(__file__), 'data')
+
+
+def check_archive(archive, tree):
+ tree2 = copy(tree)
+ for e in archive:
+ epath = str(e).rstrip('/')
+ assert epath in tree2
+ estat = tree2.pop(epath)
+ assert e.mtime == int(estat['mtime'])
+ if not e.isdir:
+ size = e.size
+ if size is not None:
+ assert size == estat['size']
+ with open(epath, 'rb') as f:
+ for block in e.get_blocks():
+ assert f.read(len(block)) == block
+ leftover = f.read()
+ assert not leftover
+
+ # Check that there are no missing directories or files
+ assert len(tree2) == 0
+
+
+def get_entries(location):
+ """
+ Using the archive file at `location`, return an iterable of name->value
+ mappings for each libarchive.ArchiveEntry objects essential attributes.
+ Paths are base64-encoded because JSON is UTF-8 and cannot handle
+ arbitrary binary pathdata.
+ """
+ with file_reader(location) as arch:
+ for entry in arch:
+ # libarchive introduces prefixes such as h prefix for
+ # hardlinks: tarfile does not, so we ignore the first char
+ mode = entry.strmode[1:].decode('ascii')
+ yield {
+ 'path': surrogate_decode(entry.pathname),
+ 'mtime': entry.mtime,
+ 'size': entry.size,
+ 'mode': mode,
+ 'isreg': entry.isreg,
+ 'isdir': entry.isdir,
+ 'islnk': entry.islnk,
+ 'issym': entry.issym,
+ 'linkpath': surrogate_decode(entry.linkpath),
+ 'isblk': entry.isblk,
+ 'ischr': entry.ischr,
+ 'isfifo': entry.isfifo,
+ 'isdev': entry.isdev,
+ 'uid': entry.uid,
+ 'gid': entry.gid
+ }
+
+
+def get_tarinfos(location):
+ """
+ Using the tar archive file at `location`, return an iterable of
+ name->value mappings for each tarfile.TarInfo objects essential
+ attributes.
+ Paths are base64-encoded because JSON is UTF-8 and cannot handle
+ arbitrary binary pathdata.
+ """
+ with closing(tarfile.open(location)) as tar:
+ for entry in tar:
+ path = surrogate_decode(entry.path or '')
+ if entry.isdir() and not path.endswith('/'):
+ path += '/'
+ # libarchive introduces prefixes such as h prefix for
+ # hardlinks: tarfile does not, so we ignore the first char
+ mode = filemode(entry.mode)[1:]
+ yield {
+ 'path': path,
+ 'mtime': entry.mtime,
+ 'size': entry.size,
+ 'mode': mode,
+ 'isreg': entry.isreg(),
+ 'isdir': entry.isdir(),
+ 'islnk': entry.islnk(),
+ 'issym': entry.issym(),
+ 'linkpath': surrogate_decode(entry.linkpath or None),
+ 'isblk': entry.isblk(),
+ 'ischr': entry.ischr(),
+ 'isfifo': entry.isfifo(),
+ 'isdev': entry.isdev(),
+ 'uid': entry.uid,
+ 'gid': entry.gid
+ }
+
+
+@contextmanager
+def in_dir(dirpath):
+ prev = abspath(getcwd())
+ chdir(dirpath)
+ try:
+ yield
+ finally:
+ chdir(prev)
+
+
+def stat_dict(path):
+ keys = set(('uid', 'gid', 'mtime'))
+ mode, _, _, _, uid, gid, size, _, mtime, _ = stat(path)
+ if S_ISREG(mode):
+ keys.add('size')
+ return {k: v for k, v in locals().items() if k in keys}
+
+
+def treestat(d, stat_dict=stat_dict):
+ r = {}
+ for dirpath, dirnames, filenames in walk(d):
+ r[dirpath] = stat_dict(dirpath)
+ for fname in filenames:
+ fpath = join(dirpath, fname)
+ r[fpath] = stat_dict(fpath)
+ return r
+
+
+def surrogate_decode(o):
+ if isinstance(o, bytes):
+ return o.decode('utf8', errors='surrogateescape')
+ return o
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/flags.tar b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/flags.tar
new file mode 100644
index 0000000..24e6c7f
Binary files /dev/null and b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/flags.tar differ
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/special.tar b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/special.tar
new file mode 100644
index 0000000..8fd0c50
Binary files /dev/null and b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/special.tar differ
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/tar_relative.tar b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/tar_relative.tar
new file mode 100644
index 0000000..0caff86
Binary files /dev/null and b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/tar_relative.tar differ
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/testtar.README b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/testtar.README
new file mode 100644
index 0000000..cd85511
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/testtar.README
@@ -0,0 +1,3 @@
+This test file is borrowed from Python codebase and test suite.
+This is a trick Tar with several weird and malformed entries:
+https://hg.python.org/cpython/file/bff88c866886/Lib/test/testtar.tar
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/testtar.tar b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/testtar.tar
new file mode 100644
index 0000000..bb93453
Binary files /dev/null and b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/testtar.tar differ
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/testtar.tar.json b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/testtar.tar.json
new file mode 100644
index 0000000..46e3f0b
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/testtar.tar.json
@@ -0,0 +1,665 @@
+[
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "ustar/conttype",
+ "size": 7011,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "ustar/regtype",
+ "size": 7011,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": true,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": false,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rwxr-xr-x",
+ "mtime": 1041808783,
+ "path": "ustar/dirtype/",
+ "size": 0,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": true,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": false,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rwxr-xr-x",
+ "mtime": 1041808783,
+ "path": "ustar/dirtype-with-size/",
+ "size": 0,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": true,
+ "isreg": false,
+ "issym": false,
+ "linkpath": "ustar/regtype",
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "ustar/lnktype",
+ "size": 0,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": false,
+ "issym": true,
+ "linkpath": "regtype",
+ "mode": "rwxrwxrwx",
+ "mtime": 1041808783,
+ "path": "ustar/symtype",
+ "size": 0,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": true,
+ "ischr": false,
+ "isdev": true,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": false,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-rw----",
+ "mtime": 1041808783,
+ "path": "ustar/blktype",
+ "size": 0,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": true,
+ "isdev": true,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": false,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-rw-rw-",
+ "mtime": 1041808783,
+ "path": "ustar/chrtype",
+ "size": 0,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": true,
+ "isdir": false,
+ "isfifo": true,
+ "islnk": false,
+ "isreg": false,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "ustar/fifotype",
+ "size": 0,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "ustar/sparse",
+ "size": 86016,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "ustar/umlauts-\udcc4\udcd6\udcdc\udce4\udcf6\udcfc\udcdf",
+ "size": 7011,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "ustar/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/12345/1234567/longname",
+ "size": 7011,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": false,
+ "issym": true,
+ "linkpath": "../linktest1/regtype",
+ "mode": "rwxrwxrwx",
+ "mtime": 1041808783,
+ "path": "./ustar/linktest2/symtype",
+ "size": 0,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "ustar/linktest1/regtype",
+ "size": 7011,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": true,
+ "isreg": false,
+ "issym": false,
+ "linkpath": "./ustar/linktest1/regtype",
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "./ustar/linktest2/lnktype",
+ "size": 0,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": false,
+ "issym": true,
+ "linkpath": "ustar/regtype",
+ "mode": "rwxrwxrwx",
+ "mtime": 1041808783,
+ "path": "symtype2",
+ "size": 0,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "gnu/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/longname",
+ "size": 7011,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": true,
+ "isreg": false,
+ "issym": false,
+ "linkpath": "gnu/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/longname",
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "gnu/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/longlink",
+ "size": 0,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "gnu/sparse",
+ "size": 86016,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "gnu/sparse-0.0",
+ "size": 86016,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "gnu/sparse-0.1",
+ "size": 86016,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "gnu/sparse-1.0",
+ "size": 86016,
+ "uid": 1000
+ },
+ {
+ "gid": 4294967295,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "gnu/regtype-gnu-uid",
+ "size": 7011,
+ "uid": 4294967295
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "misc/regtype-old-v7",
+ "size": 7011,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "misc/regtype-hpux-signed-chksum-\udcc4\udcd6\udcdc\udce4\udcf6\udcfc\udcdf",
+ "size": 7011,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "misc/regtype-old-v7-signed-chksum-\udcc4\udcd6\udcdc\udce4\udcf6\udcfc\udcdf",
+ "size": 7011,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": true,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": false,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rwxr-xr-x",
+ "mtime": 1041808783,
+ "path": "misc/dirtype-old-v7/",
+ "size": 0,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "misc/regtype-suntar",
+ "size": 7011,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "misc/regtype-xstar",
+ "size": 7011,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "pax/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/longname",
+ "size": 7011,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": true,
+ "isreg": false,
+ "issym": false,
+ "linkpath": "pax/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/longname",
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "pax/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/123/longlink",
+ "size": 0,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "pax/umlauts-\u00c4\u00d6\u00dc\u00e4\u00f6\u00fc\u00df",
+ "size": 7011,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "pax/regtype1",
+ "size": 7011,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "pax/regtype2",
+ "size": 7011,
+ "uid": 1000
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "pax/regtype3",
+ "size": 7011,
+ "uid": 1000
+ },
+ {
+ "gid": 123,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "pax/regtype4",
+ "size": 7011,
+ "uid": 123
+ },
+ {
+ "gid": 1000,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "pax/bad-pax-\udce4\udcf6\udcfc",
+ "size": 7011,
+ "uid": 1000
+ },
+ {
+ "gid": 0,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "pax/hdrcharset-\udce4\udcf6\udcfc",
+ "size": 7011,
+ "uid": 0
+ },
+ {
+ "gid": 100,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1041808783,
+ "path": "misc/eof",
+ "size": 0,
+ "uid": 1000
+ }
+]
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/unicode.tar b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/unicode.tar
new file mode 100644
index 0000000..bbaded7
Binary files /dev/null and b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/unicode.tar differ
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/unicode.tar.json b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/unicode.tar.json
new file mode 100644
index 0000000..85c631e
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/unicode.tar.json
@@ -0,0 +1,53 @@
+[
+ {
+ "gid": 513,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": true,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": false,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rwx------",
+ "mtime": 1319027321,
+ "path": "2859/",
+ "size": 0,
+ "uid": 500
+ },
+ {
+ "gid": 513,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rwx------",
+ "mtime": 1319027194,
+ "path": "2859/Copy of h\u00e0nz\u00ec-somefile.txt",
+ "size": 0,
+ "uid": 500
+ },
+ {
+ "gid": 513,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rwx------",
+ "mtime": 1319027194,
+ "path": "2859/h\u00e0nz\u00ec?-somefile.txt ",
+ "size": 0,
+ "uid": 500
+ }
+]
\ No newline at end of file
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/unicode.zip b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/unicode.zip
new file mode 100644
index 0000000..c3c5f3f
Binary files /dev/null and b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/unicode.zip differ
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/unicode.zip.json b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/unicode.zip.json
new file mode 100644
index 0000000..a07ba81
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/unicode.zip.json
@@ -0,0 +1,36 @@
+[
+ {
+ "gid": 1000,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": true,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": false,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rwxr-xr-x",
+ "mtime": 1268678396,
+ "path": "a/",
+ "size": 0,
+ "uid": 1000
+ },
+ {
+ "gid": 1000,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-r--r--",
+ "mtime": 1268678259,
+ "path": "a/gr\u00fcn.png",
+ "size": 362,
+ "uid": 1000
+ }
+]
\ No newline at end of file
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/unicode2.zip b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/unicode2.zip
new file mode 100644
index 0000000..22ad48d
Binary files /dev/null and b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/unicode2.zip differ
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/unicode2.zip.json b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/unicode2.zip.json
new file mode 100644
index 0000000..bd34813
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/unicode2.zip.json
@@ -0,0 +1,36 @@
+[
+ {
+ "gid": 0,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": true,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": false,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rwxrwxr-x",
+ "mtime": 1381752672,
+ "path": "a/",
+ "size": 0,
+ "uid": 0
+ },
+ {
+ "gid": 0,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-rw-r--",
+ "mtime": 1268681860,
+ "path": "a/gru\u0308n.png",
+ "size": 362,
+ "uid": 0
+ }
+]
\ No newline at end of file
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/프로그램.README b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/프로그램.README
new file mode 100644
index 0000000..de6ba98
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/프로그램.README
@@ -0,0 +1,3 @@
+Test file from borrowed from
+https://github.com/libarchive/libarchive/issues/459
+http://libarchive.github.io/google-code/issue-350/comment-0/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8.zip
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/프로그램.zip b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/프로그램.zip
new file mode 100644
index 0000000..5407833
Binary files /dev/null and b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/프로그램.zip differ
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/프로그램.zip.json b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/프로그램.zip.json
new file mode 100644
index 0000000..9ba3534
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/data/프로그램.zip.json
@@ -0,0 +1,36 @@
+[
+ {
+ "gid": 502,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-rw-r--",
+ "mtime": 1390485689,
+ "path": "hello.txt",
+ "size": 14,
+ "uid": 502
+ },
+ {
+ "gid": 502,
+ "isblk": false,
+ "ischr": false,
+ "isdev": false,
+ "isdir": false,
+ "isfifo": false,
+ "islnk": false,
+ "isreg": true,
+ "issym": false,
+ "linkpath": null,
+ "mode": "rw-rw-r--",
+ "mtime": 1390485651,
+ "path": "\ud504\ub85c\uadf8\ub7a8.txt",
+ "size": 13,
+ "uid": 502
+ }
+]
\ No newline at end of file
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/test_atime_mtime_ctime.py b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/test_atime_mtime_ctime.py
new file mode 100644
index 0000000..637da36
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/test_atime_mtime_ctime.py
@@ -0,0 +1,127 @@
+from copy import copy
+from os import stat
+
+from libarchive import (file_reader, file_writer, memory_reader, memory_writer)
+
+import pytest
+
+from . import treestat
+
+
+# NOTE: zip does not support high resolution time data, but pax and others do
+def check_atime_ctime(archive, tree, timefmt=int):
+ tree2 = copy(tree)
+ for entry in archive:
+ epath = str(entry).rstrip('/')
+ assert epath in tree2
+ estat = tree2.pop(epath)
+ assert entry.atime == timefmt(estat.st_atime)
+ assert entry.ctime == timefmt(estat.st_ctime)
+
+
+def stat_dict(path):
+ # return the raw stat output, the tuple output only returns ints
+ return stat(path)
+
+
+def time_check(time_tuple, timefmt):
+ seconds, nanos = time_tuple
+ maths = float(seconds) + float(nanos) / 1000000000.0
+ return timefmt(maths)
+
+
+@pytest.mark.parametrize('archfmt,timefmt', [('zip', int), ('pax', float)])
+def test_memory_atime_ctime(archfmt, timefmt):
+ # Collect information on what should be in the archive
+ tree = treestat('libarchive', stat_dict)
+
+ # Create an archive of our libarchive/ directory
+ buf = bytes(bytearray(1000000))
+ with memory_writer(buf, archfmt) as archive1:
+ archive1.add_files('libarchive/')
+
+ # Check the data
+ with memory_reader(buf) as archive2:
+ check_atime_ctime(archive2, tree, timefmt=timefmt)
+
+
+@pytest.mark.parametrize('archfmt,timefmt', [('zip', int), ('pax', float)])
+def test_file_atime_ctime(archfmt, timefmt, tmpdir):
+ archive_path = "{0}/test.{1}".format(tmpdir.strpath, archfmt)
+
+ # Collect information on what should be in the archive
+ tree = treestat('libarchive', stat_dict)
+
+ # Create an archive of our libarchive/ directory
+ with file_writer(archive_path, archfmt) as archive:
+ archive.add_files('libarchive/')
+
+ # Read the archive and check that the data is correct
+ with file_reader(archive_path) as archive:
+ check_atime_ctime(archive, tree, timefmt=timefmt)
+
+
+@pytest.mark.parametrize('archfmt,timefmt', [('zip', int), ('pax', float)])
+def test_memory_time_setters(archfmt, timefmt):
+ has_birthtime = archfmt != 'zip'
+
+ # Create an archive of our libarchive/ directory
+ buf = bytes(bytearray(1000000))
+ with memory_writer(buf, archfmt) as archive1:
+ archive1.add_files('libarchive/')
+
+ atimestamp = (1482144741, 495628118)
+ mtimestamp = (1482155417, 659017086)
+ ctimestamp = (1482145211, 536858081)
+ btimestamp = (1482144740, 495628118)
+ buf2 = bytes(bytearray(1000000))
+ with memory_reader(buf) as archive1:
+ with memory_writer(buf2, archfmt) as archive2:
+ for entry in archive1:
+ entry.set_atime(*atimestamp)
+ entry.set_mtime(*mtimestamp)
+ entry.set_ctime(*ctimestamp)
+ if has_birthtime:
+ entry.set_birthtime(*btimestamp)
+ archive2.add_entries([entry])
+
+ with memory_reader(buf2) as archive2:
+ for entry in archive2:
+ assert entry.atime == time_check(atimestamp, timefmt)
+ assert entry.mtime == time_check(mtimestamp, timefmt)
+ assert entry.ctime == time_check(ctimestamp, timefmt)
+ if has_birthtime:
+ assert entry.birthtime == time_check(btimestamp, timefmt)
+
+
+@pytest.mark.parametrize('archfmt,timefmt', [('zip', int), ('pax', float)])
+def test_file_time_setters(archfmt, timefmt, tmpdir):
+ has_birthtime = archfmt != 'zip'
+
+ # Create an archive of our libarchive/ directory
+ archive_path = tmpdir.join('/test.{0}'.format(archfmt)).strpath
+ archive2_path = tmpdir.join('/test2.{0}'.format(archfmt)).strpath
+ with file_writer(archive_path, archfmt) as archive1:
+ archive1.add_files('libarchive/')
+
+ atimestamp = (1482144741, 495628118)
+ mtimestamp = (1482155417, 659017086)
+ ctimestamp = (1482145211, 536858081)
+ btimestamp = (1482144740, 495628118)
+ with file_reader(archive_path) as archive1:
+ with file_writer(archive2_path, archfmt) as archive2:
+ for entry in archive1:
+ entry.set_atime(*atimestamp)
+ entry.set_mtime(*mtimestamp)
+ entry.set_ctime(*ctimestamp)
+ if has_birthtime:
+ entry.set_birthtime(*btimestamp)
+ archive2.add_entries([entry])
+
+ with file_reader(archive2_path) as archive2:
+ for entry in archive2:
+ assert entry.atime == time_check(atimestamp, timefmt)
+ assert entry.mtime == time_check(mtimestamp, timefmt)
+ assert entry.ctime == time_check(ctimestamp, timefmt)
+ if has_birthtime:
+ assert entry.birthtime == time_check(btimestamp, timefmt)
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/test_convert.py b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/test_convert.py
new file mode 100644
index 0000000..ff1bc75
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/test_convert.py
@@ -0,0 +1,24 @@
+from libarchive import memory_reader, memory_writer
+
+from . import check_archive, treestat
+
+
+def test_convert():
+
+ # Collect information on what should be in the archive
+ tree = treestat('libarchive')
+
+ # Create an archive of our libarchive/ directory
+ buf = bytes(bytearray(1000000))
+ with memory_writer(buf, 'gnutar', 'xz') as archive1:
+ archive1.add_files('libarchive/')
+
+ # Convert the archive to another format
+ buf2 = bytes(bytearray(1000000))
+ with memory_reader(buf) as archive1:
+ with memory_writer(buf2, 'zip') as archive2:
+ archive2.add_entries(archive1)
+
+ # Check the data
+ with memory_reader(buf2) as archive2:
+ check_archive(archive2, tree)
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/test_entry.py b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/test_entry.py
new file mode 100644
index 0000000..419cecb
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/test_entry.py
@@ -0,0 +1,151 @@
+# -*- coding: utf-8 -*-
+
+from codecs import open
+import json
+import locale
+from os import environ, stat
+from os.path import join
+import unicodedata
+
+import pytest
+
+from libarchive import memory_reader, memory_writer
+from libarchive.entry import ArchiveEntry, ConsumedArchiveEntry, PassedArchiveEntry
+
+from . import data_dir, get_entries, get_tarinfos
+
+
+text_type = unicode if str is bytes else str # noqa: F821
+
+locale.setlocale(locale.LC_ALL, '')
+
+# needed for sane time stamp comparison
+environ['TZ'] = 'UTC'
+
+
+def test_entry_properties():
+
+ buf = bytes(bytearray(1000000))
+ with memory_writer(buf, 'gnutar') as archive:
+ archive.add_files('README.rst')
+
+ readme_stat = stat('README.rst')
+
+ with memory_reader(buf) as archive:
+ for entry in archive:
+ assert entry.uid == readme_stat.st_uid
+ assert entry.gid == readme_stat.st_gid
+ assert entry.mode == readme_stat.st_mode
+ assert not entry.isblk
+ assert not entry.ischr
+ assert not entry.isdir
+ assert not entry.isfifo
+ assert not entry.islnk
+ assert not entry.issym
+ assert not entry.linkpath
+ assert entry.linkpath == entry.linkname
+ assert entry.isreg
+ assert entry.isfile
+ assert not entry.issock
+ assert not entry.isdev
+ assert b'rw' in entry.strmode
+ assert entry.pathname == entry.path
+ assert entry.pathname == entry.name
+
+
+def test_check_ArchiveEntry_against_TarInfo():
+ for name in ('special.tar', 'tar_relative.tar'):
+ path = join(data_dir, name)
+ tarinfos = list(get_tarinfos(path))
+ entries = list(get_entries(path))
+ for tarinfo, entry in zip(tarinfos, entries):
+ assert tarinfo == entry
+ assert len(tarinfos) == len(entries)
+
+
+def test_check_archiveentry_using_python_testtar():
+ check_entries(join(data_dir, 'testtar.tar'))
+
+
+def test_check_archiveentry_with_unicode_and_binary_entries_tar():
+ check_entries(join(data_dir, 'unicode.tar'))
+
+
+def test_check_archiveentry_with_unicode_and_binary_entries_zip():
+ check_entries(join(data_dir, 'unicode.zip'))
+
+
+def test_check_archiveentry_with_unicode_and_binary_entries_zip2():
+ check_entries(join(data_dir, 'unicode2.zip'), ignore='mode')
+
+
+def test_check_archiveentry_with_unicode_entries_and_name_zip():
+ check_entries(join(data_dir, '\ud504\ub85c\uadf8\ub7a8.zip'))
+
+
+def check_entries(test_file, regen=False, ignore=''):
+ ignore = ignore.split()
+ fixture_file = test_file + '.json'
+ if regen:
+ entries = list(get_entries(test_file))
+ with open(fixture_file, 'w', encoding='UTF-8') as ex:
+ json.dump(entries, ex, indent=2, sort_keys=True)
+ with open(fixture_file, encoding='UTF-8') as ex:
+ expected = json.load(ex)
+ actual = list(get_entries(test_file))
+ for e1, e2 in zip(actual, expected):
+ for key in ignore:
+ e1.pop(key)
+ e2.pop(key)
+ # Normalize all unicode (can vary depending on the system)
+ for d in (e1, e2):
+ for key in d:
+ if isinstance(d[key], text_type):
+ d[key] = unicodedata.normalize('NFC', d[key])
+ assert e1 == e2
+
+
+def test_the_life_cycle_of_archive_entries():
+ """Check that `get_blocks` only works on the current entry, and only once.
+ """
+ # Create a test archive in memory
+ buf = bytes(bytearray(10_000_000))
+ with memory_writer(buf, 'gnutar') as archive:
+ archive.add_files(
+ 'README.rst',
+ 'libarchive/__init__.py',
+ 'libarchive/entry.py',
+ )
+ # Read multiple entries of the test archive and check how the evolve
+ with memory_reader(buf) as archive:
+ archive_iter = iter(archive)
+ entry1 = next(archive_iter)
+ assert type(entry1) is ArchiveEntry
+ for block in entry1.get_blocks():
+ pass
+ assert type(entry1) is ConsumedArchiveEntry
+ with pytest.raises(TypeError):
+ entry1.get_blocks()
+ entry2 = next(archive_iter)
+ assert type(entry2) is ArchiveEntry
+ assert type(entry1) is PassedArchiveEntry
+ with pytest.raises(TypeError):
+ entry1.get_blocks()
+ entry3 = next(archive_iter)
+ assert type(entry3) is ArchiveEntry
+ assert type(entry2) is PassedArchiveEntry
+ assert type(entry1) is PassedArchiveEntry
+
+
+def test_non_ASCII_encoding_of_file_metadata():
+ buf = bytes(bytearray(100_000))
+ file_name = 'README.rst'
+ encoded_file_name = 'README.rst'.encode('cp037')
+ with memory_writer(buf, 'ustar', header_codec='cp037') as archive:
+ archive.add_file(file_name)
+ with memory_reader(buf) as archive:
+ entry = next(iter(archive))
+ assert entry.pathname == encoded_file_name
+ with memory_reader(buf, header_codec='cp037') as archive:
+ entry = next(iter(archive))
+ assert entry.pathname == file_name
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/test_errors.py b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/test_errors.py
new file mode 100644
index 0000000..513c86a
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/test_errors.py
@@ -0,0 +1,40 @@
+from errno import ENOENT
+
+import pytest
+
+from libarchive import ArchiveError, ffi, memory_writer
+
+
+def test_add_files_nonexistent():
+ with memory_writer(bytes(bytearray(4096)), 'zip') as archive:
+ with pytest.raises(ArchiveError) as e:
+ archive.add_files('nonexistent')
+ assert e.value.msg
+ assert e.value.errno == ENOENT
+ assert e.value.retcode == -25
+
+
+def test_check_int_logs_warnings(monkeypatch):
+ calls = []
+ monkeypatch.setattr(ffi.logger, 'warning', lambda *_: calls.append(1))
+ archive_p = ffi.write_new()
+ ffi.check_int(ffi.ARCHIVE_WARN, print, [archive_p])
+ assert calls == [1]
+
+
+def test_check_null():
+ with pytest.raises(ArchiveError) as e:
+ ffi.check_null(None, print, [])
+ assert str(e)
+
+
+def test_error_string_decoding(monkeypatch):
+ monkeypatch.setattr(ffi, 'error_string', lambda *_: None)
+ r = ffi._error_string(None)
+ assert r is None
+ monkeypatch.setattr(ffi, 'error_string', lambda *_: b'a')
+ r = ffi._error_string(None)
+ assert isinstance(r, type(''))
+ monkeypatch.setattr(ffi, 'error_string', lambda *_: '\xe9'.encode('utf8'))
+ r = ffi._error_string(None)
+ assert isinstance(r, bytes)
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/test_rwx.py b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/test_rwx.py
new file mode 100644
index 0000000..77c16fc
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/test_rwx.py
@@ -0,0 +1,183 @@
+"""Test reading, writing and extracting archives."""
+
+import io
+import json
+
+import libarchive
+from libarchive.entry import format_time
+from libarchive.extract import EXTRACT_OWNER, EXTRACT_PERM, EXTRACT_TIME
+from libarchive.write import memory_writer
+from unittest.mock import patch
+import pytest
+
+from . import check_archive, in_dir, treestat
+
+
+def test_buffers(tmpdir):
+
+ # Collect information on what should be in the archive
+ tree = treestat('libarchive')
+
+ # Create an archive of our libarchive/ directory
+ buf = bytes(bytearray(1000000))
+ with libarchive.memory_writer(buf, 'gnutar', 'xz') as archive:
+ archive.add_files('libarchive/')
+
+ # Read the archive and check that the data is correct
+ with libarchive.memory_reader(buf) as archive:
+ check_archive(archive, tree)
+ assert archive.format_name == b'GNU tar format'
+ assert archive.filter_names == [b'xz']
+
+ # Extract the archive in tmpdir and check that the data is intact
+ with in_dir(tmpdir.strpath):
+ flags = EXTRACT_OWNER | EXTRACT_PERM | EXTRACT_TIME
+ libarchive.extract_memory(buf, flags)
+ tree2 = treestat('libarchive')
+ assert tree2 == tree
+
+
+def test_fd(tmpdir):
+ archive_file = open(tmpdir.strpath+'/test.tar.bz2', 'w+b')
+ fd = archive_file.fileno()
+
+ # Collect information on what should be in the archive
+ tree = treestat('libarchive')
+
+ # Create an archive of our libarchive/ directory
+ with libarchive.fd_writer(fd, 'gnutar', 'bzip2') as archive:
+ archive.add_files('libarchive/')
+
+ # Read the archive and check that the data is correct
+ archive_file.seek(0)
+ with libarchive.fd_reader(fd) as archive:
+ check_archive(archive, tree)
+ assert archive.format_name == b'GNU tar format'
+ assert archive.filter_names == [b'bzip2']
+
+ # Extract the archive in tmpdir and check that the data is intact
+ archive_file.seek(0)
+ with in_dir(tmpdir.strpath):
+ flags = EXTRACT_OWNER | EXTRACT_PERM | EXTRACT_TIME
+ libarchive.extract_fd(fd, flags)
+ tree2 = treestat('libarchive')
+ assert tree2 == tree
+
+
+def test_files(tmpdir):
+ archive_path = tmpdir.strpath+'/test.tar.gz'
+
+ # Collect information on what should be in the archive
+ tree = treestat('libarchive')
+
+ # Create an archive of our libarchive/ directory
+ with libarchive.file_writer(archive_path, 'ustar', 'gzip') as archive:
+ archive.add_files('libarchive/')
+
+ # Read the archive and check that the data is correct
+ with libarchive.file_reader(archive_path) as archive:
+ check_archive(archive, tree)
+ assert archive.format_name == b'POSIX ustar format'
+ assert archive.filter_names == [b'gzip']
+
+ # Extract the archive in tmpdir and check that the data is intact
+ with in_dir(tmpdir.strpath):
+ flags = EXTRACT_OWNER | EXTRACT_PERM | EXTRACT_TIME
+ libarchive.extract_file(archive_path, flags)
+ tree2 = treestat('libarchive')
+ assert tree2 == tree
+
+
+def test_custom_writer_and_stream_reader():
+ # Collect information on what should be in the archive
+ tree = treestat('libarchive')
+
+ # Create an archive of our libarchive/ directory
+ stream = io.BytesIO()
+ with libarchive.custom_writer(stream.write, 'zip') as archive:
+ archive.add_files('libarchive/')
+ stream.seek(0)
+
+ # Read the archive and check that the data is correct
+ with libarchive.stream_reader(stream, 'zip') as archive:
+ check_archive(archive, tree)
+ assert archive.format_name == b'ZIP 2.0 (deflation)'
+ assert archive.filter_names == []
+
+
+@patch('libarchive.ffi.write_fail')
+def test_write_fail(write_fail_mock):
+ buf = bytes(bytearray(1000000))
+ try:
+ with memory_writer(buf, 'gnutar', 'xz') as archive:
+ archive.add_files('libarchive/')
+ raise TypeError
+ except TypeError:
+ pass
+ assert write_fail_mock.called
+
+
+@patch('libarchive.ffi.write_fail')
+def test_write_not_fail(write_fail_mock):
+ buf = bytes(bytearray(1000000))
+ with memory_writer(buf, 'gnutar', 'xz') as archive:
+ archive.add_files('libarchive/')
+ assert not write_fail_mock.called
+
+
+def test_adding_nonexistent_file_to_archive():
+ stream = io.BytesIO()
+ with libarchive.custom_writer(stream.write, 'zip') as archive:
+ with pytest.raises(libarchive.ArchiveError):
+ archive.add_files('nonexistent')
+ archive.add_files('libarchive/')
+
+
+@pytest.mark.parametrize(
+ 'archfmt,data_bytes',
+ [('zip', b'content'),
+ ('gnutar', b''),
+ ('pax', json.dumps({'a': 1, 'b': 2, 'c': 3}).encode()),
+ ('7zip', b'lorem\0ipsum')])
+def test_adding_entry_from_memory(archfmt, data_bytes):
+ entry_path = 'testfile.data'
+ entry_data = data_bytes
+ entry_size = len(data_bytes)
+
+ blocks = []
+
+ archfmt = 'zip'
+ has_birthtime = archfmt != 'zip'
+
+ atime = (1482144741, 495628118)
+ mtime = (1482155417, 659017086)
+ ctime = (1482145211, 536858081)
+ btime = (1482144740, 495628118) if has_birthtime else None
+
+ def write_callback(data):
+ blocks.append(data[:])
+ return len(data)
+
+ with libarchive.custom_writer(write_callback, archfmt) as archive:
+ archive.add_file_from_memory(
+ entry_path, entry_size, entry_data,
+ atime=atime, mtime=mtime, ctime=ctime, birthtime=btime,
+ uid=1000, gid=1000,
+ )
+
+ buf = b''.join(blocks)
+ with libarchive.memory_reader(buf) as memory_archive:
+ for archive_entry in memory_archive:
+ expected = entry_data
+ actual = b''.join(archive_entry.get_blocks())
+ assert expected == actual
+ assert archive_entry.path == entry_path
+ assert archive_entry.atime in (atime[0], format_time(*atime))
+ assert archive_entry.mtime in (mtime[0], format_time(*mtime))
+ assert archive_entry.ctime in (ctime[0], format_time(*ctime))
+ if has_birthtime:
+ assert archive_entry.birthtime in (
+ btime[0], format_time(*btime)
+ )
+ assert archive_entry.uid == 1000
+ assert archive_entry.gid == 1000
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/test_security_flags.py b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/test_security_flags.py
new file mode 100644
index 0000000..f279eaf
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tests/test_security_flags.py
@@ -0,0 +1,36 @@
+"""Test security-related extraction flags."""
+
+import pytest
+import os
+
+from libarchive import extract_file, file_reader
+from libarchive.extract import (
+ EXTRACT_SECURE_NOABSOLUTEPATHS, EXTRACT_SECURE_NODOTDOT,
+)
+from libarchive.exception import ArchiveError
+from . import data_dir
+
+
+def run_test(flags):
+ archive_path = os.path.join(data_dir, 'flags.tar')
+ try:
+ extract_file(archive_path, 0)
+ with pytest.raises(ArchiveError):
+ extract_file(archive_path, flags)
+ finally:
+ with file_reader(archive_path) as archive:
+ for entry in archive:
+ if os.path.exists(entry.pathname):
+ os.remove(entry.pathname)
+
+
+def test_extraction_is_secure_by_default():
+ run_test(None)
+
+
+def test_explicit_no_dot_dot():
+ run_test(EXTRACT_SECURE_NODOTDOT)
+
+
+def test_explicit_no_absolute_paths():
+ run_test(EXTRACT_SECURE_NOABSOLUTEPATHS)
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/tox.ini b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tox.ini
new file mode 100644
index 0000000..bfa1601
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/tox.ini
@@ -0,0 +1,14 @@
+[tox]
+envlist=py38,py39,py310,py311
+skipsdist=True
+
+[testenv]
+passenv = LIBARCHIVE
+commands=
+ python -m pytest -Wd -vv --forked --cov libarchive --cov-report term-missing {toxinidir}/tests {posargs}
+ flake8 {toxinidir}
+deps=
+ flake8
+ pytest
+ pytest-cov
+ pytest-forked
diff --git a/packages/libarchive-c/opengnsys-libarchive-c-5.1/version.py b/packages/libarchive-c/opengnsys-libarchive-c-5.1/version.py
new file mode 100644
index 0000000..40656b7
--- /dev/null
+++ b/packages/libarchive-c/opengnsys-libarchive-c-5.1/version.py
@@ -0,0 +1,45 @@
+# Source: https://github.com/Changaco/version.py
+
+from os.path import dirname, isdir, join
+import re
+from subprocess import CalledProcessError, check_output
+
+
+PREFIX = ''
+
+tag_re = re.compile(r'\btag: %s([0-9][^,]*)\b' % PREFIX)
+version_re = re.compile('^Version: (.+)$', re.M)
+
+
+def get_version():
+ # Return the version if it has been injected into the file by git-archive
+ version = tag_re.search('$Format:%D$')
+ if version:
+ return version.group(1)
+
+ d = dirname(__file__)
+
+ if isdir(join(d, '.git')):
+ # Get the version using "git describe".
+ cmd = 'git describe --tags --match %s[0-9]* --dirty' % PREFIX
+ try:
+ version = check_output(cmd.split()).decode().strip()[len(PREFIX):]
+ except CalledProcessError:
+ raise RuntimeError('Unable to get version number from git tags')
+
+ # PEP 440 compatibility
+ if '-' in version:
+ if version.endswith('-dirty'):
+ raise RuntimeError('The working tree is dirty')
+ version = '.post'.join(version.split('-')[:2])
+
+ else:
+ # Extract the version from the PKG-INFO file.
+ with open(join(d, 'PKG-INFO'), encoding='utf-8', errors='replace') as f:
+ version = version_re.search(f.read()).group(1)
+
+ return version
+
+
+if __name__ == '__main__':
+ print(get_version())
diff --git a/packages/libarchive-c/opengnsys-libarchive-c_5.1.debian.tar.xz b/packages/libarchive-c/opengnsys-libarchive-c_5.1.debian.tar.xz
new file mode 100644
index 0000000..ba9dca8
Binary files /dev/null and b/packages/libarchive-c/opengnsys-libarchive-c_5.1.debian.tar.xz differ