1#![allow(dead_code)]
7
8use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
9
10pub use zerocopy::byteorder::big_endian::{U32 as BE32, U64 as BE64};
11
12#[derive(Debug, Copy, Clone, IntoBytes, KnownLayout, FromBytes, Immutable)]
13#[repr(C, packed)]
14pub struct Header {
15 pub magic: BE32,
16 pub version: BE32,
17 pub backing_file_offset: BE64,
18 pub backing_file_size: BE32,
19 pub cluster_bits: BE32,
20 pub size: BE64,
21 pub crypt_method: BE32,
22 pub l1_size: BE32,
23 pub l1_table_offset: BE64,
24 pub refcount_table_offset: BE64,
25 pub nb_snapshots: BE32,
26 pub snapshots_offset: BE64,
27 pub incompatible_features: BE64,
28 pub compatible_features: BE64,
29 pub autoclear_features: BE64,
30 pub refcount_order: BE32,
31 pub header_length: BE32,
32}
33
34pub const QCOW_EXT_END: u32 = 0x00000000;
36pub const QCOW_EXT_BACKING_FILE_FORMAT_NAME: u32 = 0xE2792AC;
37pub const QCOW_EXT_FEATURE_NAME_TABLE: u32 = 0x6803f857;
38pub const QCOW_EXT_BITMAPS: u32 = 0x23852875;
39
40pub const QCOW_CRYPT_NONE: u32 = 0;
41pub const QCOW_CRYPT_AES: u32 = 1;
42
43#[derive(Debug, Copy, Clone, IntoBytes, KnownLayout, FromBytes, Immutable)]
44#[repr(C, packed)]
45pub struct ExtensionHeader {
46 pub extension_type: BE32,
47 pub extension_size: BE32,
48}
49
50#[derive(Default, Debug, Copy, Clone, IntoBytes, KnownLayout, FromBytes, Immutable)]
51#[repr(C, packed)]
52pub struct L1Entry(pub BE64);
53
54const fn lut_entry_to_offset(entry: u64) -> Option<u64> {
55 const QCOW_LUT_OFFSET_MASK: u64 = 0xfffffffffffe00;
56 let offset = entry & QCOW_LUT_OFFSET_MASK;
57 if offset == 0 {
58 return None;
59 }
60 Some(offset)
61}
62
63impl L1Entry {
64 pub fn offset(&self) -> Option<u64> {
65 lut_entry_to_offset(self.0.get())
66 }
67}
68
69#[derive(Default, Debug, Copy, Clone, IntoBytes, KnownLayout, FromBytes, Immutable)]
70#[repr(C, packed)]
71pub struct L2Entry(pub BE64);
72
73impl L2Entry {
74 pub fn compressed(&self) -> bool {
75 const QCOW_L2_COMPRESSED: u64 = 1 << 62;
76 self.0.get() & QCOW_L2_COMPRESSED != 0
77 }
78
79 pub fn offset(&self) -> Option<u64> {
80 lut_entry_to_offset(self.0.get())
81 }
82}