///|
struct Superblock {
version : Int32
offset_width : Int32
size_width : Int32
base : Int32
eof : Int32
root : Int32
}
///|
fn read_superblock(data : Bytes, limits : Limits) -> Superblock raise H5Error {
limits.validate()
if data.length() > limits.max_file_bytes {
raise Limit("input file size")
}
let magic = b"\x89HDF\r\n\x1a\n"
let mut at = 0
while true {
if at <= data.length() - 8 && data[at:at + 8].to_owned() == magic {
break
}
if at == 0 {
at = 512
} else {
if at > data.length() / 2 {
raise Invalid("HDF5 signature not found", 0)
}
at *= 2
}
if at > data.length() - 8 {
raise Invalid("HDF5 signature not found", 0)
}
}
let c = cursor(data, at, data.length() - at)
c.signature(magic)
let version = c.u8()
let (offset_width, size_width, base, eof, root) = match version {
0 | 1 => {
if c.u8() != 0 || c.u8() != 0 || c.u8() != 0 || c.u8() != 0 {
raise Unsupported("legacy superblock versions", at)
}
let ow = c.u8()
let sw = c.u8()
if c.u8() != 0 {
raise Invalid("reserved superblock field", c.pos - 1)
}
c.skip(4)
let flags = c.index(4)
if flags != 0 {
raise Unsupported("file consistency flags", at)
}
if version == 1 {
c.skip(4)
}
let base = c.index(ow)
let free = c.address(ow, base)
let eof = c.index(ow)
let driver = c.address(ow, base)
if free != None || driver != None {
raise Unsupported("external file driver/free space", at)
}
ignore(c.uint(sw))
let root = c.address(ow, base).unwrap_or(-1)
(ow, sw, base, eof, root)
}
2 | 3 => {
let ow = c.u8()
let sw = c.u8()
let flags = c.u8()
if flags != 0 {
raise Unsupported("file open for write or SWMR", at)
}
let base = c.index(ow)
let extension = c.address(ow, base)
let eof = c.index(ow)
let root = c.address(ow, base).unwrap_or(-1)
if extension != None {
raise Unsupported("superblock extension", at)
}
c.skip(4)
verify_checksum(data, at, c.pos - at)
(ow, sw, base, eof, root)
}
_ => raise Unsupported("superblock version", at)
}
if offset_width != 2 && offset_width != 4 && offset_width != 8 {
raise Unsupported("offset width", at)
}
if size_width != 2 && size_width != 4 && size_width != 8 {
raise Unsupported("length width", at)
}
if base != at {
raise Unsupported("relocated base address", at)
}
if eof > data.length() || eof <= root || root < base {
raise Invalid("file/root bounds", at)
}
{ version, offset_width, size_width, base, eof, root, }
}
///|
fn write_superblock(root : Int32, eof : Int32) -> Bytes {
let b = buffer()
b.bytes(b"\x89HDF\r\n\x1a\n")
b.u8(2)
b.u8(8)
b.u8(8)
b.u8(0)
b.uint(0UL, 8)
b.uint(0xffffffffffffffffUL, 8)
b.uint(eof.to_uint64(), 8)
b.uint(root.to_uint64(), 8)
b.uint(metadata_checksum(b.finish()).to_uint64(), 4)
b.finish()
}
///|
test "superblock checksum and declared EOF are enforced" {
let b = buffer()
b.bytes(write_superblock(48, 49))
b.u8(0)
let sb = read_superblock(b.finish(), Limits::default())
assert_eq(sb.root, 48)
assert_eq(sb.version, 2)
assert_eq(sb.eof, 49)
let broken = b.finish().to_array()
broken[16] = 1
assert_true(
try {
ignore(read_superblock(Bytes::from_array(broken), Limits::default()))
false
} catch {
_ => true
},
)
}