@@ -25,6 +25,79 @@ def assert_file(path, what):
2525 sys .exit (os .EX_NOINPUT )
2626
2727
28+ def assert_valid_codesign_config (framework_dir , zip_contents , entitlements , without_entitlements ):
29+ """Exits with exit code 1 if the codesign configuration contents are incorrect.
30+ All Mach-O binaries found within zip_contents exactly must be listed in
31+ either entitlements or without_entitlements."""
32+ if _contains_duplicates (entitlements ):
33+ log_error ('ERROR: duplicate value(s) found in entitlements.txt' )
34+ sys .exit (os .EX_DATAERR )
35+
36+ if _contains_duplicates (without_entitlements ):
37+ log_error ('ERROR: duplicate value(s) found in without_entitlements.txt' )
38+ sys .exit (os .EX_DATAERR )
39+
40+ if _contains_duplicates (entitlements + without_entitlements ):
41+ log_error ('ERROR: value(s) found in both entitlements and without_entitlements.txt' )
42+ sys .exit (os .EX_DATAERR )
43+
44+ binaries = set ()
45+ for zip_content_path in zip_contents :
46+ # If file, check if Mach-O binary.
47+ if _is_macho_binary (os .path .join (framework_dir , zip_content_path )):
48+ binaries .add (zip_content_path )
49+ # If directory, check transitive closure of files for Mach-O binaries.
50+ for root , _ , files in os .walk (os .path .join (framework_dir , zip_content_path )):
51+ for file in [os .path .join (root , f ) for f in files ]:
52+ if _is_macho_binary (file ):
53+ binaries .add (os .path .relpath (file , framework_dir ))
54+
55+ # Verify that all Mach-O binaries are listed in either entitlements or without_entitlements.
56+ listed_binaries = set (entitlements + without_entitlements )
57+ if listed_binaries != binaries :
58+ log_error (
59+ 'ERROR: binaries listed in entitlements.txt and without_entitlements.txt do not '
60+ 'match the set of binaries in the files to be zipped'
61+ )
62+ log_error ('Binaries found in files to be zipped:' )
63+ for file in sorted (binaries ):
64+ log_error (' ' + file )
65+
66+ not_listed = sorted (binaries - listed_binaries )
67+ if not_listed :
68+ log_error ('Binaries NOT LISTED in entitlements.txt/without_entitlements.txt:' )
69+ for file in not_listed :
70+ log_error (' ' + file )
71+
72+ not_found = sorted (listed_binaries - binaries )
73+ if not_found :
74+ log_error ('Binaries listed in entitlements.txt/without_entitlements.txt but NOT FOUND:' )
75+ for file in not_found :
76+ log_error (' ' + file )
77+ sys .exit (os .EX_NOINPUT )
78+
79+
80+ def _contains_duplicates (strings ):
81+ """Returns true if the list of strings contains a duplicate value."""
82+ return len (strings ) != len (set (strings ))
83+
84+
85+ def _is_macho_binary (filename ):
86+ """Returns True if the specified path is file and a Mach-O binary."""
87+ if not os .path .isfile (filename ):
88+ return False
89+
90+ with open (filename , 'rb' ) as file :
91+ chunk = file .read (4 )
92+ return chunk in (
93+ b'\xca \xfe \xba \xbe ' , # Mach-O Universal Big Endian
94+ b'\xce \xfa \xed \xfe ' , # Mach-O Little Endian (32-bit)
95+ b'\xcf \xfa \xed \xfe ' , # Mach-O Little Endian (64-bit)
96+ b'\xfe \xed \xfa \xce ' , # Mach-O Big Endian (32-bit)
97+ b'\xfe \xed \xfa \xcf ' , # Mach-O Big Endian (64-bit)
98+ )
99+
100+
28101def buildroot_relative_path (path ):
29102 """Returns the absolute path to the specified buildroot-relative path."""
30103 buildroot_dir = os .path .abspath (os .path .join (os .path .realpath (__file__ ), '..' , '..' , '..' , '..' ))
0 commit comments