def _archive_read_disk_set_standard_lookup(archive): try: return libarchive.calls.archive_read.\ c_archive_read_disk_set_standard_lookup(archive) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_read_set_format(archive, code): try: return libarchive.calls.archive_read.c_archive_read_set_format( archive, code) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_read_disk_descend(archive): result = libarchive.calls.archive_read.c_archive_read_disk_descend(archive) if result not in (libarchive.constants.archive.ARCHIVE_OK, libarchive.constants.archive.ARCHIVE_WARN): message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_read_disk_open(archive, filepath): try: return libarchive.calls.archive_read.c_archive_read_disk_open( archive, filepath) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_read_support_filter_all(archive): try: return libarchive.calls.archive_read.c_archive_read_support_filter_all( archive) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_read_support_format_7zip(archive): try: return libarchive.calls.archive_read.\ c_archive_read_support_format_7zip(archive) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_read_open_filename(archive, filepath, block_size_bytes): try: return libarchive.calls.archive_read.c_archive_read_open_filename( archive, filepath, block_size_bytes) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_write_open_filename(archive, filepath): try: libarchive.calls.archive_write.c_archive_write_open_filename( archive, filepath) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_write_header(archive, entry): try: return libarchive.calls.archive_write.c_archive_write_header( archive, entry) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_write_add_filter_compress(archive): try: libarchive.calls.archive_write.c_archive_write_add_filter_compress( archive) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_read_disk_set_standard_lookup(archive): try: libarchive.calls.archive_write.c_archive_read_disk_set_standard_lookup( archive) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_write_disk_set_options(archive, flags): try: libarchive.calls.archive_write.c_archive_write_disk_set_options( archive, flags) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _create(opener, format_code, files, filter_code=None, block_size=16384): """Create an archive from a collection of files (not recursive).""" a = _archive_write_new() _set_write_context(a, format_code, filter_code) _logger.debug("Opening archive (create).") opener(a) # Use the standard uid/gid lookup mechanisms. # This was set on an instance of *disk* that wasn't used. Do we still need it? #_archive_read_disk_set_standard_lookup(disk) for filepath in files: disk = libarchive.calls.archive_read.c_archive_read_disk_new() libarchive.calls.archive_read.c_archive_read_disk_open(disk, filepath) while 1: entry = libarchive.calls.archive_entry.c_archive_entry_new() r = libarchive.calls.archive_read.c_archive_read_next_header2( disk, entry) if r == libarchive.constants.archive.ARCHIVE_EOF: break elif r != libarchive.constants.archive.ARCHIVE_OK: message = c_archive_error_string(disk) raise libarchive.exception.ArchiveError( "Could not build header from physical source file " "during create: (%d) [%s]" % (r, message)) wrapped = libarchive.adapters.archive_entry.ArchiveEntry( disk, entry) # Strip leading slash so it stores as a relative path. if os.path.isabs(wrapped.pathname) is True: wrapped.pathname = wrapped.pathname[1:] yield wrapped libarchive.calls.archive_read.c_archive_read_disk_descend(disk) r = _archive_write_header(a, entry) with open(wrapped.sourcepath, 'rb') as f: while 1: data = f.read(block_size) if not data: break _archive_write_data(a, data) libarchive.calls.archive_entry.c_archive_entry_free(entry) libarchive.calls.archive_read.c_archive_read_close(disk) libarchive.calls.archive_read.c_archive_read_free(disk) _logger.debug("Closing archive (create).") _archive_write_close(a) _archive_write_free(a)
def _archive_write_data(archive, data): n = libarchive.calls.archive_write.c_archive_write_data( archive, ctypes.cast(ctypes.c_char_p(data), ctypes.c_void_p), len(data)) if n == 0: message = c_archive_error_string(archive) raise ValueError("No bytes were written. Error? [%s]" % (message))
def _archive_write_open_memory(archive, buffer, counter): try: libarchive.calls.archive_write.c_archive_write_open_memory( archive, ctypes.cast(ctypes.c_char_p(buffer), ctypes.c_void_p), len(buffer), ctypes.byref(counter)) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_read_disk_descend(archive): result = libarchive.calls.archive_read.c_archive_read_disk_descend( archive) if result not in (libarchive.constants.archive.ARCHIVE_OK, libarchive.constants.archive.ARCHIVE_WARN): message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_write_set_options(archive, options): try: options = bytes(options, 'utf-8') return libarchive.calls.archive_write.c_archive_write_set_options( archive, options) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_read_add_passphrase(archive, passphrase): try: passphrase = bytes(passphrase, 'utf-8') return libarchive.calls.archive_read.c_archive_read_add_passphrase( archive, passphrase) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_write_open_fd(archive, stream=sys.stdout): fp = stream.fileno() try: return libarchive.calls.archive_write.c_archive_write_open_fd(archive, fp) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_write_open_filename(archive, filepath): filepath = filepath.encode(_ASCII_ENCODING) try: libarchive.calls.archive_write.c_archive_write_open_filename( archive, filepath) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_write_open_fd(archive, stream=sys.stdout): fp = stream.fileno() try: return libarchive.calls.archive_write.c_archive_write_open_fd( archive, fp) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_write_set_passphrase(archive, passphrase): try: if sys.version_info >= (3, 0): passphrase = bytes(passphrase, 'utf-8') else: passphrase = unicode(passphrase).encode('utf-8') return libarchive.calls.archive_write.c_archive_write_set_passphrase( archive, passphrase) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_write_data(archive, data): """Write data to archive. This will only be called with a non-empty string. """ n = libarchive.calls.archive_write.c_archive_write_data( archive, ctypes.cast(ctypes.c_char_p(data), ctypes.c_void_p), len(data)) if n == 0: message = c_archive_error_string(archive) raise ValueError("No bytes were written. Error? [%s]" % (message))
def _archive_write_set_options(archive, options): try: if sys.version_info >= (3, 0): options = bytes(options, 'utf-8') else: options = unicode(options).encode('utf-8') return libarchive.calls.archive_write.c_archive_write_set_options( archive, options) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_read_next_header2(archive, entry): r = libarchive.calls.archive_read.c_archive_read_next_header2( archive, entry) if r not in (libarchive.constants.archive.ARCHIVE_OK, libarchive.constants.archive.ARCHIVE_EOF): message = c_archive_error_string(archive) raise ValueError("Archive iteration (read_next_header2) returned " "error: (%d) [%s]" % (r, message)) return r
def _archive_read_next_header(archive): entry = ctypes.c_void_p() r = libarchive.calls.archive_read.c_archive_read_next_header( archive, ctypes.byref(entry)) if r == libarchive.constants.archive.ARCHIVE_OK: yield entry elif r == libarchive.constants.archive.ARCHIVE_EOF: yield None else: message = c_archive_error_string(archive) raise ValueError("Archive iteration (read_next_header) returned " "error: (%d) [%s]" % (r, message))
def _archive_read_data(archive, block_size=8192): buffer_ = ctypes.create_string_buffer(block_size) while 1: num = libarchive.calls.archive_read.c_archive_read_data( archive, buffer_.raw, len(buffer_)) if num == 0: break elif num < 0: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message) yield buffer_.value[0:num.value]
def _pour(opener, flags=0, *args, **kwargs): """A flexible pouring facility that knows how to enumerate entry data.""" with _enumerator(opener, *args, entry_cls=_ArchiveEntryItState, **kwargs) as r: ext = libarchive.calls.archive_write.c_archive_write_disk_new() libarchive.calls.archive_write.c_archive_write_disk_set_options( ext, flags ) for state in r: yield state if state.selected is False: continue r = libarchive.calls.archive_write.c_archive_write_header( ext, state.entry_res) buff = ctypes.c_void_p() size = ctypes.c_size_t() offset = ctypes.c_longlong() while 1: r = libarchive.calls.archive_read.\ c_archive_read_data_block( state.reader_res, ctypes.byref(buff), ctypes.byref(size), ctypes.byref(offset)) if r == libarchive.constants.archive.ARCHIVE_EOF: break elif r != libarchive.constants.archive.ARCHIVE_OK: message = c_archive_error_string(state.reader_res) raise libarchive.exception.ArchiveError( "Pour failed: (%d) [%s]" % (r, message)) r = libarchive.calls.archive_write.c_archive_write_data_block( ext, buff, size, offset) r = libarchive.calls.archive_write.\ c_archive_write_finish_entry(ext)
def _pour(opener, flags=0, *args, **kwargs): """A flexible pouring facility that knows how to enumerate entry data.""" with _enumerator(opener, *args, entry_cls=_ArchiveEntryItState, **kwargs) as r: ext = libarchive.calls.archive_write.c_archive_write_disk_new() libarchive.calls.archive_write.c_archive_write_disk_set_options( ext, flags) for state in r: yield state if state.selected is False: continue r = libarchive.calls.archive_write.c_archive_write_header( ext, state.entry_res) buff = ctypes.c_void_p() size = ctypes.c_size_t() offset = ctypes.c_longlong() while 1: r = libarchive.calls.archive_read.\ c_archive_read_data_block( state.reader_res, ctypes.byref(buff), ctypes.byref(size), ctypes.byref(offset)) if r == libarchive.constants.archive.ARCHIVE_EOF: break elif r != libarchive.constants.archive.ARCHIVE_OK: message = c_archive_error_string(state.reader_res) raise libarchive.exception.ArchiveError( "Pour failed: (%d) [%s]" % (r, message)) r = libarchive.calls.archive_write.c_archive_write_data_block( ext, buff, size, offset) r = libarchive.calls.archive_write.\ c_archive_write_finish_entry(ext)
def _archive_read_data_skip(archive): try: return libarchive.calls.archive_read.c_archive_read_data_skip(archive) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _archive_write_free(archive): try: libarchive.calls.archive_write.c_archive_write_free(archive) except: message = c_archive_error_string(archive) raise libarchive.exception.ArchiveError(message)
def _create(opener, format_code, files, passphrase=None, options="zip:encryption=zipcrypt", filter_code=None, block_size=16384): """Create an archive from a collection of files (not recursive).""" a = _archive_write_new() _set_write_context(a, format_code, filter_code) if passphrase is not None and \ format_code == libarchive.constants.ARCHIVE_FORMAT_ZIP: r = _archive_write_set_options(a, options) r = _archive_write_set_passphrase(a, passphrase) _LOGGER.debug("Opening archive (create).") opener(a) # Use the standard uid/gid lookup mechanisms. # This was set on an instance of *disk* that wasn't used. Do we still need it? #_archive_read_disk_set_standard_lookup(disk) # We used to yield this, but that necessitated users always flattening the # response. This means we don't have to, but we still have to return an # enumerable in order to maintain compatibility. added = [] for filepath in files: filepath = filepath.encode('utf-8') disk = libarchive.calls.archive_read.c_archive_read_disk_new() libarchive.calls.archive_read.c_archive_read_disk_open(disk, filepath) while 1: entry = libarchive.calls.archive_entry.c_archive_entry_new() r = libarchive.calls.archive_read.c_archive_read_next_header2( disk, entry) if r == libarchive.constants.archive.ARCHIVE_EOF: break elif r != libarchive.constants.archive.ARCHIVE_OK: message = c_archive_error_string(disk) raise libarchive.exception.ArchiveError( "Could not build header from physical source file " "during create: (%d) [%s]" % (r, message)) ae = libarchive.adapters.archive_entry.ArchiveEntry(disk, entry) # print("WRITING: [{}] {}".format(ae, ae.filetype)) # Strip leading slash so it stores as a relative path. if os.path.isabs(ae.pathname) is True: ae.pathname = ae.pathname[1:] added.append(ae) libarchive.calls.archive_read.c_archive_read_disk_descend(disk) # NOTE: There's a `archive_entry_set_size()` on the underlying # entry type, but it doesn't appear to be necessary. The sizes # report perfectly fine with the [probably automatic] counting that # occurs just with `_archive_write_data()`. r = _archive_write_header(a, entry) if ae.filetype.IFLNK is True and os.path.islink( ae.sourcepath) is True: target_path = os.readlink(ae.sourcepath) ae.symlink_targetpath = target_path else: with open(ae.sourcepath, 'rb') as f: while 1: data = f.read(block_size) if not data: break _archive_write_data(a, data) libarchive.calls.archive_entry.c_archive_entry_free(entry) libarchive.calls.archive_read.c_archive_read_close(disk) libarchive.calls.archive_read.c_archive_read_free(disk) _LOGGER.debug("Closing archive (create).") _archive_write_close(a) _archive_write_free(a) return added
def _create(opener, format_code, files, filter_code=None, block_size=16384): """Create an archive from a collection of files (not recursive).""" a = _archive_write_new() _set_write_context(a, format_code, filter_code) _logger.debug("Opening archive (create).") opener(a) # Use the standard uid/gid lookup mechanisms. # This was set on an instance of *disk* that wasn't used. Do we still need it? #_archive_read_disk_set_standard_lookup(disk) for filepath in files: disk = libarchive.calls.archive_read.c_archive_read_disk_new() libarchive.calls.archive_read.c_archive_read_disk_open( disk, filepath) while 1: entry = libarchive.calls.archive_entry.c_archive_entry_new() r = libarchive.calls.archive_read.c_archive_read_next_header2( disk, entry) if r == libarchive.constants.archive.ARCHIVE_EOF: break elif r != libarchive.constants.archive.ARCHIVE_OK: message = c_archive_error_string(disk) raise libarchive.exception.ArchiveError( "Could not build header from physical source file " "during create: (%d) [%s]" % (r, message)) wrapped = libarchive.adapters.archive_entry.ArchiveEntry( disk, entry) # Strip leading slash so it stores as a relative path. if os.path.isabs(wrapped.pathname) is True: wrapped.pathname = wrapped.pathname[1:] yield wrapped libarchive.calls.archive_read.c_archive_read_disk_descend(disk) r = _archive_write_header(a, entry) with open(wrapped.sourcepath, 'rb') as f: while 1: data = f.read(block_size) if not data: break _archive_write_data(a, data) libarchive.calls.archive_entry.c_archive_entry_free(entry) libarchive.calls.archive_read.c_archive_read_close(disk) libarchive.calls.archive_read.c_archive_read_free(disk) _logger.debug("Closing archive (create).") _archive_write_close(a) _archive_write_free(a)
def _create(opener, format_code, files, filter_code=None, block_size=16384): """Create an archive from a collection of files (not recursive).""" a = _archive_write_new() _set_write_context(a, format_code, filter_code) _LOGGER.debug("Opening archive (create).") opener(a) # Use the standard uid/gid lookup mechanisms. # This was set on an instance of *disk* that wasn't used. Do we still need it? #_archive_read_disk_set_standard_lookup(disk) # We used to yield this, but that necessitated users always flattening the # response. This means we don't have to, but we still have to return an # enumerable in order to maintain compatibility. added = [] for filepath in files: filepath = filepath.encode('utf-8') disk = libarchive.calls.archive_read.c_archive_read_disk_new() libarchive.calls.archive_read.c_archive_read_disk_open( disk, filepath) while 1: entry = libarchive.calls.archive_entry.c_archive_entry_new() r = libarchive.calls.archive_read.c_archive_read_next_header2( disk, entry) if r == libarchive.constants.archive.ARCHIVE_EOF: break elif r != libarchive.constants.archive.ARCHIVE_OK: message = c_archive_error_string(disk) raise libarchive.exception.ArchiveError( "Could not build header from physical source file " "during create: (%d) [%s]" % (r, message)) ae = libarchive.adapters.archive_entry.ArchiveEntry( disk, entry) # print("WRITING: [{}] {}".format(ae, ae.filetype)) # Strip leading slash so it stores as a relative path. if os.path.isabs(ae.pathname) is True: ae.pathname = ae.pathname[1:] added.append(ae) libarchive.calls.archive_read.c_archive_read_disk_descend(disk) # NOTE: There's a `archive_entry_set_size()` on the underlying # entry type, but it doesn't appear to be necessary. The sizes # report perfectly fine with the [probably automatic] counting that # occurs just with `_archive_write_data()`. r = _archive_write_header(a, entry) if ae.filetype.IFLNK is True and os.path.islink(ae.sourcepath) is True: target_path = os.readlink(ae.sourcepath) ae.symlink_targetpath = target_path else: with open(ae.sourcepath, 'rb') as f: while 1: data = f.read(block_size) if not data: break _archive_write_data(a, data) libarchive.calls.archive_entry.c_archive_entry_free(entry) libarchive.calls.archive_read.c_archive_read_close(disk) libarchive.calls.archive_read.c_archive_read_free(disk) _LOGGER.debug("Closing archive (create).") _archive_write_close(a) _archive_write_free(a) return added