@@ -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() |