Skip to content

Commit

Permalink
Merge pull request #72 from srandall52/master
Browse files Browse the repository at this point in the history
Set options for writing archive. Set uid/gid lookup for reading disk.
  • Loading branch information
Changaco authored Jun 10, 2018
2 parents c4d812a + 3d59828 commit 3894218
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 13 deletions.
2 changes: 2 additions & 0 deletions libarchive/ffi.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ def ffi(name, argtypes, restype, errcheck=None):
# archive_read_disk

ffi('read_disk_new', [], c_archive_p, check_null)
ffi('read_disk_set_behavior', [c_archive_p, c_int], c_int, check_int)
ffi('read_disk_set_standard_lookup', [c_archive_p], c_int, check_int)
ffi('read_disk_open', [c_archive_p, c_char_p], c_int, check_int)
ffi('read_disk_open_w', [c_archive_p, c_wchar_p], c_int, check_int)
Expand All @@ -209,6 +210,7 @@ def ffi(name, argtypes, restype, errcheck=None):
# archive_write

ffi('write_new', [], c_archive_p, check_null)
ffi('write_set_options', [c_archive_p, c_char_p], c_int, check_int)

ffi('write_disk_new', [], c_archive_p, check_null)
ffi('write_disk_set_options', [c_archive_p, c_int], c_int, check_int)
Expand Down
7 changes: 7 additions & 0 deletions libarchive/flags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
READDISK_RESTORE_ATIME = 0x0001
READDISK_HONOR_NODUMP = 0x0002
READDISK_MAC_COPYFILE = 0x0004
READDISK_NO_TRAVERSE_MOUNTS = 0x0008
READDISK_NO_XATTR = 0x0010
READDISK_NO_ACL = 0x0020
READDISK_NO_FFLAGS = 0x0040
38 changes: 25 additions & 13 deletions libarchive/write.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@
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
write_finish_entry, entry_set_size, entry_set_filetype, entry_set_perm,
read_disk_set_behavior
)


@contextmanager
def new_archive_read_disk(path):
def new_archive_read_disk(path, flags=0, lookup=False):
archive_p = read_disk_new()
read_disk_set_behavior(archive_p, flags)
if lookup:
ffi.read_disk_set_standard_lookup(archive_p)
read_disk_open_w(archive_p, path)
try:
yield archive_p
Expand All @@ -39,8 +43,10 @@ def add_entries(self, entries):
write_data(write_p, block, len(block))
write_finish_entry(write_p)

def add_files(self, *paths):
def add_files(self, *paths, **kw):
"""Read the given paths from disk and add them to the archive.
The keyword arguments (`**kw`) are passed to `new_archive_read_disk`.
"""
write_p = self._pointer

Expand All @@ -51,7 +57,7 @@ def add_files(self, *paths):
with new_archive_entry() as entry_p:
entry = ArchiveEntry(None, entry_p)
for path in paths:
with new_archive_read_disk(path) as read_p:
with new_archive_read_disk(path, **kw) as read_p:
while 1:
r = read_next_header2(read_p, entry_p)
if r == ARCHIVE_EOF:
Expand Down Expand Up @@ -109,11 +115,15 @@ def add_file_from_memory(


@contextmanager
def new_archive_write(format_name, filter_name=None):
def new_archive_write(format_name, filter_name=None, options=''):
archive_p = ffi.write_new()
getattr(ffi, 'write_set_format_'+format_name)(archive_p)
if filter_name:
getattr(ffi, 'write_add_filter_'+filter_name)(archive_p)
if options:
if not isinstance(options, bytes):
options = options.encode('utf-8')
ffi.write_set_options(archive_p, options)
try:
yield archive_p
ffi.write_close(archive_p)
Expand All @@ -128,7 +138,7 @@ def new_archive_write(format_name, filter_name=None):
def custom_writer(
write_func, format_name, filter_name=None,
open_func=VOID_CB, close_func=VOID_CB, block_size=page_size,
archive_write_class=ArchiveWrite
archive_write_class=ArchiveWrite, options=''
):

def write_cb_internal(archive_p, context, buffer_, length):
Expand All @@ -139,7 +149,7 @@ def write_cb_internal(archive_p, context, buffer_, length):
write_cb = WRITE_CALLBACK(write_cb_internal)
close_cb = CLOSE_CALLBACK(close_func)

with new_archive_write(format_name, filter_name) as archive_p:
with new_archive_write(format_name, filter_name, options) as archive_p:
ffi.write_set_bytes_in_last_block(archive_p, 1)
ffi.write_set_bytes_per_block(archive_p, block_size)
ffi.write_open(archive_p, None, open_cb, write_cb, close_cb)
Expand All @@ -148,28 +158,30 @@ def write_cb_internal(archive_p, context, buffer_, length):

@contextmanager
def fd_writer(
fd, format_name, filter_name=None, archive_write_class=ArchiveWrite
fd, format_name, filter_name=None,
archive_write_class=ArchiveWrite, options=''
):
with new_archive_write(format_name, filter_name) as archive_p:
with new_archive_write(format_name, filter_name, options) as archive_p:
ffi.write_open_fd(archive_p, fd)
yield archive_write_class(archive_p)


@contextmanager
def file_writer(
filepath, format_name, filter_name=None,
archive_write_class=ArchiveWrite
archive_write_class=ArchiveWrite, options=''
):
with new_archive_write(format_name, filter_name) as archive_p:
with new_archive_write(format_name, filter_name, options) as archive_p:
ffi.write_open_filename_w(archive_p, filepath)
yield archive_write_class(archive_p)


@contextmanager
def memory_writer(
buf, format_name, filter_name=None, archive_write_class=ArchiveWrite
buf, format_name, filter_name=None,
archive_write_class=ArchiveWrite, options=''
):
with new_archive_write(format_name, filter_name) as archive_p:
with new_archive_write(format_name, filter_name, options) as archive_p:
used = byref(c_size_t())
buf_p = cast(buf, c_void_p)
ffi.write_open_memory(archive_p, buf_p, len(buf), used)
Expand Down

0 comments on commit 3894218

Please sign in to comment.