File Formats

Proxmox File Archive Format (.pxar)

digraph g {
graph [
rankdir = "LR"
fontname="Helvetica"
];
node [
fontsize = "16"
shape = "record"
];
edge [
];

"archive" [
label = "archive.pxar"
shape = "record"
];

"rootdir" [
label = "<f0> ENTRY| \{XATTR\}\* extended attribute list\l | \{ACL_USER\}\* USER ACL entries\l | \{ACL_GROUP\}\* GROUP ACL entries\l| \[ACL_GROUP_OBJ\] the ACL_GROUP_OBJ \l| \[ACL_DEFAULT\] the various default ACL fields\l|\{ACL_DEFAULT_USER\}\* USER ACL entries\l|\{ACL_DEFAULT_GROUP\}\* GROUP ACL entries\l|\[FCAPS\] file capability in Linux disk format\l|\[QUOTA_PROJECT_ID\] the ext4/xfs quota project ID\l| { PAYLOAD  | SYMLINK | DEVICE | { <de> \{DirectoryEntries\}\* | GOODBYE}}"
shape = "record"
];


"entry" [
label = "<f0> size: u64 = 64\l|type: u64 = ENTRY\l|feature_flags: u64\l|mode: u64\l|flags: u64\l|uid: u64\l|gid: u64\l|mtime: u64\l"
labeljust = "l"
shape = "record"
];



"direntry" [
label = "<f0> FILENAME |{ENTRY | HARDLINK}"
shape = "record"
];

"archive" -> "rootdir":f0

"rootdir":f0 -> "entry":f0

"rootdir":de -> "direntry":f0

}

Data Blob Format (.blob)

The data blob format is used to store small binary data. The magic number decides the exact format:

[66, 171, 56, 7, 190, 131, 112, 161]

unencrypted

uncompressed

[49, 185, 88, 66, 111, 182, 163, 127]

unencrypted

compressed

[123, 103, 133, 190, 34, 45, 76, 240]

encrypted

uncompressed

[230, 89, 27, 191, 11, 191, 216, 11]

encrypted

compressed

The compression algorithm used is zstd. The encryption cipher is AES_256_GCM.

Unencrypted blobs use the following format:

MAGIC: [u8; 8]

CRC32: [u8; 4]

Data: (max 16MiB)

Encrypted blobs additionally contain a 16 byte initialization vector (IV), followed by a 16 byte authenticated encryption (AE) tag, followed by the encrypted data:

MAGIC: [u8; 8]

CRC32: [u8; 4]

IV: [u8; 16]

TAG: [u8; 16]

Data: (max 16MiB)

Fixed Index Format (.fidx)

All numbers are stored as little-endian.

MAGIC: [u8; 8]

[47, 127, 65, 237, 145, 253, 15, 205]

uuid: [u8; 16],

Unique ID

ctime: i64,

Creation Time (epoch)

index_csum: [u8; 32],

SHA-256 over the index (without header) SHA256(digest1||digest2||...)

size: u64,

Image size

chunk_size: u64,

Chunk size

reserved: [u8; 4016],

Overall header size is one page (4096 bytes)

digest1: [u8; 32]

First chunk digest

digest2: [u8; 32]

Second chunk digest

...

Next chunk digest ...

Dynamic Index Format (.didx)

All numbers are stored as little-endian.

MAGIC: [u8; 8]

[28, 145, 78, 165, 25, 186, 179, 205]

uuid: [u8; 16],

Unique ID

ctime: i64,

Creation Time (epoch)

index_csum: [u8; 32],

SHA-256 over the index (without header) SHA256(offset1||digest1||offset2||digest2||...)

reserved: [u8; 4032],

Overall header size is one page (4096 bytes)

offset1: u64

End of first chunk

digest1: [u8; 32]

First chunk digest

offset2: u64

End of second chunk

digest2: [u8; 32]

Second chunk digest

...

Next chunk offset/digest