|
|
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 |
|