2 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
4 # SPDX-License-Identifier: BSD-3-Clause
6 """Makes sure that all files contain proper licensing information."""
16 print("""Usage: python checklicenses.py [--root <root>] [tocheck]
17 --root Specifies the repository root. This defaults to ".." relative
18 to the script file. This will be correct given the normal location
19 of the script in "<root>/tools".
21 --ignore-suppressions Ignores path-specific allowed license. Useful when
22 trying to remove a suppression/allowed entry.
24 --list-allowed Print a list of allowed licenses and exit.
26 tocheck Specifies the directory, relative to root, to check. This defaults
27 to "." so it checks everything.
30 python checklicenses.py
31 python checklicenses.py --root ~/chromium/src third_party""")
37 'BSD (2 clause) GPL (v2 or later)',
41 'ISC GPL (v2 or later)',
43 'LGPL (v2.1 or later)',
46 'Public domain GPL (v2 or later)',
47 'Public domain MIT/X11 (BSD like)',
49 'zlib/libpng GPL (v2 or later)',
53 PATH_SPECIFIC_ALLOWED_LICENSES
= {
54 'wsutil/strnatcmp.c': [
57 'wsutil/strnatcmp.h': [
60 'resources/protocols/dtds': [
63 'resources/protocols/diameter/dictionary.dtd': [
66 'resources/protocols/wimaxasncp/dictionary.dtd': [
72 'doc/custom_layer_chm.xsl': [
75 'doc/custom_layer_single_html.xsl': [
93 # Generated header files by lex/lemon/whatever
94 'epan/dtd_grammar.h': [
97 'epan/dfilter/grammar.h': [
100 'epan/dfilter/grammar.c': [
103 'epan/dissectors/packet-ieee80211-radiotap-iter.': [ # Using ISC license only
106 # Mentions BSD-3-clause twice due to embedding of code:
107 'epan/dissectors/packet-communityid.c': [
108 'BSD (3 clause) BSD (3 clause)',
110 'plugins/mate/mate_grammar.h': [
116 # Special IDL license that appears to be compatible as far as I (not a
117 # lawyer) can tell. See
118 # https://lists.wireshark.org/archives/wireshark-dev/201310/msg00234.html
119 'epan/dissectors/pidl/idl_types.h': [
122 # The following tools are under incompatible licenses (mostly GPLv3 or
123 # GPLv3+), but this is OK since they are not actually linked into Wireshark
130 'tools/licensecheck.pl': [
136 'wsutil/safe-math.h': [ # Public domain (CC0)
141 def check_licenses(options
, args
):
142 if options
.list_allowed
:
143 print('\n'.join(ALLOWED_LICENSES
))
146 # Figure out which directory we have to check.
148 # No directory to check specified, use the repository root.
149 start_dir
= options
.base_directory
151 # Directory specified. Start here. It's supposed to be relative to the
153 start_dir
= os
.path
.abspath(os
.path
.join(options
.base_directory
, args
[0]))
155 # More than one argument, we don't handle this.
159 print("Using base directory: %s" % options
.base_directory
)
160 print("Checking: %s" % start_dir
)
163 licensecheck_path
= os
.path
.abspath(os
.path
.join(options
.base_directory
,
167 licensecheck
= subprocess
.Popen([licensecheck_path
,
170 stdout
=subprocess
.PIPE
,
171 stderr
=subprocess
.PIPE
)
172 stdout
, stderr
= licensecheck
.communicate()
173 stdout
= stdout
.decode('utf-8')
174 stderr
= stderr
.decode('utf-8')
176 print('----------- licensecheck stdout -----------')
178 print('--------- end licensecheck stdout ---------')
179 if licensecheck
.returncode
!= 0 or stderr
:
180 print('----------- licensecheck stderr -----------')
182 print('--------- end licensecheck stderr ---------')
188 for line
in stdout
.splitlines():
189 filename
, license
= line
.split(':', 1)
190 filename
= os
.path
.relpath(filename
.strip(), options
.base_directory
)
192 # All files in the build output directory are generated one way or another.
193 # There's no need to check them.
194 if os
.path
.dirname(filename
).startswith('build'):
197 # For now we're just interested in the license.
198 license
= license
.replace('*No copyright*', '').strip()
200 # Skip generated files.
201 if 'GENERATED FILE' in license
:
204 # Support files which provide a choice between licenses.
205 if any(item
in ALLOWED_LICENSES
for item
in license
.split(';')):
208 if not options
.ignore_suppressions
:
209 found_path_specific
= False
210 for prefix
in PATH_SPECIFIC_ALLOWED_LICENSES
:
211 if (filename
.startswith(prefix
) and
212 license
in PATH_SPECIFIC_ALLOWED_LICENSES
[prefix
]):
213 found_path_specific
= True
215 if found_path_specific
:
218 reason
= "License '%s' for '%s' is not allowed." % (license
, filename
)
232 default_root
= os
.path
.abspath(
233 os
.path
.join(os
.path
.dirname(__file__
), '..'))
234 option_parser
= optparse
.OptionParser()
235 option_parser
.add_option('--root', default
=default_root
,
236 dest
='base_directory',
237 help='Specifies the repository root. This defaults '
238 'to "../.." relative to the script file, which '
239 'will normally be the repository root.')
240 option_parser
.add_option('-v', '--verbose', action
='store_true',
241 default
=False, help='Print debug logging')
242 option_parser
.add_option('--list-allowed',
245 help='Print a list of allowed licenses and exit.')
246 option_parser
.add_option('--ignore-suppressions',
249 help='Ignore path-specific allowed license.')
250 options
, args
= option_parser
.parse_args()
251 return check_licenses(options
, args
)
254 if '__main__' == __name__
: