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)',
39 'BSD (4 clause (University of California-Specific))',
42 'ISC GPL (v2 or later)',
44 'LGPL (v2.1 or later)',
47 'Public domain GPL (v2 or later)',
48 'Public domain MIT/X11 (BSD like)',
50 'zlib/libpng GPL (v2 or later)',
54 PATH_SPECIFIC_ALLOWED_LICENSES
= {
55 'wsutil/strnatcmp.c': [
58 'wsutil/strnatcmp.h': [
61 'resources/protocols/dtds': [
64 'resources/protocols/diameter/dictionary.dtd': [
67 'resources/protocols/wimaxasncp/dictionary.dtd': [
73 'doc/custom_layer_chm.xsl': [
76 'doc/custom_layer_single_html.xsl': [
94 # Generated header files by lex/lemon/whatever
95 'epan/dtd_grammar.h': [
98 'epan/dfilter/grammar.h': [
101 'epan/dfilter/grammar.c': [
104 'epan/dissectors/packet-ieee80211-radiotap-iter.': [ # Using ISC license only
107 # Mentions BSD-3-clause twice due to embedding of code:
108 'epan/dissectors/packet-communityid.c': [
109 'BSD (3 clause) BSD (3 clause)',
111 'plugins/mate/mate_grammar.h': [
117 # Special IDL license that appears to be compatible as far as I (not a
118 # lawyer) can tell. See
119 # https://lists.wireshark.org/archives/wireshark-dev/201310/msg00234.html
120 'epan/dissectors/pidl/idl_types.h': [
123 # The following tools are under incompatible licenses (mostly GPLv3 or
124 # GPLv3+), but this is OK since they are not actually linked into Wireshark
131 'tools/licensecheck.pl': [
143 'wsutil/safe-math.h': [ # Public domain (CC0)
148 def check_licenses(options
, args
):
149 if options
.list_allowed
:
150 print('\n'.join(ALLOWED_LICENSES
))
153 # Figure out which directory we have to check.
155 # No directory to check specified, use the repository root.
156 start_dir
= options
.base_directory
158 # Directory specified. Start here. It's supposed to be relative to the
160 start_dir
= os
.path
.abspath(os
.path
.join(options
.base_directory
, args
[0]))
162 # More than one argument, we don't handle this.
166 print("Using base directory: %s" % options
.base_directory
)
167 print("Checking: %s" % start_dir
)
170 licensecheck_path
= os
.path
.abspath(os
.path
.join(options
.base_directory
,
174 licensecheck
= subprocess
.Popen([licensecheck_path
,
177 stdout
=subprocess
.PIPE
,
178 stderr
=subprocess
.PIPE
)
179 stdout
, stderr
= licensecheck
.communicate()
180 stdout
= stdout
.decode('utf-8')
181 stderr
= stderr
.decode('utf-8')
183 print('----------- licensecheck stdout -----------')
185 print('--------- end licensecheck stdout ---------')
186 if licensecheck
.returncode
!= 0 or stderr
:
187 print('----------- licensecheck stderr -----------')
189 print('--------- end licensecheck stderr ---------')
195 for line
in stdout
.splitlines():
196 filename
, license
= line
.split(':', 1)
197 filename
= os
.path
.relpath(filename
.strip(), options
.base_directory
)
199 # All files in the build output directory are generated one way or another.
200 # There's no need to check them.
201 if os
.path
.dirname(filename
).startswith('build'):
204 # For now we're just interested in the license.
205 license
= license
.replace('*No copyright*', '').strip()
207 # Skip generated files.
208 if 'GENERATED FILE' in license
:
211 # Support files which provide a choice between licenses.
212 if any(item
in ALLOWED_LICENSES
for item
in license
.split(';')):
215 if not options
.ignore_suppressions
:
216 found_path_specific
= False
217 for prefix
in PATH_SPECIFIC_ALLOWED_LICENSES
:
218 if (filename
.startswith(prefix
) and
219 license
in PATH_SPECIFIC_ALLOWED_LICENSES
[prefix
]):
220 found_path_specific
= True
222 if found_path_specific
:
225 reason
= "License '%s' for '%s' is not allowed." % (license
, filename
)
239 default_root
= os
.path
.abspath(
240 os
.path
.join(os
.path
.dirname(__file__
), '..'))
241 option_parser
= optparse
.OptionParser()
242 option_parser
.add_option('--root', default
=default_root
,
243 dest
='base_directory',
244 help='Specifies the repository root. This defaults '
245 'to "../.." relative to the script file, which '
246 'will normally be the repository root.')
247 option_parser
.add_option('-v', '--verbose', action
='store_true',
248 default
=False, help='Print debug logging')
249 option_parser
.add_option('--list-allowed',
252 help='Print a list of allowed licenses and exit.')
253 option_parser
.add_option('--ignore-suppressions',
256 help='Ignore path-specific allowed license.')
257 options
, args
= option_parser
.parse_args()
258 return check_licenses(options
, args
)
261 if '__main__' == __name__
: