xref: /aosp_15_r20/external/cronet/third_party/icu/scripts/icuhash.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1#!/usr/bin/python3
2
3# Copyright 2022 The Chromium Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7import hashlib
8import itertools
9import sys
10
11PAGE_SIZE = 0x1000  # System page size.
12HASH_SIZE = 8       # Size of the hash in bytes.
13
14
15def hash_pages(data):
16    out = bytearray()
17
18    offset = 0
19    while offset < len(data):
20        # Extract a page and pad it with zeroes in case it's not a full page.
21        # This is to emulate the behavior of mmap in Linux (and thus ChromeOS)
22        # environments.
23        #
24        #     "POSIX specifies that the system shall always zero fill any
25        #      partial page at the end of the object [...]".
26        #
27        # Reference: https://man7.org/linux/man-pages/man2/mmap.2.html
28        page = bytearray(data[offset : offset + PAGE_SIZE])
29        page.extend(itertools.repeat(0x00, PAGE_SIZE - len(page)))
30
31        # Calculate the hash of the page.
32        digest = hashlib.blake2b(page, digest_size=HASH_SIZE).digest()
33        out.extend(digest)
34
35        offset += PAGE_SIZE
36
37    return out
38
39
40if __name__ == "__main__":
41    # Check arguments.
42    if len(sys.argv) != 3:
43        error_str = "icuhash: wrong number of arguments\n\n"
44        help_str = "usage: icuhash <infilename> <outfilename>\n\n"
45        sys.exit(error_str + help_str)
46
47    # Extract arguments.
48    in_filename = sys.argv[1]
49    out_filename = sys.argv[2]
50
51    # Read the input file.
52    with open(in_filename, "rb") as in_file:
53        data = in_file.read()
54        # Calculate hashes for each page of the file.
55        out_data = hash_pages(data)
56        # Write the output file.
57        with open(out_filename, "wb") as out_file:
58            out_file.write(out_data)
59