#!/usr/bin/env python3 import json import os import sys import gzip from concurrent.futures import ThreadPoolExecutor, as_completed backup_dir = "/mnt2/backed-up-drive/backupstore/volumes/2c/df/pvc-5c1f48e3-346f-4c35-8e6a-8fc0c4c3a842" output_img = "/mnt/nextcloud-restored.img" backup_cfg = f"{backup_dir}/backups/backup_backup-eac0221d1cab4a9c.cfg" blocks_dir = f"{backup_dir}/blocks" with open(backup_cfg) as f: data = json.load(f) blocks = data['Blocks'] total = len(blocks) size = int(data['Size']) print(f"Volume size: {size // 1024 // 1024 // 1024} GB") print(f"Block count: {total}") os.makedirs(os.path.dirname(output_img) if os.path.dirname(output_img) else '.', exist_ok=True) if not os.path.exists(output_img): import subprocess subprocess.run(['truncate', '-s', str(size), output_img], check=True) with open(output_img, 'r+b') as img: for i, block in enumerate(blocks): offset = block['Offset'] checksum = block['BlockChecksum'] block_path = f"{blocks_dir}/{checksum[:2]}/{checksum[2:4]}/{checksum}.blk" if os.path.exists(block_path): with gzip.open(block_path, 'rb') as bf: img.seek(offset) img.write(bf.read()) if (i + 1) % 500 == 0: percent = (i + 1) * 100 // total bar = '=' * (percent // 2) + ' ' * (50 - percent // 2) sys.stdout.write(f"\r[{bar}] {percent}% ({i + 1}/{total})") sys.stdout.flush() print(f"\nDone! Image: {output_img}")