@@ -0,0 +1,3 @@ | |||||
venv | |||||
*.pyc | |||||
*.swp |
@@ -0,0 +1 @@ | |||||
include README.rst |
@@ -0,0 +1,27 @@ | |||||
A `SmartFile`_ Open Source project. `Read more`_ about how SmartFile | |||||
uses and contributes to Open Source software. | |||||
.. figure:: http://www.smartfile.com/images/logo.jpg | |||||
:alt: SmartFile | |||||
Introduction | |||||
------------ | |||||
A complete wrapper for the libarchive library generated using SWIG. | |||||
Also included in the package are compatibility layers for the Python | |||||
zipfile and tarfile modules. | |||||
Libarchive supports the following: | |||||
- Reads a variety of formats, including tar, pax, cpio, zip, xar, lha, ar, cab, mtree, rar, and ISO images. | |||||
- Writes tar, pax, cpio, zip, xar, ar, ISO, mtree, and shar archives. | |||||
- Automatically handles archives compressed with gzip, bzip2, lzip, xz, lzma, or compress. | |||||
For information on installing libarchive and python-libarchive, see the `Building`_. | |||||
For information on using python-libarchive, see `Examples`_ | |||||
.. _SmartFile: http://www.smartfile.com/ | |||||
.. _Read more: http://www.smartfile.com/open-source.html | |||||
.. _Building: http://code.google.com/p/python-libarchive/wiki/Building | |||||
.. _Examples: http://code.google.com/p/python-libarchive/wiki/Examples | |||||
@@ -0,0 +1,216 @@ | |||||
# -*- coding: utf-8 -*- | |||||
# | |||||
# python-libarchive documentation build configuration file, created by | |||||
# sphinx-quickstart on Sat Jan 21 16:28:43 2012. | |||||
# | |||||
# This file is execfile()d with the current directory set to its containing dir. | |||||
# | |||||
# Note that not all possible configuration values are present in this | |||||
# autogenerated file. | |||||
# | |||||
# All configuration values have a default; values that are commented out | |||||
# serve to show the default. | |||||
import sys, os | |||||
# If extensions (or modules to document with autodoc) are in another directory, | |||||
# add these directories to sys.path here. If the directory is relative to the | |||||
# documentation root, use os.path.abspath to make it absolute, like shown here. | |||||
#sys.path.insert(0, os.path.abspath('.')) | |||||
# -- General configuration ----------------------------------------------------- | |||||
# If your documentation needs a minimal Sphinx version, state it here. | |||||
#needs_sphinx = '1.0' | |||||
# Add any Sphinx extension module names here, as strings. They can be extensions | |||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. | |||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest'] | |||||
# Add any paths that contain templates here, relative to this directory. | |||||
templates_path = [] | |||||
# The suffix of source filenames. | |||||
source_suffix = '.rst' | |||||
# The encoding of source files. | |||||
#source_encoding = 'utf-8-sig' | |||||
# The master toctree document. | |||||
master_doc = 'index' | |||||
# General information about the project. | |||||
project = u'python-libarchive' | |||||
copyright = u'2012, Ben Timby' | |||||
# The version info for the project you're documenting, acts as replacement for | |||||
# |version| and |release|, also used in various other places throughout the | |||||
# built documents. | |||||
# | |||||
# The short X.Y version. | |||||
version = '3.0.3' | |||||
# The full version, including alpha/beta/rc tags. | |||||
release = '3.0.3-2' | |||||
# The language for content autogenerated by Sphinx. Refer to documentation | |||||
# for a list of supported languages. | |||||
#language = None | |||||
# There are two options for replacing |today|: either, you set today to some | |||||
# non-false value, then it is used: | |||||
#today = '' | |||||
# Else, today_fmt is used as the format for a strftime call. | |||||
#today_fmt = '%B %d, %Y' | |||||
# List of patterns, relative to source directory, that match files and | |||||
# directories to ignore when looking for source files. | |||||
exclude_patterns = ['_build'] | |||||
# The reST default role (used for this markup: `text`) to use for all documents. | |||||
#default_role = None | |||||
# If true, '()' will be appended to :func: etc. cross-reference text. | |||||
#add_function_parentheses = True | |||||
# If true, the current module name will be prepended to all description | |||||
# unit titles (such as .. function::). | |||||
#add_module_names = True | |||||
# If true, sectionauthor and moduleauthor directives will be shown in the | |||||
# output. They are ignored by default. | |||||
#show_authors = False | |||||
# The name of the Pygments (syntax highlighting) style to use. | |||||
pygments_style = 'sphinx' | |||||
# A list of ignored prefixes for module index sorting. | |||||
#modindex_common_prefix = [] | |||||
# -- Options for HTML output --------------------------------------------------- | |||||
# The theme to use for HTML and HTML Help pages. See the documentation for | |||||
# a list of builtin themes. | |||||
html_theme = 'default' | |||||
# Theme options are theme-specific and customize the look and feel of a theme | |||||
# further. For a list of options available for each theme, see the | |||||
# documentation. | |||||
#html_theme_options = {} | |||||
# Add any paths that contain custom themes here, relative to this directory. | |||||
#html_theme_path = [] | |||||
# The name for this set of Sphinx documents. If None, it defaults to | |||||
# "<project> v<release> documentation". | |||||
#html_title = None | |||||
# A shorter title for the navigation bar. Default is the same as html_title. | |||||
#html_short_title = None | |||||
# The name of an image file (relative to this directory) to place at the top | |||||
# of the sidebar. | |||||
#html_logo = None | |||||
# The name of an image file (within the static path) to use as favicon of the | |||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 | |||||
# pixels large. | |||||
#html_favicon = None | |||||
# Add any paths that contain custom static files (such as style sheets) here, | |||||
# relative to this directory. They are copied after the builtin static files, | |||||
# so a file named "default.css" will overwrite the builtin "default.css". | |||||
html_static_path = [] | |||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, | |||||
# using the given strftime format. | |||||
#html_last_updated_fmt = '%b %d, %Y' | |||||
# If true, SmartyPants will be used to convert quotes and dashes to | |||||
# typographically correct entities. | |||||
#html_use_smartypants = True | |||||
# Custom sidebar templates, maps document names to template names. | |||||
#html_sidebars = {} | |||||
# Additional templates that should be rendered to pages, maps page names to | |||||
# template names. | |||||
#html_additional_pages = {} | |||||
# If false, no module index is generated. | |||||
#html_domain_indices = True | |||||
# If false, no index is generated. | |||||
#html_use_index = True | |||||
# If true, the index is split into individual pages for each letter. | |||||
#html_split_index = False | |||||
# If true, links to the reST sources are added to the pages. | |||||
#html_show_sourcelink = True | |||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. | |||||
#html_show_sphinx = True | |||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. | |||||
#html_show_copyright = True | |||||
# If true, an OpenSearch description file will be output, and all pages will | |||||
# contain a <link> tag referring to it. The value of this option must be the | |||||
# base URL from which the finished HTML is served. | |||||
#html_use_opensearch = '' | |||||
# This is the file name suffix for HTML files (e.g. ".xhtml"). | |||||
#html_file_suffix = None | |||||
# Output file base name for HTML help builder. | |||||
htmlhelp_basename = 'python-libarchivedoc' | |||||
# -- Options for LaTeX output -------------------------------------------------- | |||||
# The paper size ('letter' or 'a4'). | |||||
#latex_paper_size = 'letter' | |||||
# The font size ('10pt', '11pt' or '12pt'). | |||||
#latex_font_size = '10pt' | |||||
# Grouping the document tree into LaTeX files. List of tuples | |||||
# (source start file, target name, title, author, documentclass [howto/manual]). | |||||
latex_documents = [ | |||||
('index', 'python-libarchive.tex', u'python-libarchive Documentation', | |||||
u'Ben Timby', 'manual'), | |||||
] | |||||
# The name of an image file (relative to this directory) to place at the top of | |||||
# the title page. | |||||
#latex_logo = None | |||||
# For "manual" documents, if this is true, then toplevel headings are parts, | |||||
# not chapters. | |||||
#latex_use_parts = False | |||||
# If true, show page references after internal links. | |||||
#latex_show_pagerefs = False | |||||
# If true, show URL addresses after external links. | |||||
#latex_show_urls = False | |||||
# Additional stuff for the LaTeX preamble. | |||||
#latex_preamble = '' | |||||
# Documents to append as an appendix to all manuals. | |||||
#latex_appendices = [] | |||||
# If false, no module index is generated. | |||||
#latex_domain_indices = True | |||||
# -- Options for manual page output -------------------------------------------- | |||||
# One entry per manual page. List of tuples | |||||
# (source start file, name, description, authors, manual section). | |||||
man_pages = [ | |||||
('index', 'python-libarchive', u'python-libarchive Documentation', | |||||
[u'Ben Timby'], 1) | |||||
] |
@@ -0,0 +1,20 @@ | |||||
.. python-libarchive documentation master file, created by | |||||
sphinx-quickstart on Sat Jan 21 16:28:43 2012. | |||||
You can adapt this file completely to your liking, but it should at least | |||||
contain the root `toctree` directive. | |||||
Welcome to python-libarchive's documentation! | |||||
============================================= | |||||
Contents: | |||||
.. toctree:: | |||||
:maxdepth: 2 | |||||
Indices and tables | |||||
================== | |||||
* :ref:`genindex` | |||||
* :ref:`modindex` | |||||
* :ref:`search` | |||||
@@ -0,0 +1,23 @@ | |||||
CFLAGS = -g | |||||
INCLUDE = -I/usr/include -I. | |||||
LIBS = -L/usr/local/lib -l:libarchive.so.13.1.2 | |||||
#if PYTHON_VERSION | |||||
PYVER = $(PYTHON_VERSION) | |||||
#else | |||||
PYVER = 2.7 | |||||
#endif | |||||
all: __libarchive.so | |||||
_libarchive_wrap.c: _libarchive.i | |||||
swig -python -shadow _libarchive.i | |||||
_libarchive_wrap.o: _libarchive_wrap.c | |||||
${CC} -c ${CFLAGS} -fPIC ${INCLUDE} $$(python${PYVER}-config --cflags) _libarchive_wrap.c | |||||
__libarchive.so: _libarchive_wrap.o | |||||
${CC} _libarchive_wrap.o -shared $$(python${PYVER}-config --ldflags) -o __libarchive.so ${LIBS} | |||||
clean: | |||||
rm -f *.o *.so *.pyc |
@@ -0,0 +1,645 @@ | |||||
# Copyright (c) 2011, SmartFile <btimby@smartfile.com> | |||||
# All rights reserved. | |||||
# | |||||
# Redistribution and use in source and binary forms, with or without | |||||
# modification, are permitted provided that the following conditions are met: | |||||
# * Redistributions of source code must retain the above copyright | |||||
# notice, this list of conditions and the following disclaimer. | |||||
# * Redistributions in binary form must reproduce the above copyright | |||||
# notice, this list of conditions and the following disclaimer in the | |||||
# documentation and/or other materials provided with the distribution. | |||||
# * Neither the name of the organization nor the | |||||
# names of its contributors may be used to endorse or promote products | |||||
# derived from this software without specific prior written permission. | |||||
# | |||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY | |||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
import os | |||||
import stat | |||||
import sys | |||||
import time | |||||
import warnings | |||||
from libarchive import _libarchive | |||||
try: | |||||
from cStringIO import StringIO | |||||
except ImportError: | |||||
from StringIO import StringIO | |||||
# Suggested block size for libarchive. Libarchive may adjust it. | |||||
BLOCK_SIZE = 10240 | |||||
MTIME_FORMAT = '' | |||||
# Default encoding scheme. | |||||
ENCODING = 'utf-8' | |||||
# Functions to initialize read/write for various libarchive supported formats and filters. | |||||
FORMATS = { | |||||
None: (_libarchive.archive_read_support_format_all, None), | |||||
'tar': (_libarchive.archive_read_support_format_tar, _libarchive.archive_write_set_format_ustar), | |||||
'pax': (_libarchive.archive_read_support_format_tar, _libarchive.archive_write_set_format_pax), | |||||
'gnu': (_libarchive.archive_read_support_format_gnutar, _libarchive.archive_write_set_format_gnutar), | |||||
'zip': (_libarchive.archive_read_support_format_zip, _libarchive.archive_write_set_format_zip), | |||||
'rar': (_libarchive.archive_read_support_format_rar, None), | |||||
'7zip': (_libarchive.archive_read_support_format_7zip, None), | |||||
'ar': (_libarchive.archive_read_support_format_ar, None), | |||||
'cab': (_libarchive.archive_read_support_format_cab, None), | |||||
'cpio': (_libarchive.archive_read_support_format_cpio, _libarchive.archive_write_set_format_cpio_newc), | |||||
'iso': (_libarchive.archive_read_support_format_iso9660, _libarchive.archive_write_set_format_iso9660), | |||||
'lha': (_libarchive.archive_read_support_format_lha, None), | |||||
'xar': (_libarchive.archive_read_support_format_xar, _libarchive.archive_write_set_format_xar), | |||||
} | |||||
FILTERS = { | |||||
None: (_libarchive.archive_read_support_filter_all, _libarchive.archive_write_add_filter_none), | |||||
'gz': (_libarchive.archive_read_support_filter_gzip, _libarchive.archive_write_add_filter_gzip), | |||||
'bz2': (_libarchive.archive_read_support_filter_bzip2, _libarchive.archive_write_add_filter_bzip2), | |||||
} | |||||
# Map file extensions to formats and filters. To support quick detection. | |||||
FORMAT_EXTENSIONS = { | |||||
'.tar': 'tar', | |||||
'.zip': 'zip', | |||||
'.rar': 'rar', | |||||
'.7z': '7zip', | |||||
'.ar': 'ar', | |||||
'.cab': 'cab', | |||||
'.rpm': 'cpio', | |||||
'.cpio': 'cpio', | |||||
'.iso': 'iso', | |||||
'.lha': 'lha', | |||||
'.xar': 'xar', | |||||
} | |||||
FILTER_EXTENSIONS = { | |||||
'.gz': 'gz', | |||||
'.bz2': 'bz2', | |||||
} | |||||
class EOF(Exception): | |||||
'''Raised by ArchiveInfo.from_archive() when unable to read the next | |||||
archive header.''' | |||||
pass | |||||
def get_error(archive): | |||||
'''Retrieves the last error description for the given archive instance.''' | |||||
return _libarchive.archive_error_string(archive) | |||||
def call_and_check(func, archive, *args): | |||||
'''Executes a libarchive function and raises an exception when appropriate.''' | |||||
ret = func(*args) | |||||
if ret == _libarchive.ARCHIVE_OK: | |||||
return | |||||
elif ret == _libarchive.ARCHIVE_WARN: | |||||
warnings.warn('Warning executing function: %s.' % get_error(archive), RuntimeWarning) | |||||
elif ret == _libarchive.ARCHIVE_EOF: | |||||
raise EOF() | |||||
else: | |||||
raise Exception('Fatal error executing function, message is: %s.' % get_error(archive)) | |||||
def get_func(name, items, index): | |||||
item = items.get(name, None) | |||||
if item is None: | |||||
return None | |||||
return item[index] | |||||
def guess_format(filename): | |||||
filename, ext = os.path.splitext(filename) | |||||
filter = FILTER_EXTENSIONS.get(ext) | |||||
if filter: | |||||
filename, ext = os.path.splitext(filename) | |||||
format = FORMAT_EXTENSIONS.get(ext) | |||||
return format, filter | |||||
def is_archive_name(filename, formats=None): | |||||
'''Quick check to see if the given file has an extension indiciating that it is | |||||
an archive. The format parameter can be used to limit what archive format is acceptable. | |||||
If omitted, all supported archive formats will be checked. | |||||
This function will return the name of the most likely archive format, None if the file is | |||||
unlikely to be an archive.''' | |||||
if formats is None: | |||||
formats = FORMAT_EXTENSIONS.values() | |||||
format, filter = guess_format(filename) | |||||
if format in formats: | |||||
return format | |||||
def is_archive(f, formats=(None, ), filters=(None, )): | |||||
'''Check to see if the given file is actually an archive. The format parameter | |||||
can be used to specify which archive format is acceptable. If ommitted, all supported | |||||
archive formats will be checked. It opens the file using libarchive. If no error is | |||||
received, the file was successfully detected by the libarchive bidding process. | |||||
This procedure is quite costly, so you should avoid calling it unless you are reasonably | |||||
sure that the given file is an archive. In other words, you may wish to filter large | |||||
numbers of file names using is_archive_name() before double-checking the positives with | |||||
this function. | |||||
This function will return True if the file can be opened as an archive using the given | |||||
format(s)/filter(s).''' | |||||
if isinstance(f, basestring): | |||||
f = file(f, 'r') | |||||
a = _libarchive.archive_read_new() | |||||
for format in formats: | |||||
format = get_func(format, FORMATS, 0) | |||||
if format is None: | |||||
return False | |||||
format(a) | |||||
for filter in filters: | |||||
filter = get_func(filter, FILTERS, 0) | |||||
if filter is None: | |||||
return False | |||||
filter(a) | |||||
try: | |||||
try: | |||||
call_and_check(_libarchive.archive_read_open_fd, a, a, f.fileno(), BLOCK_SIZE) | |||||
return True | |||||
except: | |||||
return False | |||||
finally: | |||||
_libarchive.archive_read_close(a) | |||||
_libarchive.archive_read_free(a) | |||||
class EntryReadStream(object): | |||||
'''A file-like object for reading an entry from the archive.''' | |||||
def __init__(self, archive, size): | |||||
self.archive = archive | |||||
self.closed = False | |||||
self.size = size | |||||
self.bytes = 0 | |||||
def __enter__(self): | |||||
return self | |||||
def __exit__(self, *args): | |||||
return | |||||
def __iter__(self): | |||||
if self.closed: | |||||
return | |||||
while True: | |||||
data = self.read(BLOCK_SIZE) | |||||
if not data: | |||||
break | |||||
yield data | |||||
def __len__(self): | |||||
return self.size | |||||
def tell(self): | |||||
return self.bytes | |||||
def read(self, bytes=-1): | |||||
if self.closed: | |||||
return | |||||
if self.bytes == self.size: | |||||
# EOF already reached. | |||||
return | |||||
if bytes < 0: | |||||
bytes = self.size - self.bytes | |||||
elif self.bytes + bytes > self.size: | |||||
# Limit read to remaining bytes | |||||
bytes = self.size - self.bytes | |||||
# Read requested bytes | |||||
data = _libarchive.archive_read_data_into_str(self.archive._a, bytes) | |||||
self.bytes += len(data) | |||||
return data | |||||
def close(self): | |||||
if self.closed: | |||||
return | |||||
# Call archive.close() with _defer True to let it know we have been | |||||
# closed and it is now safe to actually close. | |||||
self.archive.close(_defer=True) | |||||
self.archive = None | |||||
self.closed = True | |||||
class EntryWriteStream(object): | |||||
'''A file-like object for writing an entry to an archive. | |||||
If the size is known ahead of time and provided, then the file contents | |||||
are not buffered but flushed directly to the archive. If size is omitted, | |||||
then the file contents are buffered and flushed in the close() method.''' | |||||
def __init__(self, archive, pathname, size=None): | |||||
self.archive = archive | |||||
self.entry = Entry(pathname=pathname, mtime=time.time(), mode=stat.S_IFREG) | |||||
if size is None: | |||||
self.buffer = StringIO() | |||||
else: | |||||
self.buffer = None | |||||
self.entry.size = size | |||||
self.entry.to_archive(self.archive) | |||||
self.bytes = 0 | |||||
self.closed = False | |||||
def __enter__(self): | |||||
return self | |||||
def __exit__(self, *args): | |||||
self.close() | |||||
def __del__(self): | |||||
self.close() | |||||
def __len__(self): | |||||
return self.bytes | |||||
def tell(self): | |||||
return self.bytes | |||||
def write(self, data): | |||||
if self.closed: | |||||
raise Exception('Cannot write to closed stream.') | |||||
if self.buffer: | |||||
self.buffer.write(data) | |||||
else: | |||||
_libarchive.archive_write_data_from_str(self.archive._a, data) | |||||
self.bytes += len(data) | |||||
def close(self): | |||||
if self.closed: | |||||
return | |||||
if self.buffer: | |||||
self.entry.size = self.buffer.tell() | |||||
self.entry.to_archive(self.archive) | |||||
_libarchive.archive_write_data_from_str(self.archive._a, self.buffer.getvalue()) | |||||
_libarchive.archive_write_finish_entry(self.archive._a) | |||||
# Call archive.close() with _defer True to let it know we have been | |||||
# closed and it is now safe to actually close. | |||||
self.archive.close(_defer=True) | |||||
self.archive = None | |||||
self.closed = True | |||||
class Entry(object): | |||||
'''An entry within an archive. Represents the header data and it's location within the archive.''' | |||||
def __init__(self, pathname=None, size=None, mtime=None, mode=None, hpos=None, encoding=ENCODING): | |||||
self.pathname = pathname | |||||
self.size = size | |||||
self.mtime = mtime | |||||
self.mode = mode | |||||
self.hpos = hpos | |||||
self.encoding = encoding | |||||
@property | |||||
def header_position(self): | |||||
return self.hpos | |||||
@classmethod | |||||
def from_archive(cls, archive, encoding=ENCODING): | |||||
'''Instantiates an Entry class and sets all the properties from an archive header.''' | |||||
e = _libarchive.archive_entry_new() | |||||
try: | |||||
call_and_check(_libarchive.archive_read_next_header2, archive._a, archive._a, e) | |||||
mode = _libarchive.archive_entry_filetype(e) | |||||
mode |= _libarchive.archive_entry_perm(e) | |||||
entry = cls( | |||||
pathname=_libarchive.archive_entry_pathname(e).decode(encoding), | |||||
size=_libarchive.archive_entry_size(e), | |||||
mtime=_libarchive.archive_entry_mtime(e), | |||||
mode=mode, | |||||
hpos=archive.header_position, | |||||
) | |||||
finally: | |||||
_libarchive.archive_entry_free(e) | |||||
return entry | |||||
@classmethod | |||||
def from_file(cls, f, entry=None, encoding=ENCODING): | |||||
'''Instantiates an Entry class and sets all the properties from a file on the file system. | |||||
f can be a file-like object or a path.''' | |||||
if entry is None: | |||||
entry = cls(encoding=encoding) | |||||
if entry.pathname is None: | |||||
if isinstance(f, basestring): | |||||
st = os.stat(f) | |||||
entry.pathname = f | |||||
entry.size = st.st_size | |||||
entry.mtime = st.st_mtime | |||||
entry.mode = st.st_mode | |||||
elif hasattr(f, 'fileno'): | |||||
st = os.fstat(f.fileno()) | |||||
entry.pathname = getattr(f, 'name', None) | |||||
entry.size = st.st_size | |||||
entry.mtime = st.st_mtime | |||||
entry.mode = st.st_mode | |||||
else: | |||||
entry.pathname = getattr(f, 'pathname', None) | |||||
entry.size = getattr(f, 'size', 0) | |||||
entry.mtime = getattr(f, 'mtime', time.time()) | |||||
entry.mode = stat.S_IFREG | |||||
return entry | |||||
def to_archive(self, archive): | |||||
'''Creates an archive header and writes it to the given archive.''' | |||||
e = _libarchive.archive_entry_new() | |||||
try: | |||||
_libarchive.archive_entry_set_pathname(e, self.pathname.encode(self.encoding)) | |||||
_libarchive.archive_entry_set_filetype(e, stat.S_IFMT(self.mode)) | |||||
_libarchive.archive_entry_set_perm(e, stat.S_IMODE(self.mode)) | |||||
_libarchive.archive_entry_set_size(e, self.size) | |||||
_libarchive.archive_entry_set_mtime(e, self.mtime, 0) | |||||
call_and_check(_libarchive.archive_write_header, archive._a, archive._a, e) | |||||
#self.hpos = archive.header_position | |||||
finally: | |||||
_libarchive.archive_entry_free(e) | |||||
def isdir(self): | |||||
return stat.S_ISDIR(self.mode) | |||||
def isfile(self): | |||||
return stat.S_ISREG(self.mode) | |||||
def issym(self): | |||||
return stat.S_ISLNK(self.mode) | |||||
def isfifo(self): | |||||
return stat.S_ISFIFO(self.mode) | |||||
def ischr(self): | |||||
return stat.S_ISCHR(self.mode) | |||||
def isblk(self): | |||||
return stat.S_ISBLK(self.mode) | |||||
class Archive(object): | |||||
'''A low-level archive reader which provides forward-only iteration. Consider | |||||
this a light-weight pythonic libarchive wrapper.''' | |||||
def __init__(self, f, mode='r', format=None, filter=None, entry_class=Entry, encoding=ENCODING, blocksize=BLOCK_SIZE): | |||||
assert mode in ('r', 'w', 'wb', 'a'), 'Mode should be "r", "w", "wb", or "a".' | |||||
self._stream = None | |||||
self.encoding = encoding | |||||
self.blocksize = blocksize | |||||
if isinstance(f, basestring): | |||||
self.filename = f | |||||
f = file(f, mode) | |||||
# Only close it if we opened it... | |||||
self._defer_close = True | |||||
elif hasattr(f, 'fileno'): | |||||
self.filename = getattr(f, 'name', None) | |||||
# Leave the fd alone, caller should manage it... | |||||
self._defer_close = False | |||||
else: | |||||
raise Exception('Provided file is not path or open file.') | |||||
self.f = f | |||||
self.mode = mode | |||||
# Guess the format/filter from file name (if not provided) | |||||
if self.filename: | |||||
if format is None: | |||||
format = guess_format(self.filename)[0] | |||||
if filter is None: | |||||
filter = guess_format(self.filename)[1] | |||||
self.format = format | |||||
self.filter = filter | |||||
# The class to use for entries. | |||||
self.entry_class = entry_class | |||||
# Select filter/format functions. | |||||
if self.mode == 'r': | |||||
self.format_func = get_func(self.format, FORMATS, 0) | |||||
if self.format_func is None: | |||||
raise Exception('Unsupported format %s' % format) | |||||
self.filter_func = get_func(self.filter, FILTERS, 0) | |||||
if self.filter_func is None: | |||||
raise Exception('Unsupported filter %s' % filter) | |||||
else: | |||||
# TODO: how to support appending? | |||||
if self.format is None: | |||||
raise Exception('You must specify a format for writing.') | |||||
self.format_func = get_func(self.format, FORMATS, 1) | |||||
if self.format_func is None: | |||||
raise Exception('Unsupported format %s' % format) | |||||
self.filter_func = get_func(self.filter, FILTERS, 1) | |||||
if self.filter_func is None: | |||||
raise Exception('Unsupported filter %s' % filter) | |||||
# Open the archive, apply filter/format functions. | |||||
self.init() | |||||
def __iter__(self): | |||||
while True: | |||||
try: | |||||
yield self.entry_class.from_archive(self, encoding=self.encoding) | |||||
except EOF: | |||||
break | |||||
def __enter__(self): | |||||
return self | |||||
def __exit__(self, type, value, traceback): | |||||
self.denit() | |||||
def __del__(self): | |||||
self.close() | |||||
def init(self): | |||||
if self.mode == 'r': | |||||
self._a = _libarchive.archive_read_new() | |||||
else: | |||||
self._a = _libarchive.archive_write_new() | |||||
self.format_func(self._a) | |||||
self.filter_func(self._a) | |||||
if self.mode == 'r': | |||||
call_and_check(_libarchive.archive_read_open_fd, self._a, self._a, self.f.fileno(), self.blocksize) | |||||
else: | |||||
call_and_check(_libarchive.archive_write_open_fd, self._a, self._a, self.f.fileno()) | |||||
def denit(self): | |||||
'''Closes and deallocates the archive reader/writer.''' | |||||
if getattr(self, '_a', None) is None: | |||||
return | |||||
try: | |||||
if self.mode == 'r': | |||||
_libarchive.archive_read_close(self._a) | |||||
_libarchive.archive_read_free(self._a) | |||||
elif self.mode == 'w': | |||||
_libarchive.archive_write_close(self._a) | |||||
_libarchive.archive_write_free(self._a) | |||||
finally: | |||||
# We only want one try at this... | |||||
self._a = None | |||||
def close(self, _defer=False): | |||||
# _defer == True is how a stream can notify Archive that the stream is | |||||
# now closed. Calling it directly in not recommended. | |||||
if _defer: | |||||
# This call came from our open stream. | |||||
self._stream = None | |||||
if not self._defer_close: | |||||
# We are not yet ready to close. | |||||
return | |||||
if self._stream is not None: | |||||
# We have a stream open! don't close, but remember we were asked to. | |||||
self._defer_close = True | |||||
return | |||||
self.denit() | |||||
# If there is a file attached... | |||||
if hasattr(self, 'f'): | |||||
# Make sure it is not already closed... | |||||
if getattr(self.f, 'closed', False): | |||||
return | |||||
# Flush it if not read-only... | |||||
if self.f.mode != 'r' and self.f.mode != 'rb': | |||||
self.f.flush() | |||||
os.fsync(self.f.fileno()) | |||||
# and then close it, if we opened it... | |||||
if getattr(self, '_close', None): | |||||
self.f.close() | |||||
@property | |||||
def header_position(self): | |||||
'''The position within the file.''' | |||||
return _libarchive.archive_read_header_position(self._a) | |||||
def iterpaths(self): | |||||
for entry in self: | |||||
yield entry.pathname | |||||
def read(self, size): | |||||
'''Read current archive entry contents into string.''' | |||||
return _libarchive.archive_read_data_into_str(self._a, size) | |||||
def readpath(self, f): | |||||
'''Write current archive entry contents to file. f can be a file-like object or | |||||
a path.''' | |||||
if isinstance(f, basestring): | |||||
basedir = os.path.basename(f) | |||||
if not os.path.exists(basedir): | |||||
os.makedirs(basedir) | |||||
f = file(f, 'w') | |||||
return _libarchive.archive_read_data_into_fd(self._a, f.fileno()) | |||||
def readstream(self, size): | |||||
'''Returns a file-like object for reading current archive entry contents.''' | |||||
self._stream = EntryReadStream(self, size) | |||||
return self._stream | |||||
def write(self, member, data=None): | |||||
'''Writes a string buffer to the archive as the given entry.''' | |||||
if isinstance(member, basestring): | |||||
member = self.entry_class(pathname=member, encoding=self.encoding) | |||||
if data: | |||||
member.size = len(data) | |||||
member.to_archive(self) | |||||
if data: | |||||
_libarchive.archive_write_data_from_str(self._a, data) | |||||
_libarchive.archive_write_finish_entry(self._a) | |||||
def writepath(self, f, pathname=None): | |||||
'''Writes a file to the archive. f can be a file-like object or a path. Uses | |||||
write() to do the actual writing.''' | |||||
member = self.entry_class.from_file(f, encoding=self.encoding) | |||||
if isinstance(f, basestring): | |||||
if os.path.isfile(f): | |||||
f = file(f, 'r') | |||||
if pathname: | |||||
member.pathname = pathname | |||||
if hasattr(f, 'read'): | |||||
# TODO: optimize this to write directly from f to archive. | |||||
self.write(member, data=f.read()) | |||||
else: | |||||
self.write(member) | |||||
def writestream(self, pathname, size=None): | |||||
'''Returns a file-like object for writing a new entry.''' | |||||
self._stream = EntryWriteStream(self, pathname, size) | |||||
return self._stream | |||||
def printlist(self, s=sys.stdout): | |||||
for entry in self: | |||||
s.write(entry.size) | |||||
s.write('\t') | |||||
s.write(entry.mtime.strftime(MTIME_FORMAT)) | |||||
s.write('\t') | |||||
s.write(entry.pathname) | |||||
s.flush() | |||||
class SeekableArchive(Archive): | |||||
'''A class that provides random-access to archive entries. It does this by using one | |||||
or many Archive instances to seek to the correct location. The best performance will | |||||
occur when reading archive entries in the order in which they appear in the archive. | |||||
Reading out of order will cause the archive to be closed and opened each time a | |||||
reverse seek is needed.''' | |||||
def __init__(self, f, **kwargs): | |||||
self._stream = None | |||||
# Convert file to open file. We need this to reopen the archive. | |||||
mode = kwargs.setdefault('mode', 'r') | |||||
if isinstance(f, basestring): | |||||
f = file(f, mode) | |||||
super(SeekableArchive, self).__init__(f, **kwargs) | |||||
self.entries = [] | |||||
self.eof = False | |||||
def __iter__(self): | |||||
for entry in self.entries: | |||||
yield entry | |||||
if not self.eof: | |||||
try: | |||||
for entry in super(SeekableArchive, self).__iter__(): | |||||
self.entries.append(entry) | |||||
yield entry | |||||
except StopIteration: | |||||
self.eof = True | |||||
def reopen(self): | |||||
'''Seeks the underlying fd to 0 position, then opens the archive. If the archive | |||||
is already open, this will effectively re-open it (rewind to the beginning).''' | |||||
self.denit() | |||||
self.f.seek(0) | |||||
self.init() | |||||
def getentry(self, pathname): | |||||
'''Take a name or entry object and returns an entry object.''' | |||||
for entry in self: | |||||
if entry.pathname == pathname: | |||||
return entry | |||||
raise KeyError(pathname) | |||||
def seek(self, entry): | |||||
'''Seeks the archive to the requested entry. Will reopen if necessary.''' | |||||
move = entry.header_position - self.header_position | |||||
if move != 0: | |||||
if move < 0: | |||||
# can't move back, re-open archive: | |||||
self.reopen() | |||||
# move to proper position in stream | |||||
for curr in super(SeekableArchive, self).__iter__(): | |||||
if curr.header_position == entry.header_position: | |||||
break | |||||
def read(self, member): | |||||
'''Return the requested archive entry contents as a string.''' | |||||
entry = self.getentry(member) | |||||
self.seek(entry) | |||||
return super(SeekableArchive, self).read(entry.size) | |||||
def readpath(self, member, f): | |||||
entry = self.getentry(member) | |||||
self.seek(entry) | |||||
return super(SeekableArchive, self).readpath(f) | |||||
def readstream(self, member): | |||||
'''Returns a file-like object for reading requested archive entry contents.''' | |||||
entry = self.getentry(member) | |||||
self.seek(entry) | |||||
self._stream = EntryReadStream(self, entry.size) | |||||
return self._stream |
@@ -0,0 +1,382 @@ | |||||
/* Copyright (c) 2011, SmartFile <btimby@smartfile.com> | |||||
All rights reserved. | |||||
Redistribution and use in source and binary forms, with or without | |||||
modification, are permitted provided that the following conditions are met: | |||||
* Redistributions of source code must retain the above copyright | |||||
notice, this list of conditions and the following disclaimer. | |||||
* Redistributions in binary form must reproduce the above copyright | |||||
notice, this list of conditions and the following disclaimer in the | |||||
documentation and/or other materials provided with the distribution. | |||||
* Neither the name of the organization nor the | |||||
names of its contributors may be used to endorse or promote products | |||||
derived from this software without specific prior written permission. | |||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY | |||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||||
%module _libarchive | |||||
%{ | |||||
#include <archive.h> | |||||
#include <archive_entry.h> | |||||
%} | |||||
%include "typemaps.i" | |||||
%typemap(in) time_t | |||||
{ | |||||
if (PyLong_Check($input)) | |||||
$1 = (time_t) PyLong_AsLong($input); | |||||
else if (PyInt_Check($input)) | |||||
$1 = (time_t) PyInt_AsLong($input); | |||||
else if (PyFloat_Check($input)) | |||||
$1 = (time_t) PyFloat_AsDouble($input); | |||||
else { | |||||
PyErr_SetString(PyExc_TypeError,"Expected a large number"); | |||||
return NULL; | |||||
} | |||||
} | |||||
%typemap(out) time_t | |||||
{ | |||||
$result = PyLong_FromLong((long)$1); | |||||
} | |||||
%typemap(in) int64_t | |||||
{ | |||||
if (PyLong_Check($input)) | |||||
$1 = (int64_t) PyLong_AsLong($input); | |||||
else if (PyInt_Check($input)) | |||||
$1 = (int64_t) PyInt_AsLong($input); | |||||
else if (PyFloat_Check($input)) | |||||
$1 = (int64_t) PyFloat_AsDouble($input); | |||||
else { | |||||
PyErr_SetString(PyExc_TypeError,"Expected a large number"); | |||||
return NULL; | |||||
} | |||||
} | |||||
%typemap(out) int64_t | |||||
{ | |||||
$result = PyLong_FromLong((long)$1); | |||||
} | |||||
typedef unsigned short mode_t; | |||||
# Everything below is from the archive.h and archive_entry.h files. | |||||
# I excluded functions declarations that are not needed. | |||||
/* CONFIGURATION */ | |||||
#include <sys/types.h> | |||||
#include <stddef.h> /* for wchar_t */ | |||||
#include <time.h> | |||||
#if defined(_WIN32) && !defined(__CYGWIN__) | |||||
#include <windows.h> | |||||
#endif | |||||
/* Get appropriate definitions of standard POSIX-style types. */ | |||||
/* These should match the types used in 'struct stat' */ | |||||
#if defined(_WIN32) && !defined(__CYGWIN__) | |||||
#define __LA_INT64_T __int64 | |||||
# if defined(__BORLANDC__) | |||||
# define __LA_UID_T uid_t /* Remove in libarchive 3.2 */ | |||||
# define __LA_GID_T gid_t /* Remove in libarchive 3.2 */ | |||||
# define __LA_DEV_T dev_t | |||||
# define __LA_MODE_T mode_t | |||||
# else | |||||
# define __LA_UID_T short /* Remove in libarchive 3.2 */ | |||||
# define __LA_GID_T short /* Remove in libarchive 3.2 */ | |||||
# define __LA_DEV_T unsigned int | |||||
# define __LA_MODE_T unsigned short | |||||
# endif | |||||
#else | |||||
#include <unistd.h> | |||||
# if defined(_SCO_DS) | |||||
# define __LA_INT64_T long long | |||||
# else | |||||
# define __LA_INT64_T int64_t | |||||
# endif | |||||
# define __LA_UID_T uid_t /* Remove in libarchive 3.2 */ | |||||
# define __LA_GID_T gid_t /* Remove in libarchive 3.2 */ | |||||
# define __LA_DEV_T dev_t | |||||
# define __LA_MODE_T mode_t | |||||
#endif | |||||
/* | |||||
* Remove this for libarchive 3.2, since ino_t is no longer used. | |||||
*/ | |||||
#define __LA_INO_T ino_t | |||||
/* | |||||
* On Windows, define LIBARCHIVE_STATIC if you're building or using a | |||||
* .lib. The default here assumes you're building a DLL. Only | |||||
* libarchive source should ever define __LIBARCHIVE_BUILD. | |||||
*/ | |||||
#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC) | |||||
# ifdef __LIBARCHIVE_BUILD | |||||
# ifdef __GNUC__ | |||||
# define extern __attribute__((dllexport)) extern | |||||
# else | |||||
# define extern __declspec(dllexport) | |||||
# endif | |||||
# else | |||||
# ifdef __GNUC__ | |||||
# define extern | |||||
# else | |||||
# define extern __declspec(dllimport) | |||||
# endif | |||||
# endif | |||||
#else | |||||
/* Static libraries on all platforms and shared libraries on non-Windows. */ | |||||
# define extern | |||||
#endif | |||||
/* STRUCTURES */ | |||||
struct archive; | |||||
struct archive_entry; | |||||
/* ARCHIVE READING */ | |||||
extern struct archive *archive_read_new(void); | |||||
extern int archive_read_free(struct archive *); | |||||
/* opening */ | |||||
extern int archive_read_open_filename(struct archive *, | |||||
const char *_filename, size_t _block_size); | |||||
extern int archive_read_open_memory(struct archive *, | |||||
void * buff, size_t size); | |||||
extern int archive_read_open_memory2(struct archive *a, void *buff, | |||||
size_t size, size_t read_size); | |||||
extern int archive_read_open_fd(struct archive *, int _fd, | |||||
size_t _block_size); | |||||
/* closing */ | |||||
extern int archive_read_close(struct archive *); | |||||
extern int archive_format(struct archive *); | |||||
/* headers */ | |||||
extern int archive_read_next_header2(struct archive *, | |||||
struct archive_entry *); | |||||
extern const struct stat *archive_entry_stat(struct archive_entry *); | |||||
extern __LA_INT64_T archive_read_header_position(struct archive *); | |||||
/* data */ | |||||
extern int archive_read_data_skip(struct archive *); | |||||
extern int archive_read_data_into_fd(struct archive *, int fd); | |||||
/* FILTERS */ | |||||
extern int archive_read_support_filter_all(struct archive *); | |||||
extern int archive_read_support_filter_bzip2(struct archive *); | |||||
extern int archive_read_support_filter_compress(struct archive *); | |||||
extern int archive_read_support_filter_gzip(struct archive *); | |||||
extern int archive_read_support_filter_lzip(struct archive *); | |||||
extern int archive_read_support_filter_lzma(struct archive *); | |||||
extern int archive_read_support_filter_none(struct archive *); | |||||
extern int archive_read_support_filter_rpm(struct archive *); | |||||
extern int archive_read_support_filter_uu(struct archive *); | |||||
extern int archive_read_support_filter_xz(struct archive *); | |||||
/* FORMATS */ | |||||
extern int archive_read_support_format_all(struct archive *); | |||||
extern int archive_read_support_format_7zip(struct archive *); | |||||
extern int archive_read_support_format_ar(struct archive *); | |||||
extern int archive_read_support_format_cab(struct archive *); | |||||
extern int archive_read_support_format_cpio(struct archive *); | |||||
extern int archive_read_support_format_empty(struct archive *); | |||||
extern int archive_read_support_format_gnutar(struct archive *); | |||||
extern int archive_read_support_format_iso9660(struct archive *); | |||||
extern int archive_read_support_format_lha(struct archive *); | |||||
/*extern int archive_read_support_format_mtree(struct archive *);*/ | |||||
extern int archive_read_support_format_rar(struct archive *); | |||||
extern int archive_read_support_format_raw(struct archive *); | |||||
extern int archive_read_support_format_tar(struct archive *); | |||||
extern int archive_read_support_format_xar(struct archive *); | |||||
extern int archive_read_support_format_zip(struct archive *); | |||||
/*extern int archive_read_support_format_by_code(struct archive *, int);*/ | |||||
/* ARCHIVE WRITING */ | |||||
extern struct archive *archive_write_new(void); | |||||
extern int archive_write_free(struct archive *); | |||||
/* opening */ | |||||
extern int archive_write_open(struct archive *, void *, | |||||
archive_open_callback *, archive_write_callback *, | |||||
archive_close_callback *); | |||||
extern int archive_write_open_fd(struct archive *, int _fd); | |||||
extern int archive_write_open_filename(struct archive *, const char *_file); | |||||
extern int archive_write_open_filename_w(struct archive *, | |||||
const wchar_t *_file); | |||||
extern int archive_write_open_memory(struct archive *, | |||||
void *_buffer, size_t _buffSize, size_t *_used); | |||||
/* closing */ | |||||
extern int archive_write_close(struct archive *); | |||||
/* headers */ | |||||
extern int archive_write_header(struct archive *, | |||||
struct archive_entry *); | |||||
/* data */ | |||||
/* commit */ | |||||
extern int archive_write_finish_entry(struct archive *); | |||||
/* FILTERS */ | |||||
extern int archive_write_add_filter_bzip2(struct archive *); | |||||
extern int archive_write_add_filter_compress(struct archive *); | |||||
extern int archive_write_add_filter_gzip(struct archive *); | |||||
extern int archive_write_add_filter_lzip(struct archive *); | |||||
extern int archive_write_add_filter_lzma(struct archive *); | |||||
extern int archive_write_add_filter_none(struct archive *); | |||||
extern int archive_write_add_filter_xz(struct archive *); | |||||
/* FORMATS */ | |||||
/* A convenience function to set the format based on the code or name. */ | |||||
extern int archive_write_set_format(struct archive *, int format_code); | |||||
extern int archive_write_set_format_by_name(struct archive *, | |||||
const char *name); | |||||
/* To minimize link pollution, use one or more of the following. */ | |||||
extern int archive_write_set_format_ar_bsd(struct archive *); | |||||
extern int archive_write_set_format_ar_svr4(struct archive *); | |||||
extern int archive_write_set_format_cpio(struct archive *); | |||||
extern int archive_write_set_format_cpio_newc(struct archive *); | |||||
extern int archive_write_set_format_gnutar(struct archive *); | |||||
extern int archive_write_set_format_iso9660(struct archive *); | |||||
/*extern int archive_write_set_format_mtree(struct archive *);*/ | |||||
/* TODO: int archive_write_set_format_old_tar(struct archive *); */ | |||||
extern int archive_write_set_format_pax(struct archive *); | |||||
extern int archive_write_set_format_pax_restricted(struct archive *); | |||||
extern int archive_write_set_format_shar(struct archive *); | |||||
extern int archive_write_set_format_shar_dump(struct archive *); | |||||
extern int archive_write_set_format_ustar(struct archive *); | |||||
extern int archive_write_set_format_xar(struct archive *); | |||||
extern int archive_write_set_format_zip(struct archive *); | |||||
/* ARCHIVE ENTRY */ | |||||
extern struct archive_entry *archive_entry_new(void); | |||||
extern void archive_entry_free(struct archive_entry *); | |||||
/* ARCHIVE ENTRY PROPERTY ACCESS */ | |||||
/* reading */ | |||||
extern const char *archive_entry_pathname(struct archive_entry *); | |||||
extern const wchar_t *archive_entry_pathname_w(struct archive_entry *); | |||||
extern __LA_INT64_T archive_entry_size(struct archive_entry *); | |||||
extern time_t archive_entry_mtime(struct archive_entry *); | |||||
extern __LA_MODE_T archive_entry_filetype(struct archive_entry *); | |||||
extern __LA_MODE_T archive_entry_perm(struct archive_entry *); | |||||
/* writing */ | |||||
extern void archive_entry_set_pathname(struct archive_entry *, const char *); | |||||
extern void archive_entry_set_size(struct archive_entry *, __LA_INT64_T); | |||||
extern void archive_entry_set_mtime(struct archive_entry *, time_t, long); | |||||
extern void archive_entry_set_filetype(struct archive_entry *, unsigned int); | |||||
extern void archive_entry_set_perm(struct archive_entry *, __LA_MODE_T); | |||||
/* ERROR HANDLING */ | |||||
extern int archive_errno(struct archive *); | |||||
extern const char *archive_error_string(struct archive *); | |||||
/* CONSTANTS */ | |||||
#define ARCHIVE_VERSION_NUMBER 3000001 | |||||
#define ARCHIVE_VERSION_STRING "libarchive 3.0.1b" | |||||
#define ARCHIVE_EOF 1 /* Found end of archive. */ | |||||
#define ARCHIVE_OK 0 /* Operation was successful. */ | |||||
#define ARCHIVE_RETRY (-10) /* Retry might succeed. */ | |||||
#define ARCHIVE_WARN (-20) /* Partial success. */ | |||||
#define ARCHIVE_FAILED (-25) /* Current operation cannot complete. */ | |||||
#define ARCHIVE_FATAL (-30) /* No more operations are possible. */ | |||||
#define ARCHIVE_FILTER_NONE 0 | |||||
#define ARCHIVE_FILTER_GZIP 1 | |||||
#define ARCHIVE_FILTER_BZIP2 2 | |||||
#define ARCHIVE_FILTER_COMPRESS 3 | |||||
#define ARCHIVE_FILTER_PROGRAM 4 | |||||
#define ARCHIVE_FILTER_LZMA 5 | |||||
#define ARCHIVE_FILTER_XZ 6 | |||||
#define ARCHIVE_FILTER_UU 7 | |||||
#define ARCHIVE_FILTER_RPM 8 | |||||
#define ARCHIVE_FILTER_LZIP 9 | |||||
#define ARCHIVE_FORMAT_BASE_MASK 0xff0000 | |||||
#define ARCHIVE_FORMAT_CPIO 0x10000 | |||||
#define ARCHIVE_FORMAT_CPIO_POSIX (ARCHIVE_FORMAT_CPIO | 1) | |||||
#define ARCHIVE_FORMAT_CPIO_BIN_LE (ARCHIVE_FORMAT_CPIO | 2) | |||||
#define ARCHIVE_FORMAT_CPIO_BIN_BE (ARCHIVE_FORMAT_CPIO | 3) | |||||
#define ARCHIVE_FORMAT_CPIO_SVR4_NOCRC (ARCHIVE_FORMAT_CPIO | 4) | |||||
#define ARCHIVE_FORMAT_CPIO_SVR4_CRC (ARCHIVE_FORMAT_CPIO | 5) | |||||
#define ARCHIVE_FORMAT_CPIO_AFIO_LARGE (ARCHIVE_FORMAT_CPIO | 6) | |||||
#define ARCHIVE_FORMAT_SHAR 0x20000 | |||||
#define ARCHIVE_FORMAT_SHAR_BASE (ARCHIVE_FORMAT_SHAR | 1) | |||||
#define ARCHIVE_FORMAT_SHAR_DUMP (ARCHIVE_FORMAT_SHAR | 2) | |||||
#define ARCHIVE_FORMAT_TAR 0x30000 | |||||
#define ARCHIVE_FORMAT_TAR_USTAR (ARCHIVE_FORMAT_TAR | 1) | |||||
#define ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE (ARCHIVE_FORMAT_TAR | 2) | |||||
#define ARCHIVE_FORMAT_TAR_PAX_RESTRICTED (ARCHIVE_FORMAT_TAR | 3) | |||||
#define ARCHIVE_FORMAT_TAR_GNUTAR (ARCHIVE_FORMAT_TAR | 4) | |||||
#define ARCHIVE_FORMAT_ISO9660 0x40000 | |||||
#define ARCHIVE_FORMAT_ISO9660_ROCKRIDGE (ARCHIVE_FORMAT_ISO9660 | 1) | |||||
#define ARCHIVE_FORMAT_ZIP 0x50000 | |||||
#define ARCHIVE_FORMAT_EMPTY 0x60000 | |||||
#define ARCHIVE_FORMAT_AR 0x70000 | |||||
#define ARCHIVE_FORMAT_AR_GNU (ARCHIVE_FORMAT_AR | 1) | |||||
#define ARCHIVE_FORMAT_AR_BSD (ARCHIVE_FORMAT_AR | 2) | |||||
#define ARCHIVE_FORMAT_MTREE 0x80000 | |||||
#define ARCHIVE_FORMAT_RAW 0x90000 | |||||
#define ARCHIVE_FORMAT_XAR 0xA0000 | |||||
#define ARCHIVE_FORMAT_LHA 0xB0000 | |||||
#define ARCHIVE_FORMAT_CAB 0xC0000 | |||||
#define ARCHIVE_FORMAT_RAR 0xD0000 | |||||
#define ARCHIVE_FORMAT_7ZIP 0xE0000 | |||||
#define ARCHIVE_EXTRACT_OWNER (0x0001) | |||||
#define ARCHIVE_EXTRACT_PERM (0x0002) | |||||
#define ARCHIVE_EXTRACT_TIME (0x0004) | |||||
#define ARCHIVE_EXTRACT_NO_OVERWRITE (0x0008) | |||||
#define ARCHIVE_EXTRACT_UNLINK (0x0010) | |||||
#define ARCHIVE_EXTRACT_ACL (0x0020) | |||||
#define ARCHIVE_EXTRACT_FFLAGS (0x0040) | |||||
#define ARCHIVE_EXTRACT_XATTR (0x0080) | |||||
#define ARCHIVE_EXTRACT_SECURE_SYMLINKS (0x0100) | |||||
#define ARCHIVE_EXTRACT_SECURE_NODOTDOT (0x0200) | |||||
#define ARCHIVE_EXTRACT_NO_AUTODIR (0x0400) | |||||
#define ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER (0x0800) | |||||
#define ARCHIVE_EXTRACT_SPARSE (0x1000) | |||||
#define ARCHIVE_EXTRACT_MAC_METADATA (0x2000) | |||||
%inline %{ | |||||
PyObject *archive_read_data_into_str(struct archive *archive, int len) { | |||||
PyObject *str = NULL; | |||||
if (!(str = PyString_FromStringAndSize(NULL, len))) { | |||||
PyErr_SetString(PyExc_MemoryError, "could not allocate string."); | |||||
return NULL; | |||||
} | |||||
if (len != archive_read_data(archive, PyString_AS_STRING(str), len)) { | |||||
PyErr_SetString(PyExc_RuntimeError, "could not read requested data."); | |||||
return NULL; | |||||
} | |||||
return str; | |||||
} | |||||
PyObject *archive_write_data_from_str(struct archive *archive, PyObject *str) { | |||||
int len = PyString_Size(str); | |||||
if (!archive_write_data(archive, PyString_AS_STRING(str), len)) { | |||||
PyErr_SetString(PyExc_RuntimeError, "could not write requested data."); | |||||
return NULL; | |||||
} | |||||
return PyInt_FromLong(len); | |||||
} | |||||
%} |
@@ -0,0 +1,478 @@ | |||||
# This file was automatically generated by SWIG (http://www.swig.org). | |||||
# Version 2.0.4 | |||||
# | |||||
# Do not make changes to this file unless you know what you are doing--modify | |||||
# the SWIG interface file instead. | |||||
from sys import version_info | |||||
if version_info >= (2,6,0): | |||||
def swig_import_helper(): | |||||
from os.path import dirname | |||||
import imp | |||||
fp = None | |||||
try: | |||||
fp, pathname, description = imp.find_module('__libarchive', [dirname(__file__)]) | |||||
except ImportError: | |||||
import __libarchive | |||||
return __libarchive | |||||
if fp is not None: | |||||
try: | |||||
_mod = imp.load_module('__libarchive', fp, pathname, description) | |||||
finally: | |||||
fp.close() | |||||
return _mod | |||||
__libarchive = swig_import_helper() | |||||
del swig_import_helper | |||||
else: | |||||
import __libarchive | |||||
del version_info | |||||
try: | |||||
_swig_property = property | |||||
except NameError: | |||||
pass # Python < 2.2 doesn't have 'property'. | |||||
def _swig_setattr_nondynamic(self,class_type,name,value,static=1): | |||||
if (name == "thisown"): return self.this.own(value) | |||||
if (name == "this"): | |||||
if type(value).__name__ == 'SwigPyObject': | |||||
self.__dict__[name] = value | |||||
return | |||||
method = class_type.__swig_setmethods__.get(name,None) | |||||
if method: return method(self,value) | |||||
if (not static): | |||||
self.__dict__[name] = value | |||||
else: | |||||
raise AttributeError("You cannot add attributes to %s" % self) | |||||
def _swig_setattr(self,class_type,name,value): | |||||
return _swig_setattr_nondynamic(self,class_type,name,value,0) | |||||
def _swig_getattr(self,class_type,name): | |||||
if (name == "thisown"): return self.this.own() | |||||
method = class_type.__swig_getmethods__.get(name,None) | |||||
if method: return method(self) | |||||
raise AttributeError(name) | |||||
def _swig_repr(self): | |||||
try: strthis = "proxy of " + self.this.__repr__() | |||||
except: strthis = "" | |||||
return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) | |||||
try: | |||||
_object = object | |||||
_newclass = 1 | |||||
except AttributeError: | |||||
class _object : pass | |||||
_newclass = 0 | |||||
def archive_read_new(): | |||||
return __libarchive.archive_read_new() | |||||
archive_read_new = __libarchive.archive_read_new | |||||
def archive_read_free(*args): | |||||
return __libarchive.archive_read_free(*args) | |||||
archive_read_free = __libarchive.archive_read_free | |||||
def archive_read_open_filename(*args): | |||||
return __libarchive.archive_read_open_filename(*args) | |||||
archive_read_open_filename = __libarchive.archive_read_open_filename | |||||
def archive_read_open_memory(*args): | |||||
return __libarchive.archive_read_open_memory(*args) | |||||
archive_read_open_memory = __libarchive.archive_read_open_memory | |||||
def archive_read_open_memory2(*args): | |||||
return __libarchive.archive_read_open_memory2(*args) | |||||
archive_read_open_memory2 = __libarchive.archive_read_open_memory2 | |||||
def archive_read_open_fd(*args): | |||||
return __libarchive.archive_read_open_fd(*args) | |||||
archive_read_open_fd = __libarchive.archive_read_open_fd | |||||
def archive_read_close(*args): | |||||
return __libarchive.archive_read_close(*args) | |||||
archive_read_close = __libarchive.archive_read_close | |||||
def archive_format(*args): | |||||
return __libarchive.archive_format(*args) | |||||
archive_format = __libarchive.archive_format | |||||
def archive_read_next_header2(*args): | |||||
return __libarchive.archive_read_next_header2(*args) | |||||
archive_read_next_header2 = __libarchive.archive_read_next_header2 | |||||
def archive_entry_stat(*args): | |||||
return __libarchive.archive_entry_stat(*args) | |||||
archive_entry_stat = __libarchive.archive_entry_stat | |||||
def archive_read_header_position(*args): | |||||
return __libarchive.archive_read_header_position(*args) | |||||
archive_read_header_position = __libarchive.archive_read_header_position | |||||
def archive_read_data_skip(*args): | |||||
return __libarchive.archive_read_data_skip(*args) | |||||
archive_read_data_skip = __libarchive.archive_read_data_skip | |||||
def archive_read_data_into_fd(*args): | |||||
return __libarchive.archive_read_data_into_fd(*args) | |||||
archive_read_data_into_fd = __libarchive.archive_read_data_into_fd | |||||
def archive_read_support_filter_all(*args): | |||||
return __libarchive.archive_read_support_filter_all(*args) | |||||
archive_read_support_filter_all = __libarchive.archive_read_support_filter_all | |||||
def archive_read_support_filter_bzip2(*args): | |||||
return __libarchive.archive_read_support_filter_bzip2(*args) | |||||
archive_read_support_filter_bzip2 = __libarchive.archive_read_support_filter_bzip2 | |||||
def archive_read_support_filter_compress(*args): | |||||
return __libarchive.archive_read_support_filter_compress(*args) | |||||
archive_read_support_filter_compress = __libarchive.archive_read_support_filter_compress | |||||
def archive_read_support_filter_gzip(*args): | |||||
return __libarchive.archive_read_support_filter_gzip(*args) | |||||
archive_read_support_filter_gzip = __libarchive.archive_read_support_filter_gzip | |||||
def archive_read_support_filter_lzip(*args): | |||||
return __libarchive.archive_read_support_filter_lzip(*args) | |||||
archive_read_support_filter_lzip = __libarchive.archive_read_support_filter_lzip | |||||
def archive_read_support_filter_lzma(*args): | |||||
return __libarchive.archive_read_support_filter_lzma(*args) | |||||
archive_read_support_filter_lzma = __libarchive.archive_read_support_filter_lzma | |||||
def archive_read_support_filter_none(*args): | |||||
return __libarchive.archive_read_support_filter_none(*args) | |||||
archive_read_support_filter_none = __libarchive.archive_read_support_filter_none | |||||
def archive_read_support_filter_rpm(*args): | |||||
return __libarchive.archive_read_support_filter_rpm(*args) | |||||
archive_read_support_filter_rpm = __libarchive.archive_read_support_filter_rpm | |||||
def archive_read_support_filter_uu(*args): | |||||
return __libarchive.archive_read_support_filter_uu(*args) | |||||
archive_read_support_filter_uu = __libarchive.archive_read_support_filter_uu | |||||
def archive_read_support_filter_xz(*args): | |||||
return __libarchive.archive_read_support_filter_xz(*args) | |||||
archive_read_support_filter_xz = __libarchive.archive_read_support_filter_xz | |||||
def archive_read_support_format_all(*args): | |||||
return __libarchive.archive_read_support_format_all(*args) | |||||
archive_read_support_format_all = __libarchive.archive_read_support_format_all | |||||
def archive_read_support_format_7zip(*args): | |||||
return __libarchive.archive_read_support_format_7zip(*args) | |||||
archive_read_support_format_7zip = __libarchive.archive_read_support_format_7zip | |||||
def archive_read_support_format_ar(*args): | |||||
return __libarchive.archive_read_support_format_ar(*args) | |||||
archive_read_support_format_ar = __libarchive.archive_read_support_format_ar | |||||
def archive_read_support_format_cab(*args): | |||||
return __libarchive.archive_read_support_format_cab(*args) | |||||
archive_read_support_format_cab = __libarchive.archive_read_support_format_cab | |||||
def archive_read_support_format_cpio(*args): | |||||
return __libarchive.archive_read_support_format_cpio(*args) | |||||
archive_read_support_format_cpio = __libarchive.archive_read_support_format_cpio | |||||
def archive_read_support_format_empty(*args): | |||||
return __libarchive.archive_read_support_format_empty(*args) | |||||
archive_read_support_format_empty = __libarchive.archive_read_support_format_empty | |||||
def archive_read_support_format_gnutar(*args): | |||||
return __libarchive.archive_read_support_format_gnutar(*args) | |||||
archive_read_support_format_gnutar = __libarchive.archive_read_support_format_gnutar | |||||
def archive_read_support_format_iso9660(*args): | |||||
return __libarchive.archive_read_support_format_iso9660(*args) | |||||
archive_read_support_format_iso9660 = __libarchive.archive_read_support_format_iso9660 | |||||
def archive_read_support_format_lha(*args): | |||||
return __libarchive.archive_read_support_format_lha(*args) | |||||
archive_read_support_format_lha = __libarchive.archive_read_support_format_lha | |||||
def archive_read_support_format_rar(*args): | |||||
return __libarchive.archive_read_support_format_rar(*args) | |||||
archive_read_support_format_rar = __libarchive.archive_read_support_format_rar | |||||
def archive_read_support_format_raw(*args): | |||||
return __libarchive.archive_read_support_format_raw(*args) | |||||
archive_read_support_format_raw = __libarchive.archive_read_support_format_raw | |||||
def archive_read_support_format_tar(*args): | |||||
return __libarchive.archive_read_support_format_tar(*args) | |||||
archive_read_support_format_tar = __libarchive.archive_read_support_format_tar | |||||
def archive_read_support_format_xar(*args): | |||||
return __libarchive.archive_read_support_format_xar(*args) | |||||
archive_read_support_format_xar = __libarchive.archive_read_support_format_xar | |||||
def archive_read_support_format_zip(*args): | |||||
return __libarchive.archive_read_support_format_zip(*args) | |||||
archive_read_support_format_zip = __libarchive.archive_read_support_format_zip | |||||
def archive_write_new(): | |||||
return __libarchive.archive_write_new() | |||||
archive_write_new = __libarchive.archive_write_new | |||||
def archive_write_free(*args): | |||||
return __libarchive.archive_write_free(*args) | |||||
archive_write_free = __libarchive.archive_write_free | |||||
def archive_write_open(*args): | |||||
return __libarchive.archive_write_open(*args) | |||||
archive_write_open = __libarchive.archive_write_open | |||||
def archive_write_open_fd(*args): | |||||
return __libarchive.archive_write_open_fd(*args) | |||||
archive_write_open_fd = __libarchive.archive_write_open_fd | |||||
def archive_write_open_filename(*args): | |||||
return __libarchive.archive_write_open_filename(*args) | |||||
archive_write_open_filename = __libarchive.archive_write_open_filename | |||||
def archive_write_open_filename_w(*args): | |||||
return __libarchive.archive_write_open_filename_w(*args) | |||||
archive_write_open_filename_w = __libarchive.archive_write_open_filename_w | |||||
def archive_write_open_memory(*args): | |||||
return __libarchive.archive_write_open_memory(*args) | |||||
archive_write_open_memory = __libarchive.archive_write_open_memory | |||||
def archive_write_close(*args): | |||||
return __libarchive.archive_write_close(*args) | |||||
archive_write_close = __libarchive.archive_write_close | |||||
def archive_write_header(*args): | |||||
return __libarchive.archive_write_header(*args) | |||||
archive_write_header = __libarchive.archive_write_header | |||||
def archive_write_finish_entry(*args): | |||||
return __libarchive.archive_write_finish_entry(*args) | |||||
archive_write_finish_entry = __libarchive.archive_write_finish_entry | |||||
def archive_write_add_filter_bzip2(*args): | |||||
return __libarchive.archive_write_add_filter_bzip2(*args) | |||||
archive_write_add_filter_bzip2 = __libarchive.archive_write_add_filter_bzip2 | |||||
def archive_write_add_filter_compress(*args): | |||||
return __libarchive.archive_write_add_filter_compress(*args) | |||||
archive_write_add_filter_compress = __libarchive.archive_write_add_filter_compress | |||||
def archive_write_add_filter_gzip(*args): | |||||
return __libarchive.archive_write_add_filter_gzip(*args) | |||||
archive_write_add_filter_gzip = __libarchive.archive_write_add_filter_gzip | |||||
def archive_write_add_filter_lzip(*args): | |||||
return __libarchive.archive_write_add_filter_lzip(*args) | |||||
archive_write_add_filter_lzip = __libarchive.archive_write_add_filter_lzip | |||||
def archive_write_add_filter_lzma(*args): | |||||
return __libarchive.archive_write_add_filter_lzma(*args) | |||||
archive_write_add_filter_lzma = __libarchive.archive_write_add_filter_lzma | |||||
def archive_write_add_filter_none(*args): | |||||
return __libarchive.archive_write_add_filter_none(*args) | |||||
archive_write_add_filter_none = __libarchive.archive_write_add_filter_none | |||||
def archive_write_add_filter_xz(*args): | |||||
return __libarchive.archive_write_add_filter_xz(*args) | |||||
archive_write_add_filter_xz = __libarchive.archive_write_add_filter_xz | |||||
def archive_write_set_format(*args): | |||||
return __libarchive.archive_write_set_format(*args) | |||||
archive_write_set_format = __libarchive.archive_write_set_format | |||||
def archive_write_set_format_by_name(*args): | |||||
return __libarchive.archive_write_set_format_by_name(*args) | |||||
archive_write_set_format_by_name = __libarchive.archive_write_set_format_by_name | |||||
def archive_write_set_format_ar_bsd(*args): | |||||
return __libarchive.archive_write_set_format_ar_bsd(*args) | |||||
archive_write_set_format_ar_bsd = __libarchive.archive_write_set_format_ar_bsd | |||||
def archive_write_set_format_ar_svr4(*args): | |||||
return __libarchive.archive_write_set_format_ar_svr4(*args) | |||||
archive_write_set_format_ar_svr4 = __libarchive.archive_write_set_format_ar_svr4 | |||||
def archive_write_set_format_cpio(*args): | |||||
return __libarchive.archive_write_set_format_cpio(*args) | |||||
archive_write_set_format_cpio = __libarchive.archive_write_set_format_cpio | |||||
def archive_write_set_format_cpio_newc(*args): | |||||
return __libarchive.archive_write_set_format_cpio_newc(*args) | |||||
archive_write_set_format_cpio_newc = __libarchive.archive_write_set_format_cpio_newc | |||||
def archive_write_set_format_gnutar(*args): | |||||
return __libarchive.archive_write_set_format_gnutar(*args) | |||||
archive_write_set_format_gnutar = __libarchive.archive_write_set_format_gnutar | |||||
def archive_write_set_format_iso9660(*args): | |||||
return __libarchive.archive_write_set_format_iso9660(*args) | |||||
archive_write_set_format_iso9660 = __libarchive.archive_write_set_format_iso9660 | |||||
def archive_write_set_format_pax(*args): | |||||
return __libarchive.archive_write_set_format_pax(*args) | |||||
archive_write_set_format_pax = __libarchive.archive_write_set_format_pax | |||||
def archive_write_set_format_pax_restricted(*args): | |||||
return __libarchive.archive_write_set_format_pax_restricted(*args) | |||||
archive_write_set_format_pax_restricted = __libarchive.archive_write_set_format_pax_restricted | |||||
def archive_write_set_format_shar(*args): | |||||
return __libarchive.archive_write_set_format_shar(*args) | |||||
archive_write_set_format_shar = __libarchive.archive_write_set_format_shar | |||||
def archive_write_set_format_shar_dump(*args): | |||||
return __libarchive.archive_write_set_format_shar_dump(*args) | |||||
archive_write_set_format_shar_dump = __libarchive.archive_write_set_format_shar_dump | |||||
def archive_write_set_format_ustar(*args): | |||||
return __libarchive.archive_write_set_format_ustar(*args) | |||||
archive_write_set_format_ustar = __libarchive.archive_write_set_format_ustar | |||||
def archive_write_set_format_xar(*args): | |||||
return __libarchive.archive_write_set_format_xar(*args) | |||||
archive_write_set_format_xar = __libarchive.archive_write_set_format_xar | |||||
def archive_write_set_format_zip(*args): | |||||
return __libarchive.archive_write_set_format_zip(*args) | |||||
archive_write_set_format_zip = __libarchive.archive_write_set_format_zip | |||||
def archive_entry_new(): | |||||
return __libarchive.archive_entry_new() | |||||
archive_entry_new = __libarchive.archive_entry_new | |||||
def archive_entry_free(*args): | |||||
return __libarchive.archive_entry_free(*args) | |||||
archive_entry_free = __libarchive.archive_entry_free | |||||
def archive_entry_pathname(*args): | |||||
return __libarchive.archive_entry_pathname(*args) | |||||
archive_entry_pathname = __libarchive.archive_entry_pathname | |||||
def archive_entry_pathname_w(*args): | |||||
return __libarchive.archive_entry_pathname_w(*args) | |||||
archive_entry_pathname_w = __libarchive.archive_entry_pathname_w | |||||
def archive_entry_size(*args): | |||||
return __libarchive.archive_entry_size(*args) | |||||
archive_entry_size = __libarchive.archive_entry_size | |||||
def archive_entry_mtime(*args): | |||||
return __libarchive.archive_entry_mtime(*args) | |||||
archive_entry_mtime = __libarchive.archive_entry_mtime | |||||
def archive_entry_filetype(*args): | |||||
return __libarchive.archive_entry_filetype(*args) | |||||
archive_entry_filetype = __libarchive.archive_entry_filetype | |||||
def archive_entry_perm(*args): | |||||
return __libarchive.archive_entry_perm(*args) | |||||
archive_entry_perm = __libarchive.archive_entry_perm | |||||
def archive_entry_set_pathname(*args): | |||||
return __libarchive.archive_entry_set_pathname(*args) | |||||
archive_entry_set_pathname = __libarchive.archive_entry_set_pathname | |||||
def archive_entry_set_size(*args): | |||||
return __libarchive.archive_entry_set_size(*args) | |||||
archive_entry_set_size = __libarchive.archive_entry_set_size | |||||
def archive_entry_set_mtime(*args): | |||||
return __libarchive.archive_entry_set_mtime(*args) | |||||
archive_entry_set_mtime = __libarchive.archive_entry_set_mtime | |||||
def archive_entry_set_filetype(*args): | |||||
return __libarchive.archive_entry_set_filetype(*args) | |||||
archive_entry_set_filetype = __libarchive.archive_entry_set_filetype | |||||
def archive_entry_set_perm(*args): | |||||
return __libarchive.archive_entry_set_perm(*args) | |||||
archive_entry_set_perm = __libarchive.archive_entry_set_perm | |||||
def archive_errno(*args): | |||||
return __libarchive.archive_errno(*args) | |||||
archive_errno = __libarchive.archive_errno | |||||
def archive_error_string(*args): | |||||
return __libarchive.archive_error_string(*args) | |||||
archive_error_string = __libarchive.archive_error_string | |||||
ARCHIVE_VERSION_NUMBER = __libarchive.ARCHIVE_VERSION_NUMBER | |||||
ARCHIVE_VERSION_STRING = __libarchive.ARCHIVE_VERSION_STRING | |||||
ARCHIVE_EOF = __libarchive.ARCHIVE_EOF | |||||
ARCHIVE_OK = __libarchive.ARCHIVE_OK | |||||
ARCHIVE_RETRY = __libarchive.ARCHIVE_RETRY | |||||
ARCHIVE_WARN = __libarchive.ARCHIVE_WARN | |||||
ARCHIVE_FAILED = __libarchive.ARCHIVE_FAILED | |||||
ARCHIVE_FATAL = __libarchive.ARCHIVE_FATAL | |||||
ARCHIVE_FILTER_NONE = __libarchive.ARCHIVE_FILTER_NONE | |||||
ARCHIVE_FILTER_GZIP = __libarchive.ARCHIVE_FILTER_GZIP | |||||
ARCHIVE_FILTER_BZIP2 = __libarchive.ARCHIVE_FILTER_BZIP2 | |||||
ARCHIVE_FILTER_COMPRESS = __libarchive.ARCHIVE_FILTER_COMPRESS | |||||
ARCHIVE_FILTER_PROGRAM = __libarchive.ARCHIVE_FILTER_PROGRAM | |||||
ARCHIVE_FILTER_LZMA = __libarchive.ARCHIVE_FILTER_LZMA | |||||
ARCHIVE_FILTER_XZ = __libarchive.ARCHIVE_FILTER_XZ | |||||
ARCHIVE_FILTER_UU = __libarchive.ARCHIVE_FILTER_UU | |||||
ARCHIVE_FILTER_RPM = __libarchive.ARCHIVE_FILTER_RPM | |||||
ARCHIVE_FILTER_LZIP = __libarchive.ARCHIVE_FILTER_LZIP | |||||
ARCHIVE_FORMAT_BASE_MASK = __libarchive.ARCHIVE_FORMAT_BASE_MASK | |||||
ARCHIVE_FORMAT_CPIO = __libarchive.ARCHIVE_FORMAT_CPIO | |||||
ARCHIVE_FORMAT_CPIO_POSIX = __libarchive.ARCHIVE_FORMAT_CPIO_POSIX | |||||
ARCHIVE_FORMAT_CPIO_BIN_LE = __libarchive.ARCHIVE_FORMAT_CPIO_BIN_LE | |||||
ARCHIVE_FORMAT_CPIO_BIN_BE = __libarchive.ARCHIVE_FORMAT_CPIO_BIN_BE | |||||
ARCHIVE_FORMAT_CPIO_SVR4_NOCRC = __libarchive.ARCHIVE_FORMAT_CPIO_SVR4_NOCRC | |||||
ARCHIVE_FORMAT_CPIO_SVR4_CRC = __libarchive.ARCHIVE_FORMAT_CPIO_SVR4_CRC | |||||
ARCHIVE_FORMAT_CPIO_AFIO_LARGE = __libarchive.ARCHIVE_FORMAT_CPIO_AFIO_LARGE | |||||
ARCHIVE_FORMAT_SHAR = __libarchive.ARCHIVE_FORMAT_SHAR | |||||
ARCHIVE_FORMAT_SHAR_BASE = __libarchive.ARCHIVE_FORMAT_SHAR_BASE | |||||
ARCHIVE_FORMAT_SHAR_DUMP = __libarchive.ARCHIVE_FORMAT_SHAR_DUMP | |||||
ARCHIVE_FORMAT_TAR = __libarchive.ARCHIVE_FORMAT_TAR | |||||
ARCHIVE_FORMAT_TAR_USTAR = __libarchive.ARCHIVE_FORMAT_TAR_USTAR | |||||
ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE = __libarchive.ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE | |||||
ARCHIVE_FORMAT_TAR_PAX_RESTRICTED = __libarchive.ARCHIVE_FORMAT_TAR_PAX_RESTRICTED | |||||
ARCHIVE_FORMAT_TAR_GNUTAR = __libarchive.ARCHIVE_FORMAT_TAR_GNUTAR | |||||
ARCHIVE_FORMAT_ISO9660 = __libarchive.ARCHIVE_FORMAT_ISO9660 | |||||
ARCHIVE_FORMAT_ISO9660_ROCKRIDGE = __libarchive.ARCHIVE_FORMAT_ISO9660_ROCKRIDGE | |||||
ARCHIVE_FORMAT_ZIP = __libarchive.ARCHIVE_FORMAT_ZIP | |||||
ARCHIVE_FORMAT_EMPTY = __libarchive.ARCHIVE_FORMAT_EMPTY | |||||
ARCHIVE_FORMAT_AR = __libarchive.ARCHIVE_FORMAT_AR | |||||
ARCHIVE_FORMAT_AR_GNU = __libarchive.ARCHIVE_FORMAT_AR_GNU | |||||
ARCHIVE_FORMAT_AR_BSD = __libarchive.ARCHIVE_FORMAT_AR_BSD | |||||
ARCHIVE_FORMAT_MTREE = __libarchive.ARCHIVE_FORMAT_MTREE | |||||
ARCHIVE_FORMAT_RAW = __libarchive.ARCHIVE_FORMAT_RAW | |||||
ARCHIVE_FORMAT_XAR = __libarchive.ARCHIVE_FORMAT_XAR | |||||
ARCHIVE_FORMAT_LHA = __libarchive.ARCHIVE_FORMAT_LHA | |||||
ARCHIVE_FORMAT_CAB = __libarchive.ARCHIVE_FORMAT_CAB | |||||
ARCHIVE_FORMAT_RAR = __libarchive.ARCHIVE_FORMAT_RAR | |||||
ARCHIVE_FORMAT_7ZIP = __libarchive.ARCHIVE_FORMAT_7ZIP | |||||
ARCHIVE_EXTRACT_OWNER = __libarchive.ARCHIVE_EXTRACT_OWNER | |||||
ARCHIVE_EXTRACT_PERM = __libarchive.ARCHIVE_EXTRACT_PERM | |||||
ARCHIVE_EXTRACT_TIME = __libarchive.ARCHIVE_EXTRACT_TIME | |||||
ARCHIVE_EXTRACT_NO_OVERWRITE = __libarchive.ARCHIVE_EXTRACT_NO_OVERWRITE | |||||
ARCHIVE_EXTRACT_UNLINK = __libarchive.ARCHIVE_EXTRACT_UNLINK | |||||
ARCHIVE_EXTRACT_ACL = __libarchive.ARCHIVE_EXTRACT_ACL | |||||
ARCHIVE_EXTRACT_FFLAGS = __libarchive.ARCHIVE_EXTRACT_FFLAGS | |||||
ARCHIVE_EXTRACT_XATTR = __libarchive.ARCHIVE_EXTRACT_XATTR | |||||
ARCHIVE_EXTRACT_SECURE_SYMLINKS = __libarchive.ARCHIVE_EXTRACT_SECURE_SYMLINKS | |||||
ARCHIVE_EXTRACT_SECURE_NODOTDOT = __libarchive.ARCHIVE_EXTRACT_SECURE_NODOTDOT | |||||
ARCHIVE_EXTRACT_NO_AUTODIR = __libarchive.ARCHIVE_EXTRACT_NO_AUTODIR | |||||
ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER = __libarchive.ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER | |||||
ARCHIVE_EXTRACT_SPARSE = __libarchive.ARCHIVE_EXTRACT_SPARSE | |||||
ARCHIVE_EXTRACT_MAC_METADATA = __libarchive.ARCHIVE_EXTRACT_MAC_METADATA | |||||
def archive_read_data_into_str(*args): | |||||
return __libarchive.archive_read_data_into_str(*args) | |||||
archive_read_data_into_str = __libarchive.archive_read_data_into_str | |||||
def archive_write_data_from_str(*args): | |||||
return __libarchive.archive_write_data_from_str(*args) | |||||
archive_write_data_from_str = __libarchive.archive_write_data_from_str | |||||
# This file is compatible with both classic and new-style classes. | |||||
@@ -0,0 +1,945 @@ | |||||
/*- | |||||
* Copyright (c) 2003-2010 Tim Kientzle | |||||
* All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions | |||||
* are met: | |||||
* 1. Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR | |||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, | |||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
* | |||||
* $FreeBSD: src/lib/libarchive/archive.h.in,v 1.50 2008/05/26 17:00:22 kientzle Exp $ | |||||
*/ | |||||
#ifndef ARCHIVE_H_INCLUDED | |||||
#define ARCHIVE_H_INCLUDED | |||||
#include <sys/stat.h> | |||||
#include <stddef.h> /* for wchar_t */ | |||||
#include <stdio.h> /* For FILE * */ | |||||
/* | |||||
* Note: archive.h is for use outside of libarchive; the configuration | |||||
* headers (config.h, archive_platform.h, etc.) are purely internal. | |||||
* Do NOT use HAVE_XXX configuration macros to control the behavior of | |||||
* this header! If you must conditionalize, use predefined compiler and/or | |||||
* platform macros. | |||||
*/ | |||||
#if defined(__BORLANDC__) && __BORLANDC__ >= 0x560 | |||||
# include <stdint.h> | |||||
#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__) && !defined(_SCO_DS) | |||||
# include <inttypes.h> | |||||
#endif | |||||
/* Get appropriate definitions of standard POSIX-style types. */ | |||||
/* These should match the types used in 'struct stat' */ | |||||
#if defined(_WIN32) && !defined(__CYGWIN__) | |||||
# define __LA_INT64_T __int64 | |||||
# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_) | |||||
# define __LA_SSIZE_T ssize_t | |||||
# elif defined(_WIN64) | |||||
# define __LA_SSIZE_T __int64 | |||||
# else | |||||
# define __LA_SSIZE_T long | |||||
# endif | |||||
#else | |||||
# include <unistd.h> /* ssize_t */ | |||||
# if defined(_SCO_DS) | |||||
# define __LA_INT64_T long long | |||||
# else | |||||
# define __LA_INT64_T int64_t | |||||
# endif | |||||
# define __LA_SSIZE_T ssize_t | |||||
#endif | |||||
/* | |||||
* On Windows, define LIBARCHIVE_STATIC if you're building or using a | |||||
* .lib. The default here assumes you're building a DLL. Only | |||||
* libarchive source should ever define __LIBARCHIVE_BUILD. | |||||
*/ | |||||
#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC) | |||||
# ifdef __LIBARCHIVE_BUILD | |||||
# ifdef __GNUC__ | |||||
# define __LA_DECL __attribute__((dllexport)) extern | |||||
# else | |||||
# define __LA_DECL __declspec(dllexport) | |||||
# endif | |||||
# else | |||||
# ifdef __GNUC__ | |||||
# define __LA_DECL | |||||
# else | |||||
# define __LA_DECL __declspec(dllimport) | |||||
# endif | |||||
# endif | |||||
#else | |||||
/* Static libraries or non-Windows needs no special declaration. */ | |||||
# define __LA_DECL | |||||
#endif | |||||
#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__MINGW32__) | |||||
#define __LA_PRINTF(fmtarg, firstvararg) \ | |||||
__attribute__((__format__ (__printf__, fmtarg, firstvararg))) | |||||
#else | |||||
#define __LA_PRINTF(fmtarg, firstvararg) /* nothing */ | |||||
#endif | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
/* | |||||
* The version number is provided as both a macro and a function. | |||||
* The macro identifies the installed header; the function identifies | |||||
* the library version (which may not be the same if you're using a | |||||
* dynamically-linked version of the library). Of course, if the | |||||
* header and library are very different, you should expect some | |||||
* strangeness. Don't do that. | |||||
*/ | |||||
/* | |||||
* The version number is expressed as a single integer that makes it | |||||
* easy to compare versions at build time: for version a.b.c, the | |||||
* version number is printf("%d%03d%03d",a,b,c). For example, if you | |||||
* know your application requires version 2.12.108 or later, you can | |||||
* assert that ARCHIVE_VERSION_NUMBER >= 2012108. | |||||
*/ | |||||
/* Note: Compiler will complain if this does not match archive_entry.h! */ | |||||
#define ARCHIVE_VERSION_NUMBER 3000004 | |||||
__LA_DECL int archive_version_number(void); | |||||
/* | |||||
* Textual name/version of the library, useful for version displays. | |||||
*/ | |||||
#define ARCHIVE_VERSION_STRING "libarchive 3.0.4" | |||||
__LA_DECL const char * archive_version_string(void); | |||||
/* Declare our basic types. */ | |||||
struct archive; | |||||
struct archive_entry; | |||||
/* | |||||
* Error codes: Use archive_errno() and archive_error_string() | |||||
* to retrieve details. Unless specified otherwise, all functions | |||||
* that return 'int' use these codes. | |||||
*/ | |||||
#define ARCHIVE_EOF 1 /* Found end of archive. */ | |||||
#define ARCHIVE_OK 0 /* Operation was successful. */ | |||||
#define ARCHIVE_RETRY (-10) /* Retry might succeed. */ | |||||
#define ARCHIVE_WARN (-20) /* Partial success. */ | |||||
/* For example, if write_header "fails", then you can't push data. */ | |||||
#define ARCHIVE_FAILED (-25) /* Current operation cannot complete. */ | |||||
/* But if write_header is "fatal," then this archive is dead and useless. */ | |||||
#define ARCHIVE_FATAL (-30) /* No more operations are possible. */ | |||||
/* | |||||
* As far as possible, archive_errno returns standard platform errno codes. | |||||
* Of course, the details vary by platform, so the actual definitions | |||||
* here are stored in "archive_platform.h". The symbols are listed here | |||||
* for reference; as a rule, clients should not need to know the exact | |||||
* platform-dependent error code. | |||||
*/ | |||||
/* Unrecognized or invalid file format. */ | |||||
/* #define ARCHIVE_ERRNO_FILE_FORMAT */ | |||||
/* Illegal usage of the library. */ | |||||
/* #define ARCHIVE_ERRNO_PROGRAMMER_ERROR */ | |||||
/* Unknown or unclassified error. */ | |||||
/* #define ARCHIVE_ERRNO_MISC */ | |||||
/* | |||||
* Callbacks are invoked to automatically read/skip/write/open/close the | |||||
* archive. You can provide your own for complex tasks (like breaking | |||||
* archives across multiple tapes) or use standard ones built into the | |||||
* library. | |||||
*/ | |||||
/* Returns pointer and size of next block of data from archive. */ | |||||
typedef __LA_SSIZE_T archive_read_callback(struct archive *, | |||||
void *_client_data, const void **_buffer); | |||||
/* Skips at most request bytes from archive and returns the skipped amount. | |||||
* This may skip fewer bytes than requested; it may even skip zero bytes. | |||||
* If you do skip fewer bytes than requested, libarchive will invoke your | |||||
* read callback and discard data as necessary to make up the full skip. | |||||
*/ | |||||
typedef __LA_INT64_T archive_skip_callback(struct archive *, | |||||
void *_client_data, __LA_INT64_T request); | |||||
/* Seeks to specified location in the file and returns the position. | |||||
* Whence values are SEEK_SET, SEEK_CUR, SEEK_END from stdio.h. | |||||
* Return ARCHIVE_FATAL if the seek fails for any reason. | |||||
*/ | |||||
typedef __LA_INT64_T archive_seek_callback(struct archive *, | |||||
void *_client_data, __LA_INT64_T offset, int whence); | |||||
/* Returns size actually written, zero on EOF, -1 on error. */ | |||||
typedef __LA_SSIZE_T archive_write_callback(struct archive *, | |||||
void *_client_data, | |||||
const void *_buffer, size_t _length); | |||||
typedef int archive_open_callback(struct archive *, void *_client_data); | |||||
typedef int archive_close_callback(struct archive *, void *_client_data); | |||||
/* | |||||
* Codes to identify various stream filters. | |||||
*/ | |||||
#define ARCHIVE_FILTER_NONE 0 | |||||
#define ARCHIVE_FILTER_GZIP 1 | |||||
#define ARCHIVE_FILTER_BZIP2 2 | |||||
#define ARCHIVE_FILTER_COMPRESS 3 | |||||
#define ARCHIVE_FILTER_PROGRAM 4 | |||||
#define ARCHIVE_FILTER_LZMA 5 | |||||
#define ARCHIVE_FILTER_XZ 6 | |||||
#define ARCHIVE_FILTER_UU 7 | |||||
#define ARCHIVE_FILTER_RPM 8 | |||||
#define ARCHIVE_FILTER_LZIP 9 | |||||
#if ARCHIVE_VERSION_NUMBER < 4000000 | |||||
#define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE | |||||
#define ARCHIVE_COMPRESSION_GZIP ARCHIVE_FILTER_GZIP | |||||
#define ARCHIVE_COMPRESSION_BZIP2 ARCHIVE_FILTER_BZIP2 | |||||
#define ARCHIVE_COMPRESSION_COMPRESS ARCHIVE_FILTER_COMPRESS | |||||
#define ARCHIVE_COMPRESSION_PROGRAM ARCHIVE_FILTER_PROGRAM | |||||
#define ARCHIVE_COMPRESSION_LZMA ARCHIVE_FILTER_LZMA | |||||
#define ARCHIVE_COMPRESSION_XZ ARCHIVE_FILTER_XZ | |||||
#define ARCHIVE_COMPRESSION_UU ARCHIVE_FILTER_UU | |||||
#define ARCHIVE_COMPRESSION_RPM ARCHIVE_FILTER_RPM | |||||
#define ARCHIVE_COMPRESSION_LZIP ARCHIVE_FILTER_LZIP | |||||
#endif | |||||
/* | |||||
* Codes returned by archive_format. | |||||
* | |||||
* Top 16 bits identifies the format family (e.g., "tar"); lower | |||||
* 16 bits indicate the variant. This is updated by read_next_header. | |||||
* Note that the lower 16 bits will often vary from entry to entry. | |||||
* In some cases, this variation occurs as libarchive learns more about | |||||
* the archive (for example, later entries might utilize extensions that | |||||
* weren't necessary earlier in the archive; in this case, libarchive | |||||
* will change the format code to indicate the extended format that | |||||
* was used). In other cases, it's because different tools have | |||||
* modified the archive and so different parts of the archive | |||||
* actually have slightly different formats. (Both tar and cpio store | |||||
* format codes in each entry, so it is quite possible for each | |||||
* entry to be in a different format.) | |||||
*/ | |||||
#define ARCHIVE_FORMAT_BASE_MASK 0xff0000 | |||||
#define ARCHIVE_FORMAT_CPIO 0x10000 | |||||
#define ARCHIVE_FORMAT_CPIO_POSIX (ARCHIVE_FORMAT_CPIO | 1) | |||||
#define ARCHIVE_FORMAT_CPIO_BIN_LE (ARCHIVE_FORMAT_CPIO | 2) | |||||
#define ARCHIVE_FORMAT_CPIO_BIN_BE (ARCHIVE_FORMAT_CPIO | 3) | |||||
#define ARCHIVE_FORMAT_CPIO_SVR4_NOCRC (ARCHIVE_FORMAT_CPIO | 4) | |||||
#define ARCHIVE_FORMAT_CPIO_SVR4_CRC (ARCHIVE_FORMAT_CPIO | 5) | |||||
#define ARCHIVE_FORMAT_CPIO_AFIO_LARGE (ARCHIVE_FORMAT_CPIO | 6) | |||||
#define ARCHIVE_FORMAT_SHAR 0x20000 | |||||
#define ARCHIVE_FORMAT_SHAR_BASE (ARCHIVE_FORMAT_SHAR | 1) | |||||
#define ARCHIVE_FORMAT_SHAR_DUMP (ARCHIVE_FORMAT_SHAR | 2) | |||||
#define ARCHIVE_FORMAT_TAR 0x30000 | |||||
#define ARCHIVE_FORMAT_TAR_USTAR (ARCHIVE_FORMAT_TAR | 1) | |||||
#define ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE (ARCHIVE_FORMAT_TAR | 2) | |||||
#define ARCHIVE_FORMAT_TAR_PAX_RESTRICTED (ARCHIVE_FORMAT_TAR | 3) | |||||
#define ARCHIVE_FORMAT_TAR_GNUTAR (ARCHIVE_FORMAT_TAR | 4) | |||||
#define ARCHIVE_FORMAT_ISO9660 0x40000 | |||||
#define ARCHIVE_FORMAT_ISO9660_ROCKRIDGE (ARCHIVE_FORMAT_ISO9660 | 1) | |||||
#define ARCHIVE_FORMAT_ZIP 0x50000 | |||||
#define ARCHIVE_FORMAT_EMPTY 0x60000 | |||||
#define ARCHIVE_FORMAT_AR 0x70000 | |||||
#define ARCHIVE_FORMAT_AR_GNU (ARCHIVE_FORMAT_AR | 1) | |||||
#define ARCHIVE_FORMAT_AR_BSD (ARCHIVE_FORMAT_AR | 2) | |||||
#define ARCHIVE_FORMAT_MTREE 0x80000 | |||||
#define ARCHIVE_FORMAT_RAW 0x90000 | |||||
#define ARCHIVE_FORMAT_XAR 0xA0000 | |||||
#define ARCHIVE_FORMAT_LHA 0xB0000 | |||||
#define ARCHIVE_FORMAT_CAB 0xC0000 | |||||
#define ARCHIVE_FORMAT_RAR 0xD0000 | |||||
#define ARCHIVE_FORMAT_7ZIP 0xE0000 | |||||
/*- | |||||
* Basic outline for reading an archive: | |||||
* 1) Ask archive_read_new for an archive reader object. | |||||
* 2) Update any global properties as appropriate. | |||||
* In particular, you'll certainly want to call appropriate | |||||
* archive_read_support_XXX functions. | |||||
* 3) Call archive_read_open_XXX to open the archive | |||||
* 4) Repeatedly call archive_read_next_header to get information about | |||||
* successive archive entries. Call archive_read_data to extract | |||||
* data for entries of interest. | |||||
* 5) Call archive_read_finish to end processing. | |||||
*/ | |||||
__LA_DECL struct archive *archive_read_new(void); | |||||
/* | |||||
* The archive_read_support_XXX calls enable auto-detect for this | |||||
* archive handle. They also link in the necessary support code. | |||||
* For example, if you don't want bzlib linked in, don't invoke | |||||
* support_compression_bzip2(). The "all" functions provide the | |||||
* obvious shorthand. | |||||
*/ | |||||
#if ARCHIVE_VERSION_NUMBER < 4000000 | |||||
__LA_DECL int archive_read_support_compression_all(struct archive *); | |||||
__LA_DECL int archive_read_support_compression_bzip2(struct archive *); | |||||
__LA_DECL int archive_read_support_compression_compress(struct archive *); | |||||
__LA_DECL int archive_read_support_compression_gzip(struct archive *); | |||||
__LA_DECL int archive_read_support_compression_lzip(struct archive *); | |||||
__LA_DECL int archive_read_support_compression_lzma(struct archive *); | |||||
__LA_DECL int archive_read_support_compression_none(struct archive *); | |||||
__LA_DECL int archive_read_support_compression_program(struct archive *, | |||||
const char *command); | |||||
__LA_DECL int archive_read_support_compression_program_signature | |||||
(struct archive *, const char *, | |||||
const void * /* match */, size_t); | |||||
__LA_DECL int archive_read_support_compression_rpm(struct archive *); | |||||
__LA_DECL int archive_read_support_compression_uu(struct archive *); | |||||
__LA_DECL int archive_read_support_compression_xz(struct archive *); | |||||
#endif | |||||
__LA_DECL int archive_read_support_filter_all(struct archive *); | |||||
__LA_DECL int archive_read_support_filter_bzip2(struct archive *); | |||||
__LA_DECL int archive_read_support_filter_compress(struct archive *); | |||||
__LA_DECL int archive_read_support_filter_gzip(struct archive *); | |||||
__LA_DECL int archive_read_support_filter_lzip(struct archive *); | |||||
__LA_DECL int archive_read_support_filter_lzma(struct archive *); | |||||
__LA_DECL int archive_read_support_filter_none(struct archive *); | |||||
__LA_DECL int archive_read_support_filter_program(struct archive *, | |||||
const char *command); | |||||
__LA_DECL int archive_read_support_filter_program_signature | |||||
(struct archive *, const char *, | |||||
const void * /* match */, size_t); | |||||
__LA_DECL int archive_read_support_filter_rpm(struct archive *); | |||||
__LA_DECL int archive_read_support_filter_uu(struct archive *); | |||||
__LA_DECL int archive_read_support_filter_xz(struct archive *); | |||||
__LA_DECL int archive_read_support_format_7zip(struct archive *); | |||||
__LA_DECL int archive_read_support_format_all(struct archive *); | |||||
__LA_DECL int archive_read_support_format_ar(struct archive *); | |||||
__LA_DECL int archive_read_support_format_by_code(struct archive *, int); | |||||
__LA_DECL int archive_read_support_format_cab(struct archive *); | |||||
__LA_DECL int archive_read_support_format_cpio(struct archive *); | |||||
__LA_DECL int archive_read_support_format_empty(struct archive *); | |||||
__LA_DECL int archive_read_support_format_gnutar(struct archive *); | |||||
__LA_DECL int archive_read_support_format_iso9660(struct archive *); | |||||
__LA_DECL int archive_read_support_format_lha(struct archive *); | |||||
__LA_DECL int archive_read_support_format_mtree(struct archive *); | |||||
__LA_DECL int archive_read_support_format_rar(struct archive *); | |||||
__LA_DECL int archive_read_support_format_raw(struct archive *); | |||||
__LA_DECL int archive_read_support_format_tar(struct archive *); | |||||
__LA_DECL int archive_read_support_format_xar(struct archive *); | |||||
__LA_DECL int archive_read_support_format_zip(struct archive *); | |||||
/* Set various callbacks. */ | |||||
__LA_DECL int archive_read_set_open_callback(struct archive *, | |||||
archive_open_callback *); | |||||
__LA_DECL int archive_read_set_read_callback(struct archive *, | |||||
archive_read_callback *); | |||||
__LA_DECL int archive_read_set_seek_callback(struct archive *, | |||||
archive_seek_callback *); | |||||
__LA_DECL int archive_read_set_skip_callback(struct archive *, | |||||
archive_skip_callback *); | |||||
__LA_DECL int archive_read_set_close_callback(struct archive *, | |||||
archive_close_callback *); | |||||
/* The callback data is provided to all of the callbacks above. */ | |||||
__LA_DECL int archive_read_set_callback_data(struct archive *, void *); | |||||
/* Opening freezes the callbacks. */ | |||||
__LA_DECL int archive_read_open1(struct archive *); | |||||
/* Convenience wrappers around the above. */ | |||||
__LA_DECL int archive_read_open(struct archive *, void *_client_data, | |||||
archive_open_callback *, archive_read_callback *, | |||||
archive_close_callback *); | |||||
__LA_DECL int archive_read_open2(struct archive *, void *_client_data, | |||||
archive_open_callback *, archive_read_callback *, | |||||
archive_skip_callback *, archive_close_callback *); | |||||
/* | |||||
* A variety of shortcuts that invoke archive_read_open() with | |||||
* canned callbacks suitable for common situations. The ones that | |||||
* accept a block size handle tape blocking correctly. | |||||
*/ | |||||
/* Use this if you know the filename. Note: NULL indicates stdin. */ | |||||
__LA_DECL int archive_read_open_filename(struct archive *, | |||||
const char *_filename, size_t _block_size); | |||||
__LA_DECL int archive_read_open_filename_w(struct archive *, | |||||
const wchar_t *_filename, size_t _block_size); | |||||
/* archive_read_open_file() is a deprecated synonym for ..._open_filename(). */ | |||||
__LA_DECL int archive_read_open_file(struct archive *, | |||||
const char *_filename, size_t _block_size); | |||||
/* Read an archive that's stored in memory. */ | |||||
__LA_DECL int archive_read_open_memory(struct archive *, | |||||
void * buff, size_t size); | |||||
/* A more involved version that is only used for internal testing. */ | |||||
__LA_DECL int archive_read_open_memory2(struct archive *a, void *buff, | |||||
size_t size, size_t read_size); | |||||
/* Read an archive that's already open, using the file descriptor. */ | |||||
__LA_DECL int archive_read_open_fd(struct archive *, int _fd, | |||||
size_t _block_size); | |||||
/* Read an archive that's already open, using a FILE *. */ | |||||
/* Note: DO NOT use this with tape drives. */ | |||||
__LA_DECL int archive_read_open_FILE(struct archive *, FILE *_file); | |||||
/* Parses and returns next entry header. */ | |||||
__LA_DECL int archive_read_next_header(struct archive *, | |||||
struct archive_entry **); | |||||
/* Parses and returns next entry header using the archive_entry passed in */ | |||||
__LA_DECL int archive_read_next_header2(struct archive *, | |||||
struct archive_entry *); | |||||
/* | |||||
* Retrieve the byte offset in UNCOMPRESSED data where last-read | |||||
* header started. | |||||
*/ | |||||
__LA_DECL __LA_INT64_T archive_read_header_position(struct archive *); | |||||
/* Read data from the body of an entry. Similar to read(2). */ | |||||
__LA_DECL __LA_SSIZE_T archive_read_data(struct archive *, | |||||
void *, size_t); | |||||
/* | |||||
* A zero-copy version of archive_read_data that also exposes the file offset | |||||
* of each returned block. Note that the client has no way to specify | |||||
* the desired size of the block. The API does guarantee that offsets will | |||||
* be strictly increasing and that returned blocks will not overlap. | |||||
*/ | |||||
__LA_DECL int archive_read_data_block(struct archive *a, | |||||
const void **buff, size_t *size, __LA_INT64_T *offset); | |||||
/*- | |||||
* Some convenience functions that are built on archive_read_data: | |||||
* 'skip': skips entire entry | |||||
* 'into_buffer': writes data into memory buffer that you provide | |||||
* 'into_fd': writes data to specified filedes | |||||
*/ | |||||
__LA_DECL int archive_read_data_skip(struct archive *); | |||||
__LA_DECL int archive_read_data_into_fd(struct archive *, int fd); | |||||
/* | |||||
* Set read options. | |||||
*/ | |||||
/* Apply option to the format only. */ | |||||
__LA_DECL int archive_read_set_format_option(struct archive *_a, | |||||
const char *m, const char *o, | |||||
const char *v); | |||||
/* Apply option to the filter only. */ | |||||
__LA_DECL int archive_read_set_filter_option(struct archive *_a, | |||||
const char *m, const char *o, | |||||
const char *v); | |||||
/* Apply option to both the format and the filter. */ | |||||
__LA_DECL int archive_read_set_option(struct archive *_a, | |||||
const char *m, const char *o, | |||||
const char *v); | |||||
/* Apply option string to both the format and the filter. */ | |||||
__LA_DECL int archive_read_set_options(struct archive *_a, | |||||
const char *opts); | |||||
/*- | |||||
* Convenience function to recreate the current entry (whose header | |||||
* has just been read) on disk. | |||||
* | |||||
* This does quite a bit more than just copy data to disk. It also: | |||||
* - Creates intermediate directories as required. | |||||
* - Manages directory permissions: non-writable directories will | |||||
* be initially created with write permission enabled; when the | |||||
* archive is closed, dir permissions are edited to the values specified | |||||
* in the archive. | |||||
* - Checks hardlinks: hardlinks will not be extracted unless the | |||||
* linked-to file was also extracted within the same session. (TODO) | |||||
*/ | |||||
/* The "flags" argument selects optional behavior, 'OR' the flags you want. */ | |||||
/* Default: Do not try to set owner/group. */ | |||||
#define ARCHIVE_EXTRACT_OWNER (0x0001) | |||||
/* Default: Do obey umask, do not restore SUID/SGID/SVTX bits. */ | |||||
#define ARCHIVE_EXTRACT_PERM (0x0002) | |||||
/* Default: Do not restore mtime/atime. */ | |||||
#define ARCHIVE_EXTRACT_TIME (0x0004) | |||||
/* Default: Replace existing files. */ | |||||
#define ARCHIVE_EXTRACT_NO_OVERWRITE (0x0008) | |||||
/* Default: Try create first, unlink only if create fails with EEXIST. */ | |||||
#define ARCHIVE_EXTRACT_UNLINK (0x0010) | |||||
/* Default: Do not restore ACLs. */ | |||||
#define ARCHIVE_EXTRACT_ACL (0x0020) | |||||
/* Default: Do not restore fflags. */ | |||||
#define ARCHIVE_EXTRACT_FFLAGS (0x0040) | |||||
/* Default: Do not restore xattrs. */ | |||||
#define ARCHIVE_EXTRACT_XATTR (0x0080) | |||||
/* Default: Do not try to guard against extracts redirected by symlinks. */ | |||||
/* Note: With ARCHIVE_EXTRACT_UNLINK, will remove any intermediate symlink. */ | |||||
#define ARCHIVE_EXTRACT_SECURE_SYMLINKS (0x0100) | |||||
/* Default: Do not reject entries with '..' as path elements. */ | |||||
#define ARCHIVE_EXTRACT_SECURE_NODOTDOT (0x0200) | |||||
/* Default: Create parent directories as needed. */ | |||||
#define ARCHIVE_EXTRACT_NO_AUTODIR (0x0400) | |||||
/* Default: Overwrite files, even if one on disk is newer. */ | |||||
#define ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER (0x0800) | |||||
/* Detect blocks of 0 and write holes instead. */ | |||||
#define ARCHIVE_EXTRACT_SPARSE (0x1000) | |||||
/* Default: Do not restore Mac extended metadata. */ | |||||
/* This has no effect except on Mac OS. */ | |||||
#define ARCHIVE_EXTRACT_MAC_METADATA (0x2000) | |||||
__LA_DECL int archive_read_extract(struct archive *, struct archive_entry *, | |||||
int flags); | |||||
__LA_DECL int archive_read_extract2(struct archive *, struct archive_entry *, | |||||
struct archive * /* dest */); | |||||
__LA_DECL void archive_read_extract_set_progress_callback(struct archive *, | |||||
void (*_progress_func)(void *), void *_user_data); | |||||
/* Record the dev/ino of a file that will not be written. This is | |||||
* generally set to the dev/ino of the archive being read. */ | |||||
__LA_DECL void archive_read_extract_set_skip_file(struct archive *, | |||||
__LA_INT64_T, __LA_INT64_T); | |||||
/* Close the file and release most resources. */ | |||||
__LA_DECL int archive_read_close(struct archive *); | |||||
/* Release all resources and destroy the object. */ | |||||
/* Note that archive_read_free will call archive_read_close for you. */ | |||||
__LA_DECL int archive_read_free(struct archive *); | |||||
#if ARCHIVE_VERSION_NUMBER < 4000000 | |||||
/* Synonym for archive_read_free() for backwards compatibility. */ | |||||
__LA_DECL int archive_read_finish(struct archive *); | |||||
#endif | |||||
/*- | |||||
* To create an archive: | |||||
* 1) Ask archive_write_new for an archive writer object. | |||||
* 2) Set any global properties. In particular, you should set | |||||
* the compression and format to use. | |||||
* 3) Call archive_write_open to open the file (most people | |||||
* will use archive_write_open_file or archive_write_open_fd, | |||||
* which provide convenient canned I/O callbacks for you). | |||||
* 4) For each entry: | |||||
* - construct an appropriate struct archive_entry structure | |||||
* - archive_write_header to write the header | |||||
* - archive_write_data to write the entry data | |||||
* 5) archive_write_close to close the output | |||||
* 6) archive_write_free to cleanup the writer and release resources | |||||
*/ | |||||
__LA_DECL struct archive *archive_write_new(void); | |||||
__LA_DECL int archive_write_set_bytes_per_block(struct archive *, | |||||
int bytes_per_block); | |||||
__LA_DECL int archive_write_get_bytes_per_block(struct archive *); | |||||
/* XXX This is badly misnamed; suggestions appreciated. XXX */ | |||||
__LA_DECL int archive_write_set_bytes_in_last_block(struct archive *, | |||||
int bytes_in_last_block); | |||||
__LA_DECL int archive_write_get_bytes_in_last_block(struct archive *); | |||||
/* The dev/ino of a file that won't be archived. This is used | |||||
* to avoid recursively adding an archive to itself. */ | |||||
__LA_DECL int archive_write_set_skip_file(struct archive *, | |||||
__LA_INT64_T, __LA_INT64_T); | |||||
#if ARCHIVE_VERSION_NUMBER < 4000000 | |||||
__LA_DECL int archive_write_set_compression_bzip2(struct archive *); | |||||
__LA_DECL int archive_write_set_compression_compress(struct archive *); | |||||
__LA_DECL int archive_write_set_compression_gzip(struct archive *); | |||||
__LA_DECL int archive_write_set_compression_lzip(struct archive *); | |||||
__LA_DECL int archive_write_set_compression_lzma(struct archive *); | |||||
__LA_DECL int archive_write_set_compression_none(struct archive *); | |||||
__LA_DECL int archive_write_set_compression_program(struct archive *, | |||||
const char *cmd); | |||||
__LA_DECL int archive_write_set_compression_xz(struct archive *); | |||||
#endif | |||||
/* A convenience function to set the filter based on the code. */ | |||||
__LA_DECL int archive_write_add_filter(struct archive *, int filter_code); | |||||
__LA_DECL int archive_write_add_filter_bzip2(struct archive *); | |||||
__LA_DECL int archive_write_add_filter_compress(struct archive *); | |||||
__LA_DECL int archive_write_add_filter_gzip(struct archive *); | |||||
__LA_DECL int archive_write_add_filter_lzip(struct archive *); | |||||
__LA_DECL int archive_write_add_filter_lzma(struct archive *); | |||||
__LA_DECL int archive_write_add_filter_none(struct archive *); | |||||
__LA_DECL int archive_write_add_filter_program(struct archive *, | |||||
const char *cmd); | |||||
__LA_DECL int archive_write_add_filter_xz(struct archive *); | |||||
/* A convenience function to set the format based on the code or name. */ | |||||
__LA_DECL int archive_write_set_format(struct archive *, int format_code); | |||||
__LA_DECL int archive_write_set_format_by_name(struct archive *, | |||||
const char *name); | |||||
/* To minimize link pollution, use one or more of the following. */ | |||||
__LA_DECL int archive_write_set_format_7zip(struct archive *); | |||||
__LA_DECL int archive_write_set_format_ar_bsd(struct archive *); | |||||
__LA_DECL int archive_write_set_format_ar_svr4(struct archive *); | |||||
__LA_DECL int archive_write_set_format_cpio(struct archive *); | |||||
__LA_DECL int archive_write_set_format_cpio_newc(struct archive *); | |||||
__LA_DECL int archive_write_set_format_gnutar(struct archive *); | |||||
__LA_DECL int archive_write_set_format_iso9660(struct archive *); | |||||
__LA_DECL int archive_write_set_format_mtree(struct archive *); | |||||
/* TODO: int archive_write_set_format_old_tar(struct archive *); */ | |||||
__LA_DECL int archive_write_set_format_pax(struct archive *); | |||||
__LA_DECL int archive_write_set_format_pax_restricted(struct archive *); | |||||
__LA_DECL int archive_write_set_format_shar(struct archive *); | |||||
__LA_DECL int archive_write_set_format_shar_dump(struct archive *); | |||||
__LA_DECL int archive_write_set_format_ustar(struct archive *); | |||||
__LA_DECL int archive_write_set_format_xar(struct archive *); | |||||
__LA_DECL int archive_write_set_format_zip(struct archive *); | |||||
__LA_DECL int archive_write_open(struct archive *, void *, | |||||
archive_open_callback *, archive_write_callback *, | |||||
archive_close_callback *); | |||||
__LA_DECL int archive_write_open_fd(struct archive *, int _fd); | |||||
__LA_DECL int archive_write_open_filename(struct archive *, const char *_file); | |||||
__LA_DECL int archive_write_open_filename_w(struct archive *, | |||||
const wchar_t *_file); | |||||
/* A deprecated synonym for archive_write_open_filename() */ | |||||
__LA_DECL int archive_write_open_file(struct archive *, const char *_file); | |||||
__LA_DECL int archive_write_open_FILE(struct archive *, FILE *); | |||||
/* _buffSize is the size of the buffer, _used refers to a variable that | |||||
* will be updated after each write into the buffer. */ | |||||
__LA_DECL int archive_write_open_memory(struct archive *, | |||||
void *_buffer, size_t _buffSize, size_t *_used); | |||||
/* | |||||
* Note that the library will truncate writes beyond the size provided | |||||
* to archive_write_header or pad if the provided data is short. | |||||
*/ | |||||
__LA_DECL int archive_write_header(struct archive *, | |||||
struct archive_entry *); | |||||
__LA_DECL __LA_SSIZE_T archive_write_data(struct archive *, | |||||
const void *, size_t); | |||||
/* This interface is currently only available for archive_write_disk handles. */ | |||||
__LA_DECL __LA_SSIZE_T archive_write_data_block(struct archive *, | |||||
const void *, size_t, __LA_INT64_T); | |||||
__LA_DECL int archive_write_finish_entry(struct archive *); | |||||
__LA_DECL int archive_write_close(struct archive *); | |||||
/* This can fail if the archive wasn't already closed, in which case | |||||
* archive_write_free() will implicitly call archive_write_close(). */ | |||||
__LA_DECL int archive_write_free(struct archive *); | |||||
#if ARCHIVE_VERSION_NUMBER < 4000000 | |||||
/* Synonym for archive_write_free() for backwards compatibility. */ | |||||
__LA_DECL int archive_write_finish(struct archive *); | |||||
#endif | |||||
/* | |||||
* Set write options. | |||||
*/ | |||||
/* Apply option to the format only. */ | |||||
__LA_DECL int archive_write_set_format_option(struct archive *_a, | |||||
const char *m, const char *o, | |||||
const char *v); | |||||
/* Apply option to the filter only. */ | |||||
__LA_DECL int archive_write_set_filter_option(struct archive *_a, | |||||
const char *m, const char *o, | |||||
const char *v); | |||||
/* Apply option to both the format and the filter. */ | |||||
__LA_DECL int archive_write_set_option(struct archive *_a, | |||||
const char *m, const char *o, | |||||
const char *v); | |||||
/* Apply option string to both the format and the filter. */ | |||||
__LA_DECL int archive_write_set_options(struct archive *_a, | |||||
const char *opts); | |||||
/*- | |||||
* ARCHIVE_WRITE_DISK API | |||||
* | |||||
* To create objects on disk: | |||||
* 1) Ask archive_write_disk_new for a new archive_write_disk object. | |||||
* 2) Set any global properties. In particular, you probably | |||||
* want to set the options. | |||||
* 3) For each entry: | |||||
* - construct an appropriate struct archive_entry structure | |||||
* - archive_write_header to create the file/dir/etc on disk | |||||
* - archive_write_data to write the entry data | |||||
* 4) archive_write_free to cleanup the writer and release resources | |||||
* | |||||
* In particular, you can use this in conjunction with archive_read() | |||||
* to pull entries out of an archive and create them on disk. | |||||
*/ | |||||
__LA_DECL struct archive *archive_write_disk_new(void); | |||||
/* This file will not be overwritten. */ | |||||
__LA_DECL int archive_write_disk_set_skip_file(struct archive *, | |||||
__LA_INT64_T, __LA_INT64_T); | |||||
/* Set flags to control how the next item gets created. | |||||
* This accepts a bitmask of ARCHIVE_EXTRACT_XXX flags defined above. */ | |||||
__LA_DECL int archive_write_disk_set_options(struct archive *, | |||||
int flags); | |||||
/* | |||||
* The lookup functions are given uname/uid (or gname/gid) pairs and | |||||
* return a uid (gid) suitable for this system. These are used for | |||||
* restoring ownership and for setting ACLs. The default functions | |||||
* are naive, they just return the uid/gid. These are small, so reasonable | |||||
* for applications that don't need to preserve ownership; they | |||||
* are probably also appropriate for applications that are doing | |||||
* same-system backup and restore. | |||||
*/ | |||||
/* | |||||
* The "standard" lookup functions use common system calls to lookup | |||||
* the uname/gname, falling back to the uid/gid if the names can't be | |||||
* found. They cache lookups and are reasonably fast, but can be very | |||||
* large, so they are not used unless you ask for them. In | |||||
* particular, these match the specifications of POSIX "pax" and old | |||||
* POSIX "tar". | |||||
*/ | |||||
__LA_DECL int archive_write_disk_set_standard_lookup(struct archive *); | |||||
/* | |||||
* If neither the default (naive) nor the standard (big) functions suit | |||||
* your needs, you can write your own and register them. Be sure to | |||||
* include a cleanup function if you have allocated private data. | |||||
*/ | |||||
__LA_DECL int archive_write_disk_set_group_lookup(struct archive *, | |||||
void * /* private_data */, | |||||
__LA_INT64_T (*)(void *, const char *, __LA_INT64_T), | |||||
void (* /* cleanup */)(void *)); | |||||
__LA_DECL int archive_write_disk_set_user_lookup(struct archive *, | |||||
void * /* private_data */, | |||||
__LA_INT64_T (*)(void *, const char *, __LA_INT64_T), | |||||
void (* /* cleanup */)(void *)); | |||||
__LA_DECL __LA_INT64_T archive_write_disk_gid(struct archive *, const char *, __LA_INT64_T); | |||||
__LA_DECL __LA_INT64_T archive_write_disk_uid(struct archive *, const char *, __LA_INT64_T); | |||||
/* | |||||
* ARCHIVE_READ_DISK API | |||||
* | |||||
* This is still evolving and somewhat experimental. | |||||
*/ | |||||
__LA_DECL struct archive *archive_read_disk_new(void); | |||||
/* The names for symlink modes here correspond to an old BSD | |||||
* command-line argument convention: -L, -P, -H */ | |||||
/* Follow all symlinks. */ | |||||
__LA_DECL int archive_read_disk_set_symlink_logical(struct archive *); | |||||
/* Follow no symlinks. */ | |||||
__LA_DECL int archive_read_disk_set_symlink_physical(struct archive *); | |||||
/* Follow symlink initially, then not. */ | |||||
__LA_DECL int archive_read_disk_set_symlink_hybrid(struct archive *); | |||||
/* TODO: Handle Linux stat32/stat64 ugliness. <sigh> */ | |||||
__LA_DECL int archive_read_disk_entry_from_file(struct archive *, | |||||
struct archive_entry *, int /* fd */, const struct stat *); | |||||
/* Look up gname for gid or uname for uid. */ | |||||
/* Default implementations are very, very stupid. */ | |||||
__LA_DECL const char *archive_read_disk_gname(struct archive *, __LA_INT64_T); | |||||
__LA_DECL const char *archive_read_disk_uname(struct archive *, __LA_INT64_T); | |||||
/* "Standard" implementation uses getpwuid_r, getgrgid_r and caches the | |||||
* results for performance. */ | |||||
__LA_DECL int archive_read_disk_set_standard_lookup(struct archive *); | |||||
/* You can install your own lookups if you like. */ | |||||
__LA_DECL int archive_read_disk_set_gname_lookup(struct archive *, | |||||
void * /* private_data */, | |||||
const char *(* /* lookup_fn */)(void *, __LA_INT64_T), | |||||
void (* /* cleanup_fn */)(void *)); | |||||
__LA_DECL int archive_read_disk_set_uname_lookup(struct archive *, | |||||
void * /* private_data */, | |||||
const char *(* /* lookup_fn */)(void *, __LA_INT64_T), | |||||
void (* /* cleanup_fn */)(void *)); | |||||
/* Start traversal. */ | |||||
__LA_DECL int archive_read_disk_open(struct archive *, const char *); | |||||
__LA_DECL int archive_read_disk_open_w(struct archive *, const wchar_t *); | |||||
/* | |||||
* Request that current entry be visited. If you invoke it on every | |||||
* directory, you'll get a physical traversal. This is ignored if the | |||||
* current entry isn't a directory or a link to a directory. So, if | |||||
* you invoke this on every returned path, you'll get a full logical | |||||
* traversal. | |||||
*/ | |||||
__LA_DECL int archive_read_disk_descend(struct archive *); | |||||
__LA_DECL int archive_read_disk_can_descend(struct archive *); | |||||
__LA_DECL int archive_read_disk_current_filesystem(struct archive *); | |||||
__LA_DECL int archive_read_disk_current_filesystem_is_synthetic(struct archive *); | |||||
__LA_DECL int archive_read_disk_current_filesystem_is_remote(struct archive *); | |||||
/* Request that the access time of the entry visited by travesal be restored. */ | |||||
__LA_DECL int archive_read_disk_set_atime_restored(struct archive *); | |||||
/* | |||||
* Set behavior. The "flags" argument selects optional behavior. | |||||
*/ | |||||
/* Request that the access time of the entry visited by travesal be restored. | |||||
* This is the same as archive_read_disk_set_atime_restored. */ | |||||
#define ARCHIVE_READDISK_RESTORE_ATIME (0x0001) | |||||
/* Default: Do not skip an entry which has nodump flags. */ | |||||
#define ARCHIVE_READDISK_HONOR_NODUMP (0x0002) | |||||
/* Default: Skip a mac resource fork file whose prefix is "._" because of | |||||
* using copyfile. */ | |||||
#define ARCHIVE_READDISK_MAC_COPYFILE (0x0004) | |||||
/* Default: Do not traverse mount points. */ | |||||
#define ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS (0x0008) | |||||
__LA_DECL int archive_read_disk_set_behavior(struct archive *, | |||||
int flags); | |||||
/* | |||||
* Set archive_match object that will be used in archive_read_disk to | |||||
* know whether an entry should be skipped. The callback function | |||||
* _excluded_func will be invoked when an entry is skipped by the result | |||||
* of archive_match. | |||||
*/ | |||||
__LA_DECL int archive_read_disk_set_matching(struct archive *, | |||||
struct archive *_matching, void (*_excluded_func) | |||||
(struct archive *, void *, struct archive_entry *), | |||||
void *_client_data); | |||||
__LA_DECL int archive_read_disk_set_metadata_filter_callback(struct archive *, | |||||
int (*_metadata_filter_func)(struct archive *, void *, | |||||
struct archive_entry *), void *_client_data); | |||||
/* | |||||
* Accessor functions to read/set various information in | |||||
* the struct archive object: | |||||
*/ | |||||
/* Number of filters in the current filter pipeline. */ | |||||
/* Filter #0 is the one closest to the format, -1 is a synonym for the | |||||
* last filter, which is always the pseudo-filter that wraps the | |||||
* client callbacks. */ | |||||
__LA_DECL int archive_filter_count(struct archive *); | |||||
__LA_DECL __LA_INT64_T archive_filter_bytes(struct archive *, int); | |||||
__LA_DECL int archive_filter_code(struct archive *, int); | |||||
__LA_DECL const char * archive_filter_name(struct archive *, int); | |||||
#if ARCHIVE_VERSION_NUMBER < 4000000 | |||||
/* These don't properly handle multiple filters, so are deprecated and | |||||
* will eventually be removed. */ | |||||
/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, -1); */ | |||||
__LA_DECL __LA_INT64_T archive_position_compressed(struct archive *); | |||||
/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, 0); */ | |||||
__LA_DECL __LA_INT64_T archive_position_uncompressed(struct archive *); | |||||
/* As of libarchive 3.0, this is an alias for archive_filter_name(a, 0); */ | |||||
__LA_DECL const char *archive_compression_name(struct archive *); | |||||
/* As of libarchive 3.0, this is an alias for archive_filter_code(a, 0); */ | |||||
__LA_DECL int archive_compression(struct archive *); | |||||
#endif | |||||
__LA_DECL int archive_errno(struct archive *); | |||||
__LA_DECL const char *archive_error_string(struct archive *); | |||||
__LA_DECL const char *archive_format_name(struct archive *); | |||||
__LA_DECL int archive_format(struct archive *); | |||||
__LA_DECL void archive_clear_error(struct archive *); | |||||
__LA_DECL void archive_set_error(struct archive *, int _err, | |||||
const char *fmt, ...) __LA_PRINTF(3, 4); | |||||
__LA_DECL void archive_copy_error(struct archive *dest, | |||||
struct archive *src); | |||||
__LA_DECL int archive_file_count(struct archive *); | |||||
/* | |||||
* ARCHIVE_MATCH API | |||||
*/ | |||||
__LA_DECL struct archive *archive_match_new(void); | |||||
__LA_DECL int archive_match_free(struct archive *); | |||||
/* | |||||
* Test if archive_entry is excluded. | |||||
* This is a convenience function. This is the same as calling all | |||||
* archive_match_path_excluded, archive_match_time_excluded | |||||
* and archive_match_owner_excluded. | |||||
*/ | |||||
__LA_DECL int archive_match_excluded(struct archive *, | |||||
struct archive_entry *); | |||||
/* | |||||
* Test if pathname is excluded. The conditions are set by following functions. | |||||
*/ | |||||
__LA_DECL int archive_match_path_excluded(struct archive *, | |||||
struct archive_entry *); | |||||
/* Add exclusion pathname pattern. */ | |||||
__LA_DECL int archive_match_exclude_pattern(struct archive *, const char *); | |||||
__LA_DECL int archive_match_exclude_pattern_w(struct archive *, | |||||
const wchar_t *); | |||||
/* Add exclusion pathname pattern from file. */ | |||||
__LA_DECL int archive_match_exclude_pattern_from_file(struct archive *, | |||||
const char *, int _nullSeparator); | |||||
__LA_DECL int archive_match_exclude_pattern_from_file_w(struct archive *, | |||||
const wchar_t *, int _nullSeparator); | |||||
/* Add inclusion pathname pattern. */ | |||||
__LA_DECL int archive_match_include_pattern(struct archive *, const char *); | |||||
__LA_DECL int archive_match_include_pattern_w(struct archive *, | |||||
const wchar_t *); | |||||
/* Add inclusion pathname pattern from file. */ | |||||
__LA_DECL int archive_match_include_pattern_from_file(struct archive *, | |||||
const char *, int _nullSeparator); | |||||
__LA_DECL int archive_match_include_pattern_from_file_w(struct archive *, | |||||
const wchar_t *, int _nullSeparator); | |||||
/* | |||||
* How to get statistic information for inclusion patterns. | |||||
*/ | |||||
/* Return the amount number of unmatched inclusion patterns. */ | |||||
__LA_DECL int archive_match_path_unmatched_inclusions(struct archive *); | |||||
/* Return the pattern of unmatched inclusion with ARCHIVE_OK. | |||||
* Return ARCHIVE_EOF if there is no inclusion pattern. */ | |||||
__LA_DECL int archive_match_path_unmatched_inclusions_next( | |||||
struct archive *, const char **); | |||||
__LA_DECL int archive_match_path_unmatched_inclusions_next_w( | |||||
struct archive *, const wchar_t **); | |||||
/* | |||||
* Test if a file is excluded by its time stamp. | |||||
* The conditions are set by following functions. | |||||
*/ | |||||
__LA_DECL int archive_match_time_excluded(struct archive *, | |||||
struct archive_entry *); | |||||
/* | |||||
* Flags to tell a matching type of time stamps. These are used for | |||||
* following functinos. | |||||
*/ | |||||
/* Time flag: mtime to be tested. */ | |||||
#define ARCHIVE_MATCH_MTIME (0x0100) | |||||
/* Time flag: ctime to be tested. */ | |||||
#define ARCHIVE_MATCH_CTIME (0x0200) | |||||
/* Comparison flag: Match the time if it is newer than. */ | |||||
#define ARCHIVE_MATCH_NEWER (0x0001) | |||||
/* Comparison flag: Match the time if it is older than. */ | |||||
#define ARCHIVE_MATCH_OLDER (0x0002) | |||||
/* Comparison flag: Match the time if it is equal to. */ | |||||
#define ARCHIVE_MATCH_EQUAL (0x0010) | |||||
/* Set inclusion time. */ | |||||
__LA_DECL int archive_match_include_time(struct archive *, int _flag, | |||||
time_t _sec, long _nsec); | |||||
/* Set inclusion time by a date string. */ | |||||
__LA_DECL int archive_match_include_date(struct archive *, int _flag, | |||||
const char *_datestr); | |||||
__LA_DECL int archive_match_include_date_w(struct archive *, int _flag, | |||||
const wchar_t *_datestr); | |||||
/* Set inclusion time by a particluar file. */ | |||||
__LA_DECL int archive_match_include_file_time(struct archive *, | |||||
int _flag, const char *_pathname); | |||||
__LA_DECL int archive_match_include_file_time_w(struct archive *, | |||||
int _flag, const wchar_t *_pathname); | |||||
/* Add exclusion entry. */ | |||||
__LA_DECL int archive_match_exclude_entry(struct archive *, | |||||
int _flag, struct archive_entry *); | |||||
/* | |||||
* Test if a file is excluded by its uid ,gid, uname or gname. | |||||
* The conditions are set by following functions. | |||||
*/ | |||||
__LA_DECL int archive_match_owner_excluded(struct archive *, | |||||
struct archive_entry *); | |||||
/* Add inclusion uid, gid, uname and gname. */ | |||||
__LA_DECL int archive_match_include_uid(struct archive *, __LA_INT64_T); | |||||
__LA_DECL int archive_match_include_gid(struct archive *, __LA_INT64_T); | |||||
__LA_DECL int archive_match_include_uname(struct archive *, const char *); | |||||
__LA_DECL int archive_match_include_uname_w(struct archive *, | |||||
const wchar_t *); | |||||
__LA_DECL int archive_match_include_gname(struct archive *, const char *); | |||||
__LA_DECL int archive_match_include_gname_w(struct archive *, | |||||
const wchar_t *); | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
/* These are meaningless outside of this header. */ | |||||
#undef __LA_DECL | |||||
/* These need to remain defined because they're used in the | |||||
* callback type definitions. XXX Fix this. This is ugly. XXX */ | |||||
/* #undef __LA_INT64_T */ | |||||
/* #undef __LA_SSIZE_T */ | |||||
#endif /* !ARCHIVE_H_INCLUDED */ |
@@ -0,0 +1,615 @@ | |||||
/*- | |||||
* Copyright (c) 2003-2008 Tim Kientzle | |||||
* All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions | |||||
* are met: | |||||
* 1. Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR | |||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, | |||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
* | |||||
* $FreeBSD: head/lib/libarchive/archive_entry.h 201096 2009-12-28 02:41:27Z kientzle $ | |||||
*/ | |||||
#ifndef ARCHIVE_ENTRY_H_INCLUDED | |||||
#define ARCHIVE_ENTRY_H_INCLUDED | |||||
/* Note: Compiler will complain if this does not match archive.h! */ | |||||
#define ARCHIVE_VERSION_NUMBER 3000004 | |||||
/* | |||||
* Note: archive_entry.h is for use outside of libarchive; the | |||||
* configuration headers (config.h, archive_platform.h, etc.) are | |||||
* purely internal. Do NOT use HAVE_XXX configuration macros to | |||||
* control the behavior of this header! If you must conditionalize, | |||||
* use predefined compiler and/or platform macros. | |||||
*/ | |||||
#include <sys/types.h> | |||||
#include <stddef.h> /* for wchar_t */ | |||||
#include <time.h> | |||||
#if defined(_WIN32) && !defined(__CYGWIN__) | |||||
#include <windows.h> | |||||
#endif | |||||
/* Get a suitable 64-bit integer type. */ | |||||
#if defined(_WIN32) && !defined(__CYGWIN__) | |||||
# define __LA_INT64_T __int64 | |||||
#else | |||||
#include <unistd.h> | |||||
# if defined(_SCO_DS) | |||||
# define __LA_INT64_T long long | |||||
# else | |||||
# define __LA_INT64_T int64_t | |||||
# endif | |||||
#endif | |||||
/* Get a suitable definition for mode_t */ | |||||
#if ARCHIVE_VERSION_NUMBER >= 3999000 | |||||
/* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */ | |||||
# define __LA_MODE_T int | |||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__) | |||||
# define __LA_MODE_T unsigned short | |||||
#else | |||||
# define __LA_MODE_T mode_t | |||||
#endif | |||||
/* | |||||
* On Windows, define LIBARCHIVE_STATIC if you're building or using a | |||||
* .lib. The default here assumes you're building a DLL. Only | |||||
* libarchive source should ever define __LIBARCHIVE_BUILD. | |||||
*/ | |||||
#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC) | |||||
# ifdef __LIBARCHIVE_BUILD | |||||
# ifdef __GNUC__ | |||||
# define __LA_DECL __attribute__((dllexport)) extern | |||||
# else | |||||
# define __LA_DECL __declspec(dllexport) | |||||
# endif | |||||
# else | |||||
# ifdef __GNUC__ | |||||
# define __LA_DECL | |||||
# else | |||||
# define __LA_DECL __declspec(dllimport) | |||||
# endif | |||||
# endif | |||||
#else | |||||
/* Static libraries on all platforms and shared libraries on non-Windows. */ | |||||
# define __LA_DECL | |||||
#endif | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
/* | |||||
* Description of an archive entry. | |||||
* | |||||
* You can think of this as "struct stat" with some text fields added in. | |||||
* | |||||
* TODO: Add "comment", "charset", and possibly other entries that are | |||||
* supported by "pax interchange" format. However, GNU, ustar, cpio, | |||||
* and other variants don't support these features, so they're not an | |||||
* excruciatingly high priority right now. | |||||
* | |||||
* TODO: "pax interchange" format allows essentially arbitrary | |||||
* key/value attributes to be attached to any entry. Supporting | |||||
* such extensions may make this library useful for special | |||||
* applications (e.g., a package manager could attach special | |||||
* package-management attributes to each entry). | |||||
*/ | |||||
struct archive; | |||||
struct archive_entry; | |||||
/* | |||||
* File-type constants. These are returned from archive_entry_filetype() | |||||
* and passed to archive_entry_set_filetype(). | |||||
* | |||||
* These values match S_XXX defines on every platform I've checked, | |||||
* including Windows, AIX, Linux, Solaris, and BSD. They're | |||||
* (re)defined here because platforms generally don't define the ones | |||||
* they don't support. For example, Windows doesn't define S_IFLNK or | |||||
* S_IFBLK. Instead of having a mass of conditional logic and system | |||||
* checks to define any S_XXX values that aren't supported locally, | |||||
* I've just defined a new set of such constants so that | |||||
* libarchive-based applications can manipulate and identify archive | |||||
* entries properly even if the hosting platform can't store them on | |||||
* disk. | |||||
* | |||||
* These values are also used directly within some portable formats, | |||||
* such as cpio. If you find a platform that varies from these, the | |||||
* correct solution is to leave these alone and translate from these | |||||
* portable values to platform-native values when entries are read from | |||||
* or written to disk. | |||||
*/ | |||||
/* | |||||
* In libarchive 4.0, we can drop the casts here. | |||||
* They're needed to work around Borland C's broken mode_t. | |||||
*/ | |||||
#define AE_IFMT ((__LA_MODE_T)0170000) | |||||
#define AE_IFREG ((__LA_MODE_T)0100000) | |||||
#define AE_IFLNK ((__LA_MODE_T)0120000) | |||||
#define AE_IFSOCK ((__LA_MODE_T)0140000) | |||||
#define AE_IFCHR ((__LA_MODE_T)0020000) | |||||
#define AE_IFBLK ((__LA_MODE_T)0060000) | |||||
#define AE_IFDIR ((__LA_MODE_T)0040000) | |||||
#define AE_IFIFO ((__LA_MODE_T)0010000) | |||||
/* | |||||
* Basic object manipulation | |||||
*/ | |||||
__LA_DECL struct archive_entry *archive_entry_clear(struct archive_entry *); | |||||
/* The 'clone' function does a deep copy; all of the strings are copied too. */ | |||||
__LA_DECL struct archive_entry *archive_entry_clone(struct archive_entry *); | |||||
__LA_DECL void archive_entry_free(struct archive_entry *); | |||||
__LA_DECL struct archive_entry *archive_entry_new(void); | |||||
/* | |||||
* This form of archive_entry_new2() will pull character-set | |||||
* conversion information from the specified archive handle. The | |||||
* older archive_entry_new(void) form is equivalent to calling | |||||
* archive_entry_new2(NULL) and will result in the use of an internal | |||||
* default character-set conversion. | |||||
*/ | |||||
__LA_DECL struct archive_entry *archive_entry_new2(struct archive *); | |||||
/* | |||||
* Retrieve fields from an archive_entry. | |||||
* | |||||
* There are a number of implicit conversions among these fields. For | |||||
* example, if a regular string field is set and you read the _w wide | |||||
* character field, the entry will implicitly convert narrow-to-wide | |||||
* using the current locale. Similarly, dev values are automatically | |||||
* updated when you write devmajor or devminor and vice versa. | |||||
* | |||||
* In addition, fields can be "set" or "unset." Unset string fields | |||||
* return NULL, non-string fields have _is_set() functions to test | |||||
* whether they've been set. You can "unset" a string field by | |||||
* assigning NULL; non-string fields have _unset() functions to | |||||
* unset them. | |||||
* | |||||
* Note: There is one ambiguity in the above; string fields will | |||||
* also return NULL when implicit character set conversions fail. | |||||
* This is usually what you want. | |||||
*/ | |||||
__LA_DECL time_t archive_entry_atime(struct archive_entry *); | |||||
__LA_DECL long archive_entry_atime_nsec(struct archive_entry *); | |||||
__LA_DECL int archive_entry_atime_is_set(struct archive_entry *); | |||||
__LA_DECL time_t archive_entry_birthtime(struct archive_entry *); | |||||
__LA_DECL long archive_entry_birthtime_nsec(struct archive_entry *); | |||||
__LA_DECL int archive_entry_birthtime_is_set(struct archive_entry *); | |||||
__LA_DECL time_t archive_entry_ctime(struct archive_entry *); | |||||
__LA_DECL long archive_entry_ctime_nsec(struct archive_entry *); | |||||
__LA_DECL int archive_entry_ctime_is_set(struct archive_entry *); | |||||
__LA_DECL dev_t archive_entry_dev(struct archive_entry *); | |||||
__LA_DECL int archive_entry_dev_is_set(struct archive_entry *); | |||||
__LA_DECL dev_t archive_entry_devmajor(struct archive_entry *); | |||||
__LA_DECL dev_t archive_entry_devminor(struct archive_entry *); | |||||
__LA_DECL __LA_MODE_T archive_entry_filetype(struct archive_entry *); | |||||
__LA_DECL void archive_entry_fflags(struct archive_entry *, | |||||
unsigned long * /* set */, | |||||
unsigned long * /* clear */); | |||||
__LA_DECL const char *archive_entry_fflags_text(struct archive_entry *); | |||||
__LA_DECL __LA_INT64_T archive_entry_gid(struct archive_entry *); | |||||
__LA_DECL const char *archive_entry_gname(struct archive_entry *); | |||||
__LA_DECL const wchar_t *archive_entry_gname_w(struct archive_entry *); | |||||
__LA_DECL const char *archive_entry_hardlink(struct archive_entry *); | |||||
__LA_DECL const wchar_t *archive_entry_hardlink_w(struct archive_entry *); | |||||
__LA_DECL __LA_INT64_T archive_entry_ino(struct archive_entry *); | |||||
__LA_DECL __LA_INT64_T archive_entry_ino64(struct archive_entry *); | |||||
__LA_DECL int archive_entry_ino_is_set(struct archive_entry *); | |||||
__LA_DECL __LA_MODE_T archive_entry_mode(struct archive_entry *); | |||||
__LA_DECL time_t archive_entry_mtime(struct archive_entry *); | |||||
__LA_DECL long archive_entry_mtime_nsec(struct archive_entry *); | |||||
__LA_DECL int archive_entry_mtime_is_set(struct archive_entry *); | |||||
__LA_DECL unsigned int archive_entry_nlink(struct archive_entry *); | |||||
__LA_DECL const char *archive_entry_pathname(struct archive_entry *); | |||||
__LA_DECL const wchar_t *archive_entry_pathname_w(struct archive_entry *); | |||||
__LA_DECL __LA_MODE_T archive_entry_perm(struct archive_entry *); | |||||
__LA_DECL dev_t archive_entry_rdev(struct archive_entry *); | |||||
__LA_DECL dev_t archive_entry_rdevmajor(struct archive_entry *); | |||||
__LA_DECL dev_t archive_entry_rdevminor(struct archive_entry *); | |||||
__LA_DECL const char *archive_entry_sourcepath(struct archive_entry *); | |||||
__LA_DECL const wchar_t *archive_entry_sourcepath_w(struct archive_entry *); | |||||
__LA_DECL __LA_INT64_T archive_entry_size(struct archive_entry *); | |||||
__LA_DECL int archive_entry_size_is_set(struct archive_entry *); | |||||
__LA_DECL const char *archive_entry_strmode(struct archive_entry *); | |||||
__LA_DECL const char *archive_entry_symlink(struct archive_entry *); | |||||
__LA_DECL const wchar_t *archive_entry_symlink_w(struct archive_entry *); | |||||
__LA_DECL __LA_INT64_T archive_entry_uid(struct archive_entry *); | |||||
__LA_DECL const char *archive_entry_uname(struct archive_entry *); | |||||
__LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *); | |||||
/* | |||||
* Set fields in an archive_entry. | |||||
* | |||||
* Note: Before libarchive 2.4, there were 'set' and 'copy' versions | |||||
* of the string setters. 'copy' copied the actual string, 'set' just | |||||
* stored the pointer. In libarchive 2.4 and later, strings are | |||||
* always copied. | |||||
*/ | |||||
__LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long); | |||||
__LA_DECL void archive_entry_unset_atime(struct archive_entry *); | |||||
#if defined(_WIN32) && !defined(__CYGWIN__) | |||||
__LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, BY_HANDLE_FILE_INFORMATION *); | |||||
#endif | |||||
__LA_DECL void archive_entry_set_birthtime(struct archive_entry *, time_t, long); | |||||
__LA_DECL void archive_entry_unset_birthtime(struct archive_entry *); | |||||
__LA_DECL void archive_entry_set_ctime(struct archive_entry *, time_t, long); | |||||
__LA_DECL void archive_entry_unset_ctime(struct archive_entry *); | |||||
__LA_DECL void archive_entry_set_dev(struct archive_entry *, dev_t); | |||||
__LA_DECL void archive_entry_set_devmajor(struct archive_entry *, dev_t); | |||||
__LA_DECL void archive_entry_set_devminor(struct archive_entry *, dev_t); | |||||
__LA_DECL void archive_entry_set_filetype(struct archive_entry *, unsigned int); | |||||
__LA_DECL void archive_entry_set_fflags(struct archive_entry *, | |||||
unsigned long /* set */, unsigned long /* clear */); | |||||
/* Returns pointer to start of first invalid token, or NULL if none. */ | |||||
/* Note that all recognized tokens are processed, regardless. */ | |||||
__LA_DECL const char *archive_entry_copy_fflags_text(struct archive_entry *, | |||||
const char *); | |||||
__LA_DECL const wchar_t *archive_entry_copy_fflags_text_w(struct archive_entry *, | |||||
const wchar_t *); | |||||
__LA_DECL void archive_entry_set_gid(struct archive_entry *, __LA_INT64_T); | |||||
__LA_DECL void archive_entry_set_gname(struct archive_entry *, const char *); | |||||
__LA_DECL void archive_entry_copy_gname(struct archive_entry *, const char *); | |||||
__LA_DECL void archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *); | |||||
__LA_DECL int archive_entry_update_gname_utf8(struct archive_entry *, const char *); | |||||
__LA_DECL void archive_entry_set_hardlink(struct archive_entry *, const char *); | |||||
__LA_DECL void archive_entry_copy_hardlink(struct archive_entry *, const char *); | |||||
__LA_DECL void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *); | |||||
__LA_DECL int archive_entry_update_hardlink_utf8(struct archive_entry *, const char *); | |||||
__LA_DECL void archive_entry_set_ino(struct archive_entry *, __LA_INT64_T); | |||||
__LA_DECL void archive_entry_set_ino64(struct archive_entry *, __LA_INT64_T); | |||||
__LA_DECL void archive_entry_set_link(struct archive_entry *, const char *); | |||||
__LA_DECL void archive_entry_copy_link(struct archive_entry *, const char *); | |||||
__LA_DECL void archive_entry_copy_link_w(struct archive_entry *, const wchar_t *); | |||||
__LA_DECL int archive_entry_update_link_utf8(struct archive_entry *, const char *); | |||||
__LA_DECL void archive_entry_set_mode(struct archive_entry *, __LA_MODE_T); | |||||
__LA_DECL void archive_entry_set_mtime(struct archive_entry *, time_t, long); | |||||
__LA_DECL void archive_entry_unset_mtime(struct archive_entry *); | |||||
__LA_DECL void archive_entry_set_nlink(struct archive_entry *, unsigned int); | |||||
__LA_DECL void archive_entry_set_pathname(struct archive_entry *, const char *); | |||||
__LA_DECL void archive_entry_copy_pathname(struct archive_entry *, const char *); | |||||
__LA_DECL void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *); | |||||
__LA_DECL int archive_entry_update_pathname_utf8(struct archive_entry *, const char *); | |||||
__LA_DECL void archive_entry_set_perm(struct archive_entry *, __LA_MODE_T); | |||||
__LA_DECL void archive_entry_set_rdev(struct archive_entry *, dev_t); | |||||
__LA_DECL void archive_entry_set_rdevmajor(struct archive_entry *, dev_t); | |||||
__LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, dev_t); | |||||
__LA_DECL void archive_entry_set_size(struct archive_entry *, __LA_INT64_T); | |||||
__LA_DECL void archive_entry_unset_size(struct archive_entry *); | |||||
__LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *); | |||||
__LA_DECL void archive_entry_copy_sourcepath_w(struct archive_entry *, const wchar_t *); | |||||
__LA_DECL void archive_entry_set_symlink(struct archive_entry *, const char *); | |||||
__LA_DECL void archive_entry_copy_symlink(struct archive_entry *, const char *); | |||||
__LA_DECL void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *); | |||||
__LA_DECL int archive_entry_update_symlink_utf8(struct archive_entry *, const char *); | |||||
__LA_DECL void archive_entry_set_uid(struct archive_entry *, __LA_INT64_T); | |||||
__LA_DECL void archive_entry_set_uname(struct archive_entry *, const char *); | |||||
__LA_DECL void archive_entry_copy_uname(struct archive_entry *, const char *); | |||||
__LA_DECL void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *); | |||||
__LA_DECL int archive_entry_update_uname_utf8(struct archive_entry *, const char *); | |||||
/* | |||||
* Routines to bulk copy fields to/from a platform-native "struct | |||||
* stat." Libarchive used to just store a struct stat inside of each | |||||
* archive_entry object, but this created issues when trying to | |||||
* manipulate archives on systems different than the ones they were | |||||
* created on. | |||||
* | |||||
* TODO: On Linux and other LFS systems, provide both stat32 and | |||||
* stat64 versions of these functions and all of the macro glue so | |||||
* that archive_entry_stat is magically defined to | |||||
* archive_entry_stat32 or archive_entry_stat64 as appropriate. | |||||
*/ | |||||
__LA_DECL const struct stat *archive_entry_stat(struct archive_entry *); | |||||
__LA_DECL void archive_entry_copy_stat(struct archive_entry *, const struct stat *); | |||||
/* | |||||
* Storage for Mac OS-specific AppleDouble metadata information. | |||||
* Apple-format tar files store a separate binary blob containing | |||||
* encoded metadata with ACL, extended attributes, etc. | |||||
* This provides a place to store that blob. | |||||
*/ | |||||
__LA_DECL const void * archive_entry_mac_metadata(struct archive_entry *, size_t *); | |||||
__LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const void *, size_t); | |||||
/* | |||||
* ACL routines. This used to simply store and return text-format ACL | |||||
* strings, but that proved insufficient for a number of reasons: | |||||
* = clients need control over uname/uid and gname/gid mappings | |||||
* = there are many different ACL text formats | |||||
* = would like to be able to read/convert archives containing ACLs | |||||
* on platforms that lack ACL libraries | |||||
* | |||||
* This last point, in particular, forces me to implement a reasonably | |||||
* complete set of ACL support routines. | |||||
*/ | |||||
/* | |||||
* Permission bits. | |||||
*/ | |||||
#define ARCHIVE_ENTRY_ACL_EXECUTE 0x00000001 | |||||
#define ARCHIVE_ENTRY_ACL_WRITE 0x00000002 | |||||
#define ARCHIVE_ENTRY_ACL_READ 0x00000004 | |||||
#define ARCHIVE_ENTRY_ACL_READ_DATA 0x00000008 | |||||
#define ARCHIVE_ENTRY_ACL_LIST_DIRECTORY 0x00000008 | |||||
#define ARCHIVE_ENTRY_ACL_WRITE_DATA 0x00000010 | |||||
#define ARCHIVE_ENTRY_ACL_ADD_FILE 0x00000010 | |||||
#define ARCHIVE_ENTRY_ACL_APPEND_DATA 0x00000020 | |||||
#define ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY 0x00000020 | |||||
#define ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS 0x00000040 | |||||
#define ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS 0x00000080 | |||||
#define ARCHIVE_ENTRY_ACL_DELETE_CHILD 0x00000100 | |||||
#define ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES 0x00000200 | |||||
#define ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES 0x00000400 | |||||
#define ARCHIVE_ENTRY_ACL_DELETE 0x00000800 | |||||
#define ARCHIVE_ENTRY_ACL_READ_ACL 0x00001000 | |||||
#define ARCHIVE_ENTRY_ACL_WRITE_ACL 0x00002000 | |||||
#define ARCHIVE_ENTRY_ACL_WRITE_OWNER 0x00004000 | |||||
#define ARCHIVE_ENTRY_ACL_SYNCHRONIZE 0x00008000 | |||||
#define ARCHIVE_ENTRY_ACL_PERMS_POSIX1E \ | |||||
(ARCHIVE_ENTRY_ACL_EXECUTE \ | |||||
| ARCHIVE_ENTRY_ACL_WRITE \ | |||||
| ARCHIVE_ENTRY_ACL_READ) | |||||
#define ARCHIVE_ENTRY_ACL_PERMS_NFS4 \ | |||||
(ARCHIVE_ENTRY_ACL_EXECUTE \ | |||||
| ARCHIVE_ENTRY_ACL_READ_DATA \ | |||||
| ARCHIVE_ENTRY_ACL_LIST_DIRECTORY \ | |||||
| ARCHIVE_ENTRY_ACL_WRITE_DATA \ | |||||
| ARCHIVE_ENTRY_ACL_ADD_FILE \ | |||||
| ARCHIVE_ENTRY_ACL_APPEND_DATA \ | |||||
| ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY \ | |||||
| ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS \ | |||||
| ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS \ | |||||
| ARCHIVE_ENTRY_ACL_DELETE_CHILD \ | |||||
| ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES \ | |||||
| ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES \ | |||||
| ARCHIVE_ENTRY_ACL_DELETE \ | |||||
| ARCHIVE_ENTRY_ACL_READ_ACL \ | |||||
| ARCHIVE_ENTRY_ACL_WRITE_ACL \ | |||||
| ARCHIVE_ENTRY_ACL_WRITE_OWNER \ | |||||
| ARCHIVE_ENTRY_ACL_SYNCHRONIZE) | |||||
/* | |||||
* Inheritance values (NFS4 ACLs only); included in permset. | |||||
*/ | |||||
#define ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT 0x02000000 | |||||
#define ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT 0x04000000 | |||||
#define ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT 0x08000000 | |||||
#define ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY 0x10000000 | |||||
#define ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS 0x20000000 | |||||
#define ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS 0x40000000 | |||||
#define ARCHIVE_ENTRY_ACL_INHERITANCE_NFS4 \ | |||||
(ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT \ | |||||
| ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT \ | |||||
| ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT \ | |||||
| ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY \ | |||||
| ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS \ | |||||
| ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS) | |||||
/* We need to be able to specify combinations of these. */ | |||||
#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 256 /* POSIX.1e only */ | |||||
#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 512 /* POSIX.1e only */ | |||||
#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 1024 /* NFS4 only */ | |||||
#define ARCHIVE_ENTRY_ACL_TYPE_DENY 2048 /* NFS4 only */ | |||||
#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 4096 /* NFS4 only */ | |||||
#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 8192 /* NFS4 only */ | |||||
#define ARCHIVE_ENTRY_ACL_TYPE_POSIX1E (ARCHIVE_ENTRY_ACL_TYPE_ACCESS \ | |||||
| ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) | |||||
#define ARCHIVE_ENTRY_ACL_TYPE_NFS4 (ARCHIVE_ENTRY_ACL_TYPE_ALLOW \ | |||||
| ARCHIVE_ENTRY_ACL_TYPE_DENY \ | |||||
| ARCHIVE_ENTRY_ACL_TYPE_AUDIT \ | |||||
| ARCHIVE_ENTRY_ACL_TYPE_ALARM) | |||||
/* Tag values mimic POSIX.1e */ | |||||
#define ARCHIVE_ENTRY_ACL_USER 10001 /* Specified user. */ | |||||
#define ARCHIVE_ENTRY_ACL_USER_OBJ 10002 /* User who owns the file. */ | |||||
#define ARCHIVE_ENTRY_ACL_GROUP 10003 /* Specified group. */ | |||||
#define ARCHIVE_ENTRY_ACL_GROUP_OBJ 10004 /* Group who owns the file. */ | |||||
#define ARCHIVE_ENTRY_ACL_MASK 10005 /* Modify group access (POSIX.1e only) */ | |||||
#define ARCHIVE_ENTRY_ACL_OTHER 10006 /* Public (POSIX.1e only) */ | |||||
#define ARCHIVE_ENTRY_ACL_EVERYONE 10107 /* Everyone (NFS4 only) */ | |||||
/* | |||||
* Set the ACL by clearing it and adding entries one at a time. | |||||
* Unlike the POSIX.1e ACL routines, you must specify the type | |||||
* (access/default) for each entry. Internally, the ACL data is just | |||||
* a soup of entries. API calls here allow you to retrieve just the | |||||
* entries of interest. This design (which goes against the spirit of | |||||
* POSIX.1e) is useful for handling archive formats that combine | |||||
* default and access information in a single ACL list. | |||||
*/ | |||||
__LA_DECL void archive_entry_acl_clear(struct archive_entry *); | |||||
__LA_DECL int archive_entry_acl_add_entry(struct archive_entry *, | |||||
int /* type */, int /* permset */, int /* tag */, | |||||
int /* qual */, const char * /* name */); | |||||
__LA_DECL int archive_entry_acl_add_entry_w(struct archive_entry *, | |||||
int /* type */, int /* permset */, int /* tag */, | |||||
int /* qual */, const wchar_t * /* name */); | |||||
/* | |||||
* To retrieve the ACL, first "reset", then repeatedly ask for the | |||||
* "next" entry. The want_type parameter allows you to request only | |||||
* certain types of entries. | |||||
*/ | |||||
__LA_DECL int archive_entry_acl_reset(struct archive_entry *, int /* want_type */); | |||||
__LA_DECL int archive_entry_acl_next(struct archive_entry *, int /* want_type */, | |||||
int * /* type */, int * /* permset */, int * /* tag */, | |||||
int * /* qual */, const char ** /* name */); | |||||
__LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type */, | |||||
int * /* type */, int * /* permset */, int * /* tag */, | |||||
int * /* qual */, const wchar_t ** /* name */); | |||||
/* | |||||
* Construct a text-format ACL. The flags argument is a bitmask that | |||||
* can include any of the following: | |||||
* | |||||
* ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include POSIX.1e "access" entries. | |||||
* ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include POSIX.1e "default" entries. | |||||
* ARCHIVE_ENTRY_ACL_TYPE_NFS4 - Include NFS4 entries. | |||||
* ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in | |||||
* each ACL entry. ('star' introduced this for POSIX.1e, this flag | |||||
* also applies to NFS4.) | |||||
* ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each | |||||
* default ACL entry, as used in old Solaris ACLs. | |||||
*/ | |||||
#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024 | |||||
#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048 | |||||
__LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *, | |||||
int /* flags */); | |||||
__LA_DECL const char *archive_entry_acl_text(struct archive_entry *, | |||||
int /* flags */); | |||||
/* Return a count of entries matching 'want_type' */ | |||||
__LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */); | |||||
/* Return an opaque ACL object. */ | |||||
/* There's not yet anything clients can actually do with this... */ | |||||
struct archive_acl; | |||||
__LA_DECL struct archive_acl *archive_entry_acl(struct archive_entry *); | |||||
/* | |||||
* extended attributes | |||||
*/ | |||||
__LA_DECL void archive_entry_xattr_clear(struct archive_entry *); | |||||
__LA_DECL void archive_entry_xattr_add_entry(struct archive_entry *, | |||||
const char * /* name */, const void * /* value */, | |||||
size_t /* size */); | |||||
/* | |||||
* To retrieve the xattr list, first "reset", then repeatedly ask for the | |||||
* "next" entry. | |||||
*/ | |||||
__LA_DECL int archive_entry_xattr_count(struct archive_entry *); | |||||
__LA_DECL int archive_entry_xattr_reset(struct archive_entry *); | |||||
__LA_DECL int archive_entry_xattr_next(struct archive_entry *, | |||||
const char ** /* name */, const void ** /* value */, size_t *); | |||||
/* | |||||
* sparse | |||||
*/ | |||||
__LA_DECL void archive_entry_sparse_clear(struct archive_entry *); | |||||
__LA_DECL void archive_entry_sparse_add_entry(struct archive_entry *, | |||||
__LA_INT64_T /* offset */, __LA_INT64_T /* length */); | |||||
/* | |||||
* To retrieve the xattr list, first "reset", then repeatedly ask for the | |||||
* "next" entry. | |||||
*/ | |||||
__LA_DECL int archive_entry_sparse_count(struct archive_entry *); | |||||
__LA_DECL int archive_entry_sparse_reset(struct archive_entry *); | |||||
__LA_DECL int archive_entry_sparse_next(struct archive_entry *, | |||||
__LA_INT64_T * /* offset */, __LA_INT64_T * /* length */); | |||||
/* | |||||
* Utility to match up hardlinks. | |||||
* | |||||
* The 'struct archive_entry_linkresolver' is a cache of archive entries | |||||
* for files with multiple links. Here's how to use it: | |||||
* 1. Create a lookup object with archive_entry_linkresolver_new() | |||||
* 2. Tell it the archive format you're using. | |||||
* 3. Hand each archive_entry to archive_entry_linkify(). | |||||
* That function will return 0, 1, or 2 entries that should | |||||
* be written. | |||||
* 4. Call archive_entry_linkify(resolver, NULL) until | |||||
* no more entries are returned. | |||||
* 5. Call archive_entry_linkresolver_free(resolver) to free resources. | |||||
* | |||||
* The entries returned have their hardlink and size fields updated | |||||
* appropriately. If an entry is passed in that does not refer to | |||||
* a file with multiple links, it is returned unchanged. The intention | |||||
* is that you should be able to simply filter all entries through | |||||
* this machine. | |||||
* | |||||
* To make things more efficient, be sure that each entry has a valid | |||||
* nlinks value. The hardlink cache uses this to track when all links | |||||
* have been found. If the nlinks value is zero, it will keep every | |||||
* name in the cache indefinitely, which can use a lot of memory. | |||||
* | |||||
* Note that archive_entry_size() is reset to zero if the file | |||||
* body should not be written to the archive. Pay attention! | |||||
*/ | |||||
struct archive_entry_linkresolver; | |||||
/* | |||||
* There are three different strategies for marking hardlinks. | |||||
* The descriptions below name them after the best-known | |||||
* formats that rely on each strategy: | |||||
* | |||||
* "Old cpio" is the simplest, it always returns any entry unmodified. | |||||
* As far as I know, only cpio formats use this. Old cpio archives | |||||
* store every link with the full body; the onus is on the dearchiver | |||||
* to detect and properly link the files as they are restored. | |||||
* "tar" is also pretty simple; it caches a copy the first time it sees | |||||
* any link. Subsequent appearances are modified to be hardlink | |||||
* references to the first one without any body. Used by all tar | |||||
* formats, although the newest tar formats permit the "old cpio" strategy | |||||
* as well. This strategy is very simple for the dearchiver, | |||||
* and reasonably straightforward for the archiver. | |||||
* "new cpio" is trickier. It stores the body only with the last | |||||
* occurrence. The complication is that we might not | |||||
* see every link to a particular file in a single session, so | |||||
* there's no easy way to know when we've seen the last occurrence. | |||||
* The solution here is to queue one link until we see the next. | |||||
* At the end of the session, you can enumerate any remaining | |||||
* entries by calling archive_entry_linkify(NULL) and store those | |||||
* bodies. If you have a file with three links l1, l2, and l3, | |||||
* you'll get the following behavior if you see all three links: | |||||
* linkify(l1) => NULL (the resolver stores l1 internally) | |||||
* linkify(l2) => l1 (resolver stores l2, you write l1) | |||||
* linkify(l3) => l2, l3 (all links seen, you can write both). | |||||
* If you only see l1 and l2, you'll get this behavior: | |||||
* linkify(l1) => NULL | |||||
* linkify(l2) => l1 | |||||
* linkify(NULL) => l2 (at end, you retrieve remaining links) | |||||
* As the name suggests, this strategy is used by newer cpio variants. | |||||
* It's noticeably more complex for the archiver, slightly more complex | |||||
* for the dearchiver than the tar strategy, but makes it straightforward | |||||
* to restore a file using any link by simply continuing to scan until | |||||
* you see a link that is stored with a body. In contrast, the tar | |||||
* strategy requires you to rescan the archive from the beginning to | |||||
* correctly extract an arbitrary link. | |||||
*/ | |||||
__LA_DECL struct archive_entry_linkresolver *archive_entry_linkresolver_new(void); | |||||
__LA_DECL void archive_entry_linkresolver_set_strategy( | |||||
struct archive_entry_linkresolver *, int /* format_code */); | |||||
__LA_DECL void archive_entry_linkresolver_free(struct archive_entry_linkresolver *); | |||||
__LA_DECL void archive_entry_linkify(struct archive_entry_linkresolver *, | |||||
struct archive_entry **, struct archive_entry **); | |||||
__LA_DECL struct archive_entry *archive_entry_partial_links( | |||||
struct archive_entry_linkresolver *res, unsigned int *links); | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
/* This is meaningless outside of this header. */ | |||||
#undef __LA_DECL | |||||
#endif /* !ARCHIVE_ENTRY_H_INCLUDED */ |
@@ -0,0 +1,135 @@ | |||||
# Copyright (c) 2011, SmartFile <btimby@smartfile.com> | |||||
# All rights reserved. | |||||
# | |||||
# Redistribution and use in source and binary forms, with or without | |||||
# modification, are permitted provided that the following conditions are met: | |||||
# * Redistributions of source code must retain the above copyright | |||||
# notice, this list of conditions and the following disclaimer. | |||||
# * Redistributions in binary form must reproduce the above copyright | |||||
# notice, this list of conditions and the following disclaimer in the | |||||
# documentation and/or other materials provided with the distribution. | |||||
# * Neither the name of the organization nor the | |||||
# names of its contributors may be used to endorse or promote products | |||||
# derived from this software without specific prior written permission. | |||||
# | |||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY | |||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
import time | |||||
from libarchive import is_archive, Entry, SeekableArchive | |||||
from tarfile import DEFAULT_FORMAT, USTAR_FORMAT, GNU_FORMAT, PAX_FORMAT, ENCODING | |||||
from tarfile import REGTYPE, AREGTYPE, LNKTYPE, SYMTYPE, DIRTYPE, FIFOTYPE, CONTTYPE, CHRTYPE, BLKTYPE, GNUTYPE_SPARSE | |||||
FORMAT_CONVERSION = { | |||||
USTAR_FORMAT: 'tar', | |||||
GNU_FORMAT: 'gnu', | |||||
PAX_FORMAT: 'pax', | |||||
} | |||||
def is_tarfile(filename): | |||||
return is_archive(filename, formats=('tar', 'gnu', 'pax')) | |||||
def open(**kwargs): | |||||
return TarFile(**kwargs) | |||||
class TarInfo(Entry): | |||||
def __init__(self, name): | |||||
super(TarInfo, self).__init__(pathname=name) | |||||
fromtarfile = Entry.from_archive | |||||
def get_name(self): | |||||
return self.pathname | |||||
def set_name(self, value): | |||||
self.pathname = value | |||||
name = property(get_name, set_name) | |||||
@property | |||||
def get_type(self): | |||||
for attr, type in ( | |||||
('isdir', DIRTYPE), ('isfile', REGTYPE), ('issym', SYMTYPE), | |||||
('isfifo', FIFOTYPE), ('ischr', CHRTYPE), ('isblk', BLKTYPE), | |||||
): | |||||
if getattr(self, attr)(): | |||||
return type | |||||
def _get_missing(self): | |||||
raise NotImplemented() | |||||
def _set_missing(self, value): | |||||
raise NotImplemented() | |||||
pax_headers = property(_get_missing, _set_missing) | |||||
class TarFile(SeekableArchive): | |||||
def __init__(self, name=None, mode='r', fileobj=None, format=DEFAULT_FORMAT, tarinfo=TarInfo, encoding=ENCODING): | |||||
if name: | |||||
f = name | |||||
elif fileobj: | |||||
f = fileobj | |||||
try: | |||||
format = FORMAT_CONVERSION.get(format) | |||||
except KeyError: | |||||
raise Exception('Invalid tar format: %s' % format) | |||||
super(TarFile, self).__init__(f, mode=mode, format=format, entry_class=tarinfo, encoding=encoding) | |||||
getmember = SeekableArchive.getentry | |||||
list = SeekableArchive.printlist | |||||
extract = SeekableArchive.readpath | |||||
extractfile = SeekableArchive.readstream | |||||
def getmembers(self): | |||||
return list(self) | |||||
def getnames(self): | |||||
return list(self.iterpaths) | |||||
def next(self): | |||||
pass # TODO: how to do this? | |||||
def extract(self, member, path=None): | |||||
if path is None: | |||||
path = os.getcwd() | |||||
if isinstance(member, basestring): | |||||
f = os.path.join(path, member) | |||||
else: | |||||
f = os.path.join(path, member.pathname) | |||||
return self.readpath(member, f) | |||||
def add(self, name, arcname, recursive=True, exclude=None, filter=None): | |||||
pass # TODO: implement this. | |||||
def addfile(tarinfo, fileobj): | |||||
return self.writepath(fileobj, tarinfo) | |||||
def gettarinfo(name=None, arcname=None, fileobj=None): | |||||
if name: | |||||
f = name | |||||
elif fileobj: | |||||
f = fileobj | |||||
entry = self.entry_class.from_file(f) | |||||
if arcname: | |||||
entry.pathname = arcname | |||||
return entry | |||||
def _get_missing(self): | |||||
raise NotImplemented() | |||||
def _set_missing(self, value): | |||||
raise NotImplemented() | |||||
pax_headers = property(_get_missing, _set_missing) |
@@ -0,0 +1,151 @@ | |||||
# Copyright (c) 2011, SmartFile <btimby@smartfile.com> | |||||
# All rights reserved. | |||||
# | |||||
# Redistribution and use in source and binary forms, with or without | |||||
# modification, are permitted provided that the following conditions are met: | |||||
# * Redistributions of source code must retain the above copyright | |||||
# notice, this list of conditions and the following disclaimer. | |||||
# * Redistributions in binary form must reproduce the above copyright | |||||
# notice, this list of conditions and the following disclaimer in the | |||||
# documentation and/or other materials provided with the distribution. | |||||
# * Neither the name of the organization nor the | |||||
# names of its contributors may be used to endorse or promote products | |||||
# derived from this software without specific prior written permission. | |||||
# | |||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY | |||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
import os, time | |||||
from libarchive import is_archive, Entry, SeekableArchive | |||||
from zipfile import ZIP_STORED, ZIP_DEFLATED | |||||
def is_zipfile(filename): | |||||
return is_archive(filename, formats=('zip', )) | |||||
class ZipEntry(Entry): | |||||
def __init__(self, *args, **kwargs): | |||||
super(ZipEntry, self).__init__(*args, **kwargs) | |||||
def get_filename(self): | |||||
return self.pathname | |||||
def set_filename(self, value): | |||||
self.pathname = value | |||||
filename = property(get_filename, set_filename) | |||||
def get_file_size(self): | |||||
return self.size | |||||
def set_file_size(self, value): | |||||
assert isinstance(size, (int, long)), 'Please provide size as int or long.' | |||||
self.size = value | |||||
file_size = property(get_file_size, set_file_size) | |||||
def get_date_time(self): | |||||
return time.localtime(self.mtime)[0:6] | |||||
def set_date_time(self, value): | |||||
assert isinstance(value, tuple), 'mtime should be tuple (year, month, day, hour, minute, second).' | |||||
assert len(value) == 6, 'mtime should be tuple (year, month, day, hour, minute, second).' | |||||
self.mtime = time.mktime(value + (0, 0, 0)) | |||||
date_time = property(get_date_time, set_date_time) | |||||
header_offset = Entry.header_position | |||||
def _get_missing(self): | |||||
raise NotImplemented() | |||||
def _set_missing(self, value): | |||||
raise NotImplemented() | |||||
compress_type = property(_get_missing, _set_missing) | |||||
comment = property(_get_missing, _set_missing) | |||||
extra = property(_get_missing, _set_missing) | |||||
create_system = property(_get_missing, _set_missing) | |||||
create_version = property(_get_missing, _set_missing) | |||||
extract_version = property(_get_missing, _set_missing) | |||||
reserved = property(_get_missing, _set_missing) | |||||
flag_bits = property(_get_missing, _set_missing) | |||||
volume = property(_get_missing, _set_missing) | |||||
internal_attr = property(_get_missing, _set_missing) | |||||
external_attr = property(_get_missing, _set_missing) | |||||
CRC = property(_get_missing, _set_missing) | |||||
compress_size = property(_get_missing, _set_missing) | |||||
class ZipFile(SeekableArchive): | |||||
def __init__(self, f, mode='r', compression=ZIP_DEFLATED, allowZip64=False): | |||||
super(ZipFile, self).__init__(f, mode=mode, format='zip', entry_class=ZipEntry, encoding='CP437') | |||||
if mode == 'w' and compression == ZIP_STORED: | |||||
# Disable compression for writing. | |||||
_libarchive.archive_write_set_format_option(self.archive._a, "zip", "compression", "store") | |||||
self.compression = compression | |||||
getinfo = SeekableArchive.getentry | |||||
def namelist(self): | |||||
return list(self.iterpaths) | |||||
def infolist(self): | |||||
return list(self) | |||||
def open(self, name, mode, pwd=None): | |||||
if pwd: | |||||
raise NotImplemented('Encryption not supported.') | |||||
if mode == 'r': | |||||
return self.readstream(name) | |||||
else: | |||||
return self.writestream(name) | |||||
def extract(self, name, path=None, pwd=None): | |||||
if pwd: | |||||
raise NotImplemented('Encryption not supported.') | |||||
if not path: | |||||
path = os.getcwd() | |||||
return self.readpath(name, os.path.join(path, name)) | |||||
def extractall(self, path, names=None, pwd=None): | |||||
if pwd: | |||||
raise NotImplemented('Encryption not supported.') | |||||
if not names: | |||||
names = self.namelist() | |||||
if names: | |||||
for name in names: | |||||
self.extract(name, path) | |||||
def read(self, name, pwd=None): | |||||
if pwd: | |||||
raise NotImplemented('Encryption not supported.') | |||||
return self.read(name) | |||||
def writestr(self, member, data, compress_type=None): | |||||
if compress_type != self.compression: | |||||
raise Exception('Cannot change compression type for individual entries.') | |||||
return self.write(member, data) | |||||
def setpassword(self, pwd): | |||||
raise NotImplemented('Encryption not supported.') | |||||
def testzip(self): | |||||
raise NotImplemented() | |||||
def _get_missing(self): | |||||
raise NotImplemented() | |||||
def _set_missing(self, value): | |||||
raise NotImplemented() | |||||
comment = property(_get_missing, _set_missing) |
@@ -0,0 +1,119 @@ | |||||
#!/usr/bin/env python | |||||
# | |||||
# Copyright (c) 2011, SmartFile <btimby@smartfile.com> | |||||
# All rights reserved. | |||||
# | |||||
# Redistribution and use in source and binary forms, with or without | |||||
# modification, are permitted provided that the following conditions are met: | |||||
# * Redistributions of source code must retain the above copyright | |||||
# notice, this list of conditions and the following disclaimer. | |||||
# * Redistributions in binary form must reproduce the above copyright | |||||
# notice, this list of conditions and the following disclaimer in the | |||||
# documentation and/or other materials provided with the distribution. | |||||
# * Neither the name of the organization nor the | |||||
# names of its contributors may be used to endorse or promote products | |||||
# derived from this software without specific prior written permission. | |||||
# | |||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY | |||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
from os import environ | |||||
try: | |||||
from setuptools import setup, Extension | |||||
from setuptools.command.build_ext import build_ext | |||||
except ImportError: | |||||
from distutils.core import setup, Extension | |||||
from distutils.command.build_ext import build_ext | |||||
name = 'python-libarchive' | |||||
version = '3.1.2' | |||||
release = '1' | |||||
versrel = version + '-' + release | |||||
readme = 'README.rst' | |||||
download_url = "http://" + name + ".googlecode.com/files/" + name + "-" + \ | |||||
versrel + ".tar.gz" | |||||
long_description = file(readme).read() | |||||
class build_ext_extra(build_ext, object): | |||||
""" | |||||
Extend build_ext allowing extra_compile_args and extra_link_args to be set | |||||
on the command-line. | |||||
""" | |||||
user_options = build_ext.user_options | |||||
user_options.append( | |||||
('extra-compile-args=', None, | |||||
'Extra arguments passed directly to the compiler') | |||||
) | |||||
user_options.append( | |||||
('extra-link-args=', None, | |||||
'Extra arguments passed directly to the linker') | |||||
) | |||||
def initialize_options(self): | |||||
build_ext.initialize_options(self) | |||||
self.extra_compile_args = None | |||||
self.extra_link_args = None | |||||
def build_extension(self, ext): | |||||
if self.extra_compile_args: | |||||
ext.extra_compile_args.append(self.extra_compile_args) | |||||
if self.extra_link_args: | |||||
ext.extra_link_args.append(self.extra_link_args) | |||||
super(build_ext_extra, self).build_extension(ext) | |||||
# Use a provided libarchive else default to hard-coded path. | |||||
libarchivePrefix = environ.get('LIBARCHIVE_PREFIX') | |||||
if libarchivePrefix: | |||||
extra_compile_args = ['-I{0}/include'.format(libarchivePrefix)] | |||||
extra_link_args = ['-Wl,-rpath={0}/lib'.format(libarchivePrefix)] | |||||
environ['LDFLAGS'] = '-L{0}/lib {1}'.format(libarchivePrefix, | |||||
environ.get('LDFLAGS', '')) | |||||
else: | |||||
extra_compile_args = [] | |||||
extra_link_args = ['-l:libarchive.so.13.1.2'] | |||||
__libarchive = Extension(name='libarchive.__libarchive', | |||||
sources=['libarchive/_libarchive_wrap.c'], | |||||
libraries=['archive'], | |||||
extra_compile_args=extra_compile_args, | |||||
extra_link_args=extra_link_args, | |||||
include_dirs=['libarchive'], | |||||
) | |||||
setup(name = name, | |||||
version = versrel, | |||||
description = 'A libarchive wrapper for Python.', | |||||
long_description = long_description, | |||||
license = 'BSD-style license', | |||||
platforms = ['any'], | |||||
author = 'Ben Timby', | |||||
author_email = 'btimby at gmail dot com', | |||||
url = 'http://code.google.com/p/python-libarchive/', | |||||
download_url = download_url, | |||||
packages = ['libarchive'], | |||||
classifiers = [ | |||||
'Development Status :: 4 - Beta', | |||||
'Intended Audience :: Developers', | |||||
'Operating System :: OS Independent', | |||||
'Programming Language :: C', | |||||
'Programming Language :: Python', | |||||
'Topic :: System :: Archiving :: Compression', | |||||
'Topic :: Software Development :: Libraries :: Python Modules', | |||||
], | |||||
cmdclass = { | |||||
'build_ext': build_ext_extra, | |||||
}, | |||||
ext_modules = [__libarchive], | |||||
) |
@@ -0,0 +1,220 @@ | |||||
#!/usr/bin/env python | |||||
# coding=utf-8 | |||||
# | |||||
# Copyright (c) 2011, SmartFile <btimby@smartfile.com> | |||||
# All rights reserved. | |||||
# | |||||
# Redistribution and use in source and binary forms, with or without | |||||
# modification, are permitted provided that the following conditions are met: | |||||
# * Redistributions of source code must retain the above copyright | |||||
# notice, this list of conditions and the following disclaimer. | |||||
# * Redistributions in binary form must reproduce the above copyright | |||||
# notice, this list of conditions and the following disclaimer in the | |||||
# documentation and/or other materials provided with the distribution. | |||||
# * Neither the name of the organization nor the | |||||
# names of its contributors may be used to endorse or promote products | |||||
# derived from this software without specific prior written permission. | |||||
# | |||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY | |||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
import os, unittest, tempfile, random, string, subprocess | |||||
from libarchive import is_archive_name, is_archive | |||||
from libarchive.zip import is_zipfile, ZipFile, ZipEntry | |||||
TMPDIR = tempfile.mkdtemp() | |||||
ZIPCMD = '/usr/bin/zip' | |||||
ZIPFILE = 'test.zip' | |||||
ZIPPATH = os.path.join(TMPDIR, ZIPFILE) | |||||
FILENAMES = [ | |||||
'test1.txt', | |||||
'foo', | |||||
# TODO: test non-ASCII chars. | |||||
#'álért.txt', | |||||
] | |||||
def make_temp_files(): | |||||
print TMPDIR | |||||
if not os.path.exists(ZIPPATH): | |||||
for name in FILENAMES: | |||||
file(os.path.join(TMPDIR, name), 'w').write(''.join(random.sample(string.printable, 10))) | |||||
def make_temp_archive(): | |||||
if not os.access(ZIPCMD, os.X_OK): | |||||
raise AssertionError('Cannot execute %s.' % ZIPCMD) | |||||
cmd = [ZIPCMD, ZIPFILE] | |||||
make_temp_files() | |||||
cmd.extend(FILENAMES) | |||||
os.chdir(TMPDIR) | |||||
subprocess.call(cmd) | |||||
class TestIsArchiveName(unittest.TestCase): | |||||
def test_formats(self): | |||||
self.assertEqual(is_archive_name('foo'), None) | |||||
self.assertEqual(is_archive_name('foo.txt'), None) | |||||
self.assertEqual(is_archive_name('foo.txt.gz'), None) | |||||
self.assertEqual(is_archive_name('foo.tar.gz'), 'tar') | |||||
self.assertEqual(is_archive_name('foo.tar.bz2'), 'tar') | |||||
self.assertEqual(is_archive_name('foo.zip'), 'zip') | |||||
self.assertEqual(is_archive_name('foo.rar'), 'rar') | |||||
self.assertEqual(is_archive_name('foo.iso'), 'iso') | |||||
self.assertEqual(is_archive_name('foo.rpm'), 'cpio') | |||||
class TestIsArchiveZip(unittest.TestCase): | |||||
def setUp(self): | |||||
make_temp_archive() | |||||
def test_zip(self): | |||||
self.assertEqual(is_archive(ZIPPATH), True) | |||||
self.assertEqual(is_archive(ZIPPATH, formats=('zip', )), True) | |||||
self.assertEqual(is_archive(ZIPPATH, formats=('tar', )), False) | |||||
class TestIsArchiveTar(unittest.TestCase): | |||||
def test_tar(self): | |||||
pass | |||||
# TODO: incorporate tests from: | |||||
# http://hg.python.org/cpython/file/a6e1d926cd98/Lib/test/test_zipfile.py | |||||
class TestZipRead(unittest.TestCase): | |||||
def setUp(self): | |||||
make_temp_archive() | |||||
def test_iszipfile(self): | |||||
self.assertEqual(is_zipfile('/dev/null'), False) | |||||
self.assertEqual(is_zipfile(ZIPPATH), True) | |||||
def test_iterate(self): | |||||
f = file(ZIPPATH, mode='r') | |||||
z = ZipFile(f, 'r') | |||||
count = 0 | |||||
for e in z: | |||||
count += 1 | |||||
self.assertEqual(count, len(FILENAMES), 'Did not enumerate correct number of items in archive.') | |||||
def test_deferred_close_by_archive(self): | |||||
""" Test archive deferred close without a stream. """ | |||||
f = file(ZIPPATH, mode='r') | |||||
z = ZipFile(f, 'r') | |||||
self.assertIsNotNone(z._a) | |||||
self.assertIsNone(z._stream) | |||||
z.close() | |||||
self.assertIsNone(z._a) | |||||
def test_deferred_close_by_stream(self): | |||||
""" Ensure archive closes self if stream is closed first. """ | |||||
f = file(ZIPPATH, mode='r') | |||||
z = ZipFile(f, 'r') | |||||
stream = z.readstream(FILENAMES[0]) | |||||
stream.close() | |||||
# Make sure archive stays open after stream is closed. | |||||
self.assertIsNotNone(z._a) | |||||
self.assertIsNone(z._stream) | |||||
z.close() | |||||
self.assertIsNone(z._a) | |||||
self.assertTrue(stream.closed) | |||||
def test_close_stream_first(self): | |||||
""" Ensure that archive stays open after being closed if a stream is | |||||
open. Further, ensure closing the stream closes the archive. """ | |||||
f = file(ZIPPATH, mode='r') | |||||
z = ZipFile(f, 'r') | |||||
stream = z.readstream(FILENAMES[0]) | |||||
z.close() | |||||
try: | |||||
stream.read() | |||||
except: | |||||
self.fail("Reading stream from closed archive failed!") | |||||
stream.close() | |||||
# Now the archive should close. | |||||
self.assertIsNone(z._a) | |||||
self.assertTrue(stream.closed) | |||||
self.assertIsNone(z._stream) | |||||
def test_filenames(self): | |||||
f = file(ZIPPATH, mode='r') | |||||
z = ZipFile(f, 'r') | |||||
names = [] | |||||
for e in z: | |||||
names.append(e.filename) | |||||
self.assertEqual(names, FILENAMES, 'File names differ in archive.') | |||||
#~ def test_non_ascii(self): | |||||
#~ pass | |||||
def test_extract_str(self): | |||||
pass | |||||
class TestZipWrite(unittest.TestCase): | |||||
def setUp(self): | |||||
make_temp_files() | |||||
def test_writepath(self): | |||||
f = file(ZIPPATH, mode='w') | |||||
z = ZipFile(f, 'w') | |||||
for fname in FILENAMES: | |||||
z.writepath(file(os.path.join(TMPDIR, fname), 'r')) | |||||
z.close() | |||||
def test_writestream(self): | |||||
f = file(ZIPPATH, mode='w') | |||||
z = ZipFile(f, 'w') | |||||
for fname in FILENAMES: | |||||
full_path = os.path.join(TMPDIR, fname) | |||||
i = file(full_path) | |||||
o = z.writestream(fname) | |||||
while True: | |||||
data = i.read(1) | |||||
if not data: | |||||
break | |||||
o.write(data) | |||||
o.close() | |||||
i.close() | |||||
z.close() | |||||
def test_writestream_unbuffered(self): | |||||
f = file(ZIPPATH, mode='w') | |||||
z = ZipFile(f, 'w') | |||||
for fname in FILENAMES: | |||||
full_path = os.path.join(TMPDIR, fname) | |||||
i = file(full_path) | |||||
o = z.writestream(fname, os.path.getsize(full_path)) | |||||
while True: | |||||
data = i.read(1) | |||||
if not data: | |||||
break | |||||
o.write(data) | |||||
o.close() | |||||
i.close() | |||||
z.close() | |||||
def test_deferred_close_by_archive(self): | |||||
""" Test archive deferred close without a stream. """ | |||||
f = file(ZIPPATH, mode='w') | |||||
z = ZipFile(f, 'w') | |||||
o = z.writestream(FILENAMES[0]) | |||||
z.close() | |||||
self.assertIsNotNone(z._a) | |||||
self.assertIsNotNone(z._stream) | |||||
o.write('testdata') | |||||
o.close() | |||||
self.assertIsNone(z._a) | |||||
self.assertIsNone(z._stream) | |||||
z.close() | |||||
if __name__ == '__main__': | |||||
unittest.main() |