Browse Source

Fixed the file mode not reading the correct integer value

test_fixup
root 10 years ago
commit
bfc45cb236
17 changed files with 10410 additions and 0 deletions
  1. BIN
      .coverage
  2. +3
    -0
      .gitignore
  3. +1
    -0
      MANIFEST.in
  4. +27
    -0
      README.rst
  5. +216
    -0
      docs/conf.py
  6. +20
    -0
      docs/index.rst
  7. +23
    -0
      libarchive/Makefile
  8. +645
    -0
      libarchive/__init__.py
  9. +382
    -0
      libarchive/_libarchive.i
  10. +478
    -0
      libarchive/_libarchive.py
  11. +6430
    -0
      libarchive/_libarchive_wrap.c
  12. +945
    -0
      libarchive/archive.h
  13. +615
    -0
      libarchive/archive_entry.h
  14. +135
    -0
      libarchive/tar.py
  15. +151
    -0
      libarchive/zip.py
  16. +119
    -0
      setup.py
  17. +220
    -0
      tests.py

BIN
.coverage View File


+ 3
- 0
.gitignore View File

@@ -0,0 +1,3 @@
venv
*.pyc
*.swp

+ 1
- 0
MANIFEST.in View File

@@ -0,0 +1 @@
include README.rst

+ 27
- 0
README.rst View File

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


+ 216
- 0
docs/conf.py View File

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

+ 20
- 0
docs/index.rst View File

@@ -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`


+ 23
- 0
libarchive/Makefile View File

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

+ 645
- 0
libarchive/__init__.py View File

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

+ 382
- 0
libarchive/_libarchive.i View File

@@ -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);
}
%}

+ 478
- 0
libarchive/_libarchive.py View File

@@ -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.



+ 6430
- 0
libarchive/_libarchive_wrap.c
File diff suppressed because it is too large
View File


+ 945
- 0
libarchive/archive.h View File

@@ -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 */

+ 615
- 0
libarchive/archive_entry.h View File

@@ -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 */

+ 135
- 0
libarchive/tar.py View File

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

+ 151
- 0
libarchive/zip.py View File

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

+ 119
- 0
setup.py View File

@@ -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],
)

+ 220
- 0
tests.py View File

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

Loading…
Cancel
Save