Skip to content

Commit 222f41a

Browse files
authored
Merge pull request #114 from Changaco/various
2 parents 9cf50ca + c931af3 commit 222f41a

File tree

3 files changed

+26
-46
lines changed

3 files changed

+26
-46
lines changed

libarchive/ffi.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@
5151
)
5252
OPEN_CALLBACK = CFUNCTYPE(c_int, c_void_p, c_void_p)
5353
CLOSE_CALLBACK = CFUNCTYPE(c_int, c_void_p, c_void_p)
54-
VOID_CB = lambda *_: ARCHIVE_OK
54+
55+
NO_OPEN_CB = ctypes.cast(None, OPEN_CALLBACK)
56+
NO_CLOSE_CB = ctypes.cast(None, CLOSE_CALLBACK)
5557

5658

5759
# Type aliases, for readability
@@ -79,7 +81,7 @@ def _error_string(archive_p):
7981

8082
def archive_error(archive_p, retcode):
8183
msg = _error_string(archive_p)
82-
raise ArchiveError(msg, errno(archive_p), retcode, archive_p)
84+
return ArchiveError(msg, errno(archive_p), retcode, archive_p)
8385

8486

8587
def check_null(ret, func, args):
@@ -328,5 +330,5 @@ def get_write_filter_function(filter_name):
328330
except AttributeError:
329331
logger.info(
330332
f"the libarchive being used (version {version_number()}, "
331-
f"path {ffi.libarchive_path}) doesn't support encryption"
333+
f"path {libarchive_path}) doesn't support encryption"
332334
)

libarchive/read.py

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from . import ffi
66
from .ffi import (
77
ARCHIVE_EOF, OPEN_CALLBACK, READ_CALLBACK, CLOSE_CALLBACK, SEEK_CALLBACK,
8-
VOID_CB, page_size,
8+
NO_OPEN_CB, NO_CLOSE_CB, page_size,
99
)
1010
from .entry import ArchiveEntry, new_archive_entry
1111

@@ -57,15 +57,17 @@ def new_archive_read(format_name='all', filter_name='all', passphrase=None):
5757
@contextmanager
5858
def custom_reader(
5959
read_func, format_name='all', filter_name='all',
60-
open_func=VOID_CB, close_func=VOID_CB, block_size=page_size,
61-
archive_read_class=ArchiveRead, passphrase=None,
60+
open_func=None, seek_func=None, close_func=None,
61+
block_size=page_size, archive_read_class=ArchiveRead, passphrase=None,
6262
):
6363
"""Read an archive using a custom function.
6464
"""
65-
open_cb = OPEN_CALLBACK(open_func)
65+
open_cb = OPEN_CALLBACK(open_func) if open_func else NO_OPEN_CB
6666
read_cb = READ_CALLBACK(read_func)
67-
close_cb = CLOSE_CALLBACK(close_func)
67+
close_cb = CLOSE_CALLBACK(close_func) if close_func else NO_CLOSE_CB
6868
with new_archive_read(format_name, filter_name, passphrase) as archive_p:
69+
if seek_func:
70+
ffi.read_set_seek_callback(archive_p, SEEK_CALLBACK(seek_func))
6971
ffi.read_open(archive_p, None, open_cb, read_cb, close_cb)
7072
yield archive_read_class(archive_p)
7173

@@ -117,36 +119,9 @@ def stream_reader(
117119
"""Read an archive from a stream.
118120
119121
The `stream` object must support the standard `readinto` method.
120-
"""
121-
buf = create_string_buffer(block_size)
122-
buf_p = cast(buf, c_void_p)
123122
124-
def read_func(archive_p, context, ptrptr):
125-
# readinto the buffer, returns number of bytes read
126-
length = stream.readinto(buf)
127-
# write the address of the buffer into the pointer
128-
ptrptr = cast(ptrptr, POINTER(c_void_p))
129-
ptrptr[0] = buf_p
130-
# tell libarchive how much data was written into the buffer
131-
return length
132-
133-
open_cb = OPEN_CALLBACK(VOID_CB)
134-
read_cb = READ_CALLBACK(read_func)
135-
close_cb = CLOSE_CALLBACK(VOID_CB)
136-
with new_archive_read(format_name, filter_name, passphrase) as archive_p:
137-
ffi.read_open(archive_p, None, open_cb, read_cb, close_cb)
138-
yield ArchiveRead(archive_p)
139-
140-
141-
@contextmanager
142-
def seekable_stream_reader(
143-
stream, format_name='all', filter_name='all', block_size=page_size,
144-
passphrase=None,
145-
):
146-
"""Read an archive from a seekable stream.
147-
148-
The `stream` object must support the standard `readinto`, 'seek' and
149-
'tell' methods.
123+
If `stream.seekable()` returns `True`, then an appropriate seek callback is
124+
passed to libarchive.
150125
"""
151126
buf = create_string_buffer(block_size)
152127
buf_p = cast(buf, c_void_p)
@@ -165,11 +140,14 @@ def seek_func(archive_p, context, offset, whence):
165140
# tell libarchive the current position
166141
return stream.tell()
167142

168-
open_cb = OPEN_CALLBACK(VOID_CB)
143+
open_cb = NO_OPEN_CB
169144
read_cb = READ_CALLBACK(read_func)
170-
seek_cb = SEEK_CALLBACK(seek_func)
171-
close_cb = CLOSE_CALLBACK(VOID_CB)
145+
close_cb = NO_CLOSE_CB
172146
with new_archive_read(format_name, filter_name, passphrase) as archive_p:
173-
ffi.read_set_seek_callback(archive_p, seek_cb)
147+
if stream.seekable():
148+
ffi.read_set_seek_callback(archive_p, SEEK_CALLBACK(seek_func))
174149
ffi.read_open(archive_p, None, open_cb, read_cb, close_cb)
175150
yield ArchiveRead(archive_p)
151+
152+
153+
seekable_stream_reader = stream_reader

libarchive/write.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
from . import ffi
66
from .entry import ArchiveEntry, new_archive_entry
77
from .ffi import (
8-
OPEN_CALLBACK, WRITE_CALLBACK, CLOSE_CALLBACK, VOID_CB, REGULAR_FILE,
9-
DEFAULT_UNIX_PERMISSION, ARCHIVE_EOF,
8+
OPEN_CALLBACK, WRITE_CALLBACK, CLOSE_CALLBACK, NO_OPEN_CB, NO_CLOSE_CB,
9+
REGULAR_FILE, DEFAULT_UNIX_PERMISSION, ARCHIVE_EOF,
1010
page_size, entry_sourcepath, entry_clear, read_disk_new, read_disk_open_w,
1111
read_next_header2, read_disk_descend, read_free, write_header, write_data,
1212
write_finish_entry, entry_set_size, entry_set_filetype, entry_set_perm,
@@ -187,17 +187,17 @@ def new_archive_write(format_name, filter_name=None, options='', passphrase=None
187187
@contextmanager
188188
def custom_writer(
189189
write_func, format_name, filter_name=None,
190-
open_func=VOID_CB, close_func=VOID_CB, block_size=page_size,
190+
open_func=None, close_func=None, block_size=page_size,
191191
archive_write_class=ArchiveWrite, options='', passphrase=None,
192192
):
193193

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

198-
open_cb = OPEN_CALLBACK(open_func)
198+
open_cb = OPEN_CALLBACK(open_func) if open_func else NO_OPEN_CB
199199
write_cb = WRITE_CALLBACK(write_cb_internal)
200-
close_cb = CLOSE_CALLBACK(close_func)
200+
close_cb = CLOSE_CALLBACK(close_func) if close_func else NO_CLOSE_CB
201201

202202
with new_archive_write(format_name, filter_name, options,
203203
passphrase) as archive_p:

0 commit comments

Comments
 (0)