Last active
April 25, 2026 09:27
-
-
Save kobuki/48bb83b71f2768b7fea22ce2393b9f23 to your computer and use it in GitHub Desktop.
Create file hierarchy from a Proxmox pmxcfs/pve-cluster SQLite config database
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| # Simple Python 3 script to create a browsable file tree from a Proxmox pmxcfs config.db. | |
| # Can be used for restore tasks or other investigation purposes. | |
| import sqlite3 | |
| import os | |
| import argparse | |
| def create_hierarchy(db_file, output_dir): | |
| # Connect to the SQLite database | |
| conn = sqlite3.connect(db_file) | |
| cursor = conn.cursor() | |
| # Fetch all entries from the table | |
| cursor.execute("SELECT inode, parent, type, name, data, mtime FROM tree") | |
| entries = cursor.fetchall() | |
| # Close the connection | |
| conn.close() | |
| # Dictionary to map inodes to paths | |
| inode_map = {} | |
| os.makedirs(output_dir, exist_ok=True) | |
| # Function to resolve parent directory path recursively | |
| def get_parent_path(parent): | |
| if parent == 0: | |
| return output_dir | |
| if parent not in inode_map: | |
| parent_entry = next((e for e in entries if e[0] == parent), None) | |
| if parent_entry: | |
| inode_map[parent] = os.path.join(get_parent_path(parent_entry[1]), parent_entry[3]) | |
| os.makedirs(inode_map[parent], exist_ok=True) | |
| return inode_map.get(parent, output_dir) | |
| # Process directories first to ensure they exist | |
| for inode, parent, obj_type, name, data, mtime in entries: | |
| if obj_type == 4: # Directory | |
| parent_path = get_parent_path(parent) | |
| dir_path = os.path.join(parent_path, name) | |
| os.makedirs(dir_path, exist_ok=True) | |
| inode_map[inode] = dir_path | |
| os.utime(dir_path, (mtime, mtime)) | |
| # Process files | |
| for inode, parent, obj_type, name, data, mtime in entries: | |
| if obj_type == 8: # File | |
| parent_path = get_parent_path(parent) | |
| file_path = os.path.join(parent_path, name) | |
| with open(file_path, "wb") as f: | |
| f.write(data if data is not None else b"") | |
| os.utime(file_path, (mtime, mtime)) | |
| if __name__ == "__main__": | |
| parser = argparse.ArgumentParser(description="Reconstruct filesystem from SQLite database") | |
| parser.add_argument("db_file", help="Path to the SQLite database file") | |
| parser.add_argument("output_dir", help="Path to the output directory") | |
| args = parser.parse_args() | |
| create_hierarchy(args.db_file, args.output_dir) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment