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