def _sparse_copy(src_path, dst_path, virtual_size, block_size=4096):
    start_time = last_log_time = timeutils.utcnow()
    EMPTY_BLOCK = '\0' * block_size
    bytes_read = 0
    skipped_bytes = 0
    left = virtual_size

    LOG.debug("Starting sparse_copy src=%(src_path)s dst=%(dst_path)s "
              "virtual_size=%(virtual_size)d block_size=%(block_size)d",
              {'src_path': src_path, 'dst_path': dst_path,
               'virtual_size': virtual_size, 'block_size': block_size})

    # NOTE(sirp): we need read/write access to the devices; since we don't have
    # the luxury of shelling out to a sudo'd command, we temporarily take
    # ownership of the devices.
    with utils.temporary_chown(src_path):
        with utils.temporary_chown(dst_path):
            with open(src_path, "r") as src:
                with open(dst_path, "w") as dst:
                    data = src.read(min(block_size, left))
                    while data:
                        if data == EMPTY_BLOCK:
                            dst.seek(block_size, os.SEEK_CUR)
                            left -= block_size
                            bytes_read += block_size
                            skipped_bytes += block_size
                        else:
                            dst.write(data)
                            data_len = len(data)
                            left -= data_len
                            bytes_read += data_len

                        if left <= 0:
                            break

                        data = src.read(min(block_size, left))
                        greenthread.sleep(0)
                        last_log_time = _log_progress_if_required(
                            left, last_log_time, virtual_size)

    duration = timeutils.delta_seconds(start_time, timeutils.utcnow())
    compression_pct = float(skipped_bytes) / bytes_read * 100

    LOG.debug("Finished sparse_copy in %(duration).2f secs, "
              "%(compression_pct).2f%% reduction in size",
              {'duration': duration, 'compression_pct': compression_pct})
Copy data, skipping long runs of zeros to create a sparse file.
dataset/ETHPy150Open BU-NU-CLOUD-SP16/Trusted-Platform-Module-nova/nova/virt/xenapi/vm_utils.py/_sparse_copy