alexk / rpms / rpm

Forked from rpms/rpm 2 years ago
Clone
629b27
From c705a6287f8c7fb5e37dad0ac87257731a41fa69 Mon Sep 17 00:00:00 2001
629b27
From: chantra <chantr4@gmail.com>
629b27
Date: Sat, 29 Jan 2022 07:00:27 +0000
629b27
Subject: [PATCH 08/30] [rpm2extents] Add script to troubleshoot transcoded
629b27
 file content This script is essentially dumping the metadata written at the
629b27
 end of the transcoded files, it will also be used as part of the end-to-end
629b27
 tests.
629b27
629b27
---
629b27
 scripts/rpm2extents_dump | 94 ++++++++++++++++++++++++++++++++++++++++
629b27
 1 file changed, 94 insertions(+)
629b27
 create mode 100755 scripts/rpm2extents_dump
629b27
629b27
diff --git a/scripts/rpm2extents_dump b/scripts/rpm2extents_dump
629b27
new file mode 100755
629b27
index 000000000..596a59a49
629b27
--- /dev/null
629b27
+++ b/scripts/rpm2extents_dump
629b27
@@ -0,0 +1,94 @@
629b27
+#!/usr/bin/env python3
629b27
+
629b27
+import argparse
629b27
+import binascii
629b27
+import os
629b27
+import struct
629b27
+import sys
629b27
+
629b27
+MAGIC_SIZE = 8
629b27
+MAGIC_STR = b'KWTSH100'
629b27
+
629b27
+POS_SIZE = 8
629b27
+
629b27
+def keep_position(func):
629b27
+    def wrapper(*args, **kwargs):
629b27
+        curr = args[0].tell()
629b27
+        res = func(*args, **kwargs)
629b27
+        f.seek(curr, os.SEEK_SET)
629b27
+        return res
629b27
+    return wrapper
629b27
+
629b27
+def read_validation_digest(f, validation_offset):
629b27
+	digests = []
629b27
+    # validation
629b27
+	f.seek(validation_offset, os.SEEK_SET)
629b27
+	val_content_len, val_digests_num = struct.unpack('=QI', f.read(8+4))
629b27
+	for i in range(val_digests_num):
629b27
+		algo_name_len, digest_len = struct.unpack('=II', f.read(8))
629b27
+		algo_name, digest = struct.unpack(f'{algo_name_len}s{digest_len}s', f.read(algo_name_len+digest_len))
629b27
+		digests.append((algo_name, binascii.hexlify(digest)))
629b27
+	return digests
629b27
+
629b27
+
629b27
+def read_digests_table(f, digest_offset):
629b27
+	digests = []
629b27
+    # validation
629b27
+	f.seek(digest_offset, os.SEEK_SET)
629b27
+	table_len, digest_len = struct.unpack('=II', f.read(8))
629b27
+
629b27
+	for i in range(table_len):
629b27
+		digest, pos = struct.unpack(f'{digest_len}sQ', f.read(digest_len + 8))
629b27
+		digests.append((pos, binascii.hexlify(digest)))
629b27
+	return digests
629b27
+
629b27
+def read_signature_output(f, signature_offset):
629b27
+    f.seek(signature_offset, os.SEEK_SET)
629b27
+    signature_rc, signature_output_len = struct.unpack('=IQ', f.read(12))
629b27
+    return signature_rc, f.read(signature_output_len)
629b27
+
629b27
+@keep_position
629b27
+def parse_file(f):
629b27
+	digests = []
629b27
+	pos_table_offset = f.seek(-8 - 3*POS_SIZE, os.SEEK_END)
629b27
+	signature_offset, digest_offset, validation_offset = struct.unpack('=QQQ', f.read(3*POS_SIZE))
629b27
+
629b27
+	validation_digests = read_validation_digest(f, validation_offset)
629b27
+	digests_table = read_digests_table(f, digest_offset)
629b27
+	signature_ouput = read_signature_output(f, signature_offset)
629b27
+
629b27
+	return validation_digests, digests_table, signature_ouput
629b27
+
629b27
+@keep_position
629b27
+def is_transcoded(f):
629b27
+    f.seek(-MAGIC_SIZE, os.SEEK_END)
629b27
+    magic = f.read(MAGIC_SIZE)
629b27
+    return magic == MAGIC_STR
629b27
+
629b27
+def arg_parse():
629b27
+    parser = argparse.ArgumentParser()
629b27
+    parser.add_argument('--dump-signature', action='store_true')
629b27
+    parser.add_argument('--dump-file-digest-table', action='store_true')
629b27
+    parser.add_argument('--dump-digests', action='store_true')
629b27
+    parser.add_argument('file')
629b27
+
629b27
+    return parser.parse_args()
629b27
+
629b27
+if __name__ == '__main__':
629b27
+    args = arg_parse()
629b27
+    f = open(args.file, 'rb')
629b27
+    if not is_transcoded(f):
629b27
+        sys.exit(1)
629b27
+
629b27
+    validation_digests, digests_table, signature_output = parse_file(f)
629b27
+    if(args.dump_file_digest_table):
629b27
+        for digest in digests_table:
629b27
+            print(f"FileDigest {hex(digest[0])}: {digest[1]}")
629b27
+
629b27
+    if(args.dump_digests):
629b27
+        for validation_digest in validation_digests:
629b27
+            print(f"HeaderDigest {validation_digest[0]} {validation_digest[1]}")
629b27
+
629b27
+    if(args.dump_signature):
629b27
+        print(f"RPMSignOutput RC {signature_output[0]}\nRPMSignOutput Content {signature_output[1].decode()}")
629b27
+
629b27
-- 
629b27
2.35.1
629b27