Skip to content

Commit

Permalink
Merge pull request #114 from Changaco/various
Browse files Browse the repository at this point in the history
  • Loading branch information
Changaco authored Jun 1, 2021
2 parents 9cf50ca + c931af3 commit 222f41a
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 46 deletions.
8 changes: 5 additions & 3 deletions libarchive/ffi.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@
)
OPEN_CALLBACK = CFUNCTYPE(c_int, c_void_p, c_void_p)
CLOSE_CALLBACK = CFUNCTYPE(c_int, c_void_p, c_void_p)
VOID_CB = lambda *_: ARCHIVE_OK

NO_OPEN_CB = ctypes.cast(None, OPEN_CALLBACK)
NO_CLOSE_CB = ctypes.cast(None, CLOSE_CALLBACK)


# Type aliases, for readability
Expand Down Expand Up @@ -79,7 +81,7 @@ def _error_string(archive_p):

def archive_error(archive_p, retcode):
msg = _error_string(archive_p)
raise ArchiveError(msg, errno(archive_p), retcode, archive_p)
return ArchiveError(msg, errno(archive_p), retcode, archive_p)


def check_null(ret, func, args):
Expand Down Expand Up @@ -328,5 +330,5 @@ def get_write_filter_function(filter_name):
except AttributeError:
logger.info(
f"the libarchive being used (version {version_number()}, "
f"path {ffi.libarchive_path}) doesn't support encryption"
f"path {libarchive_path}) doesn't support encryption"
)
54 changes: 16 additions & 38 deletions libarchive/read.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from . import ffi
from .ffi import (
ARCHIVE_EOF, OPEN_CALLBACK, READ_CALLBACK, CLOSE_CALLBACK, SEEK_CALLBACK,
VOID_CB, page_size,
NO_OPEN_CB, NO_CLOSE_CB, page_size,
)
from .entry import ArchiveEntry, new_archive_entry

Expand Down Expand Up @@ -57,15 +57,17 @@ def new_archive_read(format_name='all', filter_name='all', passphrase=None):
@contextmanager
def custom_reader(
read_func, format_name='all', filter_name='all',
open_func=VOID_CB, close_func=VOID_CB, block_size=page_size,
archive_read_class=ArchiveRead, passphrase=None,
open_func=None, seek_func=None, close_func=None,
block_size=page_size, archive_read_class=ArchiveRead, passphrase=None,
):
"""Read an archive using a custom function.
"""
open_cb = OPEN_CALLBACK(open_func)
open_cb = OPEN_CALLBACK(open_func) if open_func else NO_OPEN_CB
read_cb = READ_CALLBACK(read_func)
close_cb = CLOSE_CALLBACK(close_func)
close_cb = CLOSE_CALLBACK(close_func) if close_func else NO_CLOSE_CB
with new_archive_read(format_name, filter_name, passphrase) as archive_p:
if seek_func:
ffi.read_set_seek_callback(archive_p, SEEK_CALLBACK(seek_func))
ffi.read_open(archive_p, None, open_cb, read_cb, close_cb)
yield archive_read_class(archive_p)

Expand Down Expand Up @@ -117,36 +119,9 @@ def stream_reader(
"""Read an archive from a stream.
The `stream` object must support the standard `readinto` method.
"""
buf = create_string_buffer(block_size)
buf_p = cast(buf, c_void_p)
def read_func(archive_p, context, ptrptr):
# readinto the buffer, returns number of bytes read
length = stream.readinto(buf)
# write the address of the buffer into the pointer
ptrptr = cast(ptrptr, POINTER(c_void_p))
ptrptr[0] = buf_p
# tell libarchive how much data was written into the buffer
return length

open_cb = OPEN_CALLBACK(VOID_CB)
read_cb = READ_CALLBACK(read_func)
close_cb = CLOSE_CALLBACK(VOID_CB)
with new_archive_read(format_name, filter_name, passphrase) as archive_p:
ffi.read_open(archive_p, None, open_cb, read_cb, close_cb)
yield ArchiveRead(archive_p)


@contextmanager
def seekable_stream_reader(
stream, format_name='all', filter_name='all', block_size=page_size,
passphrase=None,
):
"""Read an archive from a seekable stream.
The `stream` object must support the standard `readinto`, 'seek' and
'tell' methods.
If `stream.seekable()` returns `True`, then an appropriate seek callback is
passed to libarchive.
"""
buf = create_string_buffer(block_size)
buf_p = cast(buf, c_void_p)
Expand All @@ -165,11 +140,14 @@ def seek_func(archive_p, context, offset, whence):
# tell libarchive the current position
return stream.tell()

open_cb = OPEN_CALLBACK(VOID_CB)
open_cb = NO_OPEN_CB
read_cb = READ_CALLBACK(read_func)
seek_cb = SEEK_CALLBACK(seek_func)
close_cb = CLOSE_CALLBACK(VOID_CB)
close_cb = NO_CLOSE_CB
with new_archive_read(format_name, filter_name, passphrase) as archive_p:
ffi.read_set_seek_callback(archive_p, seek_cb)
if stream.seekable():
ffi.read_set_seek_callback(archive_p, SEEK_CALLBACK(seek_func))
ffi.read_open(archive_p, None, open_cb, read_cb, close_cb)
yield ArchiveRead(archive_p)


seekable_stream_reader = stream_reader
10 changes: 5 additions & 5 deletions libarchive/write.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
from . import ffi
from .entry import ArchiveEntry, new_archive_entry
from .ffi import (
OPEN_CALLBACK, WRITE_CALLBACK, CLOSE_CALLBACK, VOID_CB, REGULAR_FILE,
DEFAULT_UNIX_PERMISSION, ARCHIVE_EOF,
OPEN_CALLBACK, WRITE_CALLBACK, CLOSE_CALLBACK, NO_OPEN_CB, NO_CLOSE_CB,
REGULAR_FILE, DEFAULT_UNIX_PERMISSION, ARCHIVE_EOF,
page_size, entry_sourcepath, entry_clear, read_disk_new, read_disk_open_w,
read_next_header2, read_disk_descend, read_free, write_header, write_data,
write_finish_entry, entry_set_size, entry_set_filetype, entry_set_perm,
Expand Down Expand Up @@ -187,17 +187,17 @@ def new_archive_write(format_name, filter_name=None, options='', passphrase=None
@contextmanager
def custom_writer(
write_func, format_name, filter_name=None,
open_func=VOID_CB, close_func=VOID_CB, block_size=page_size,
open_func=None, close_func=None, block_size=page_size,
archive_write_class=ArchiveWrite, options='', passphrase=None,
):

def write_cb_internal(archive_p, context, buffer_, length):
data = cast(buffer_, POINTER(c_char * length))[0]
return write_func(data)

open_cb = OPEN_CALLBACK(open_func)
open_cb = OPEN_CALLBACK(open_func) if open_func else NO_OPEN_CB
write_cb = WRITE_CALLBACK(write_cb_internal)
close_cb = CLOSE_CALLBACK(close_func)
close_cb = CLOSE_CALLBACK(close_func) if close_func else NO_CLOSE_CB

with new_archive_write(format_name, filter_name, options,
passphrase) as archive_p:
Expand Down

0 comments on commit 222f41a

Please sign in to comment.