#!/usr/bin/env python3 # SPDX-License-Identifier: GPL-3.0-or-later """Strict parser for the bounded Phase-1.0DQ inventory stream.""" from __future__ import annotations from dataclasses import dataclass import struct MAGIC=b"CHI10DQ1";FRAME=struct.Struct("<8sIIiiIIQ24s");ENTRY=struct.Struct("<256sIIIIQQq24s") HEADER=1;TERMINAL=2;ERROR=3;MAX_ENTRIES=256;MAX_WIRE=64+MAX_ENTRIES*320+64 class ProtocolError(ValueError):pass @dataclass(frozen=True) class InventoryEntry:name:str;file_type:int;mode:int;size:int;inode:int;mtime:int def _frame(raw:bytes): if len(raw)!=FRAME.size:raise ProtocolError("frame size") value=FRAME.unpack(raw) if value[0]!=MAGIC or value[1]!=1 or value[8]!=bytes(24):raise ProtocolError("frame identity") return value def parse_stream(raw:bytes)->tuple[InventoryEntry,...]: if not isinstance(raw,bytes) or not 128<=len(raw)<=MAX_WIRE or (len(raw)-128)%ENTRY.size:raise ProtocolError("stream length") first=_frame(raw[:64]);kind,status,saved,count,reserved,transferred=first[2:8] if kind==ERROR:raise ProtocolError(f"target error {status}:{saved}") if kind!=HEADER or status or saved or count or reserved or transferred:raise ProtocolError("header invalid") entries=[] for offset in range(64,len(raw)-64,ENTRY.size): name_raw,name_length,file_type,mode,reserved,size,inode,mtime,padding=ENTRY.unpack(raw[offset:offset+ENTRY.size]) if not 0