Add _find_bin_for_hash() helper to repository_tool

Add a helper function to determine the name of a bin that a hashed
targetfile will be delegated to.

Based sketches by Lukas Puehringer in issues #994 & #995

Signed-off-by: Joshua Lock <jlock@vmware.com>
This commit is contained in:
Joshua Lock 2020-03-20 12:10:45 +00:00
parent eb01374c3b
commit 40d1dcfa6c
2 changed files with 56 additions and 1 deletions

View file

@ -1301,7 +1301,7 @@ def check_prefixes_match_range():
prefixes = delegated_role['path_hash_prefixes']
if len(prefixes) > 1:
prefix_range = "{}-{}".format(prefixes[0], prefixes[1])
prefix_range = "{}-{}".format(prefixes[0], prefixes[-1])
else:
prefix_range = prefixes[0]

View file

@ -2824,6 +2824,61 @@ def _get_hash(target_filepath):
def _create_bin_name(low, high, prefix_len):
"""
<Purpose>
Create a string name of a delegated hash bin, where name will be a range of
zero-padded (up to prefix_len) strings i.e. for low=00, high=07,
prefix_len=3 the returned name would be '000-007'.
"""
if low == high:
return "{low:0{len}x}".format(low=low, len=prefix_len)
return "{low:0{len}x}-{high:0{len}x}".format(low=low, high=high,
len=prefix_len)
def _find_bin_for_hash(path_hash, number_of_bins):
"""
<Purpose>
For a given hashed filename, path_hash, calculate the name of a hashed bin
into which this file would be delegated given number_of_bins bins are in
use.
<Arguments>
path_hash:
The hash of the target file's path
number_of_bins:
The number of hashed_bins in use
<Returns>
The name of the hashed bin path_hash would be binned into.
"""
prefix_len = len("{:x}".format(number_of_bins - 1))
prefix_count = 16 ** prefix_len
if prefix_count % number_of_bins != 0:
# Note: doesn't guarantee a power of two for any x and y, but does work
# due to the relationship between nuber_of_bins and prefix_count
raise securesystemslib.exceptions.Error('The "number_of_bins" argument'
' must be a power of 2.')
bin_size = prefix_count // number_of_bins
prefix = int(path_hash[:prefix_len], 16)
low = prefix - (prefix % bin_size)
high = (low + bin_size - 1)
return _create_bin_name(low, high, prefix_len)
def create_new_repository(repository_directory, repository_name='default'):