Commit | Line | Data |
---|---|---|
10ba5f69 OD |
1 | # SPDX-License-Identifier: GPL-2.0-only |
2 | # | |
3 | # Copyright (C) 2023 EfficiOS Inc. | |
4 | # | |
5 | # pyright: strict, reportTypeCommentUsage=false | |
6 | ||
7 | import os | |
8 | import string | |
9 | import argparse | |
10 | ||
11 | import normand | |
12 | import moultipart | |
13 | ||
14 | ||
15 | def _make_ctf_1_metadata(payload_fc: str): | |
16 | payload_fc = payload_fc.strip() | |
17 | ||
18 | if "@" in payload_fc: | |
19 | payload_fc = payload_fc.replace("@", "root") | |
20 | else: | |
21 | payload_fc += " root" | |
22 | ||
23 | return string.Template( | |
24 | """\ | |
25 | /* CTF 1.8 */ | |
26 | ||
27 | trace { | |
28 | major = 1; | |
29 | minor = 8; | |
30 | byte_order = le; | |
31 | }; | |
32 | ||
33 | typealias integer { size = 8; } := u8; | |
34 | typealias integer { size = 16; } := u16; | |
35 | typealias integer { size = 32; } := u32; | |
36 | typealias integer { size = 64; } := u64; | |
37 | typealias integer { size = 8; byte_order = le; } := u8le; | |
38 | typealias integer { size = 16; byte_order = le; } := u16le; | |
39 | typealias integer { size = 32; byte_order = le; } := u32le; | |
40 | typealias integer { size = 64; byte_order = le; } := u64le; | |
41 | typealias integer { size = 8; byte_order = be; } := u8be; | |
42 | typealias integer { size = 16; byte_order = be; } := u16be; | |
43 | typealias integer { size = 32; byte_order = be; } := u32be; | |
44 | typealias integer { size = 64; byte_order = be; } := u64be; | |
45 | typealias integer { signed = true; size = 8; } := i8; | |
46 | typealias integer { signed = true; size = 16; } := i16; | |
47 | typealias integer { signed = true; size = 32; } := i32; | |
48 | typealias integer { signed = true; size = 64; } := i64; | |
49 | typealias integer { signed = true; size = 8; byte_order = le; } := i8le; | |
50 | typealias integer { signed = true; size = 16; byte_order = le; } := i16le; | |
51 | typealias integer { signed = true; size = 32; byte_order = le; } := i32le; | |
52 | typealias integer { signed = true; size = 64; byte_order = le; } := i64le; | |
53 | typealias integer { signed = true; size = 8; byte_order = be; } := i8be; | |
54 | typealias integer { signed = true; size = 16; byte_order = be; } := i16be; | |
55 | typealias integer { signed = true; size = 32; byte_order = be; } := i32be; | |
56 | typealias integer { signed = true; size = 64; byte_order = be; } := i64be; | |
57 | typealias floating_point { exp_dig = 8; mant_dig = 24; } := flt32; | |
58 | typealias floating_point { exp_dig = 11; mant_dig = 53; } := flt64; | |
59 | typealias floating_point { exp_dig = 8; mant_dig = 24; byte_order = le; } := flt32le; | |
60 | typealias floating_point { exp_dig = 11; mant_dig = 53; byte_order = le; } := flt64le; | |
61 | typealias floating_point { exp_dig = 8; mant_dig = 24; byte_order = be; } := flt32be; | |
62 | typealias floating_point { exp_dig = 11; mant_dig = 53; byte_order = be; } := flt64be; | |
63 | typealias string { encoding = UTF8; } := nt_str; | |
64 | ||
65 | event { | |
66 | name = the_event; | |
67 | fields := struct { | |
68 | ${payload_fc}; | |
69 | }; | |
70 | }; | |
71 | """ | |
72 | ).substitute(payload_fc=payload_fc) | |
73 | ||
74 | ||
75 | def _make_ctf_1_data(normand_text: str): | |
76 | # Default to little-endian because that's also the TSDL default in | |
77 | # _make_ctf_1_metadata() above. | |
78 | return normand.parse("!le\n" + normand_text).data | |
79 | ||
80 | ||
81 | def _create_files_from_mp(mp_path: str, output_dir: str): | |
82 | trace_dir = os.path.join(output_dir, "trace") | |
83 | expect_path = os.path.join(output_dir, "expect") | |
84 | metadata_path = os.path.join(trace_dir, "metadata") | |
85 | data_path = os.path.join(trace_dir, "data") | |
86 | os.makedirs(trace_dir, exist_ok=True) | |
87 | ||
88 | with open(mp_path, "r") as f: | |
89 | parts = moultipart.parse(f) | |
90 | ||
91 | with open(metadata_path, "w") as f: | |
92 | f.write(_make_ctf_1_metadata(parts[0].content)) | |
93 | ||
94 | with open(data_path, "wb") as f: | |
95 | f.write(_make_ctf_1_data(parts[1].content)) | |
96 | ||
97 | with open(expect_path, "w") as f: | |
98 | f.write(parts[2].content) | |
99 | ||
100 | ||
101 | if __name__ == "__main__": | |
102 | parser = argparse.ArgumentParser() | |
103 | parser.add_argument( | |
104 | "mp_path", metavar="MP-PATH", help="moultipart document to process" | |
105 | ) | |
106 | parser.add_argument( | |
107 | "output_dir", | |
108 | metavar="OUTPUT-DIR", | |
109 | help="output directory for the CTF trace and expectation file", | |
110 | ) | |
111 | args = parser.parse_args() | |
112 | _create_files_from_mp(args.mp_path, args.output_dir) |