microsandbox_utils/index/types.rs
1//! Wire format types for the layer sidecar index.
2//!
3//! Binary mmap-friendly index generated at OCI layer extraction time and consumed
4//! by OverlayFs at runtime. See `layer-index-format.md` for the full specification.
5//!
6//! All types are `#[repr(C)]` with natural alignment for zero-copy mmap access on
7//! little-endian targets (x86_64, aarch64).
8
9//--------------------------------------------------------------------------------------------------
10// Constants
11//--------------------------------------------------------------------------------------------------
12
13/// Magic bytes: "MSBi" in little-endian.
14pub const INDEX_MAGIC: u32 = 0x6942_534D;
15
16/// Current wire format version.
17pub const INDEX_VERSION: u32 = 1;
18
19/// DirRecord flag: directory is opaque (hides all lower entries).
20pub const DIR_FLAG_OPAQUE: u8 = 0x01;
21
22/// EntryRecord flag: entry is a whiteout (masks a lower entry).
23pub const ENTRY_FLAG_WHITEOUT: u8 = 0x01;
24
25/// Sentinel value for `EntryRecord.dir_record_idx` on non-directory entries.
26pub const DIR_RECORD_IDX_NONE: u32 = 0xFFFF_FFFF;
27
28//--------------------------------------------------------------------------------------------------
29// Types
30//--------------------------------------------------------------------------------------------------
31
32/// Index file header (32 bytes, offset 0).
33#[repr(C)]
34#[derive(Debug, Clone, Copy)]
35pub struct IndexHeader {
36 /// Magic bytes (`INDEX_MAGIC`).
37 pub magic: u32,
38 /// Wire format version (`INDEX_VERSION`).
39 pub version: u32,
40 /// Reserved flags (must be 0).
41 pub flags: u32,
42 /// Number of `DirRecord` entries.
43 pub dir_count: u32,
44 /// Total number of `EntryRecord` entries across all directories.
45 pub entry_count: u32,
46 /// Number of `HardlinkRef` entries.
47 pub hardlink_ref_count: u32,
48 /// Total bytes in the string pool.
49 pub string_pool_size: u32,
50 /// CRC32C of entire file with this field zeroed.
51 pub checksum: u32,
52}
53
54/// A directory in the index (24 bytes). Sorted by path (lexicographic).
55#[repr(C)]
56#[derive(Debug, Clone, Copy)]
57pub struct DirRecord {
58 /// String pool offset for directory path.
59 pub path_off: u32,
60 /// Byte length of path (`""` for root, `"etc"`, `"usr/bin"`).
61 pub path_len: u16,
62 /// Flags (bit 0 = `DIR_FLAG_OPAQUE`).
63 pub flags: u8,
64 /// Padding.
65 pub _pad: u8,
66 /// Index of first child in the entry table.
67 pub first_entry: u32,
68 /// Number of children in this directory.
69 pub entry_count: u32,
70 /// String pool offset for overflow tombstone data (0 = none).
71 pub tombstone_off: u32,
72 /// Number of overflow tombstoned names.
73 pub tombstone_count: u16,
74 /// Padding.
75 pub _pad2: u16,
76}
77
78/// A filesystem entry in the index (40 bytes, 8-byte aligned).
79/// Grouped by parent directory (contiguous), sorted by name within each group.
80#[repr(C)]
81#[derive(Debug, Clone, Copy)]
82pub struct EntryRecord {
83 /// Host inode number (`LowerOriginId.object_id`).
84 pub host_ino: u64,
85 /// File size in bytes.
86 pub size: u64,
87 /// String pool offset for entry name.
88 pub name_off: u32,
89 /// Full stat mode including `S_IFMT` type bits.
90 pub mode: u32,
91 /// Guest-visible uid (from `override_stat` xattr).
92 pub uid: u32,
93 /// Guest-visible gid (from `override_stat` xattr).
94 pub gid: u32,
95 /// Byte length of name.
96 pub name_len: u16,
97 /// Flags (bit 0 = `ENTRY_FLAG_WHITEOUT`).
98 pub flags: u8,
99 /// Padding.
100 pub _pad: u8,
101 /// `DirRecord` index for directory entries; `DIR_RECORD_IDX_NONE` for non-dirs.
102 pub dir_record_idx: u32,
103}
104
105/// A hardlink reference (16 bytes, 8-byte aligned).
106/// Sorted by `host_ino`, then by path. Only entries with nlink > 1 within the layer.
107#[repr(C)]
108#[derive(Debug, Clone, Copy)]
109pub struct HardlinkRef {
110 /// Shared host inode number.
111 pub host_ino: u64,
112 /// String pool offset for full path (e.g. `"usr/bin/tool"`).
113 pub path_off: u32,
114 /// Byte length of path.
115 pub path_len: u32,
116}
117
118// Compile-time size assertions.
119const _: () = assert!(size_of::<IndexHeader>() == 32);
120const _: () = assert!(size_of::<DirRecord>() == 24);
121const _: () = assert!(size_of::<EntryRecord>() == 40);
122const _: () = assert!(size_of::<HardlinkRef>() == 16);