sq epan/dissectors/pidl/rcg/rcg.cnf
[wireshark-sm.git] / tools / checklicenses.py
blob090bf6df9de16991a53c87f8f9b176dc5e5e6b4f
1 #!/usr/bin/env python3
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."""
9 import optparse
10 import os.path
11 import subprocess
12 import sys
15 def PrintUsage():
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.
29 Examples:
30 python checklicenses.py
31 python checklicenses.py --root ~/chromium/src third_party""")
34 ALLOWED_LICENSES = [
35 'BSD (1 clause)',
36 'BSD (2 clause)',
37 'BSD (2 clause) GPL (v2 or later)',
38 'BSD (3 clause)',
39 'GPL (v2 or later)',
40 'ISC',
41 'ISC GPL (v2 or later)',
42 'LGPL (v2 or later)',
43 'LGPL (v2.1 or later)',
44 'MIT/X11 (BSD like)',
45 'Public domain',
46 'Public domain GPL (v2 or later)',
47 'Public domain MIT/X11 (BSD like)',
48 'zlib/libpng',
49 'zlib/libpng GPL (v2 or later)',
53 PATH_SPECIFIC_ALLOWED_LICENSES = {
54 'wsutil/strnatcmp.c': [
55 'Zlib',
57 'wsutil/strnatcmp.h': [
58 'Zlib',
60 'resources/protocols/dtds': [
61 'UNKNOWN',
63 'resources/protocols/diameter/dictionary.dtd': [
64 'UNKNOWN',
66 'resources/protocols/wimaxasncp/dictionary.dtd': [
67 'UNKNOWN',
69 'doc/': [
70 'UNKNOWN',
72 'doc/custom_layer_chm.xsl': [
73 'UNKNOWN',
75 'doc/custom_layer_single_html.xsl': [
76 'UNKNOWN',
78 'fix': [
79 'UNKNOWN',
81 'wsutil/g711.c': [
82 'UNKNOWN',
84 'packaging/macosx': [
85 'UNKNOWN',
87 'epan/except.c': [
88 'UNKNOWN',
90 'epan/except.h': [
91 'UNKNOWN',
93 # Generated header files by lex/lemon/whatever
94 'epan/dtd_grammar.h': [
95 'UNKNOWN',
97 'epan/dfilter/grammar.h': [
98 'UNKNOWN',
100 'epan/dfilter/grammar.c': [
101 'UNKNOWN',
103 'epan/dissectors/packet-ieee80211-radiotap-iter.': [ # Using ISC license only
104 'ISC GPL (v2)'
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': [
111 'UNKNOWN',
113 'vcs_version.h': [
114 'UNKNOWN',
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': [
120 'UNKNOWN',
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
124 'tools/pidl': [
125 'UNKNOWN',
127 'tools/lemon': [
128 'UNKNOWN',
130 'tools/licensecheck.pl': [
131 'GPL (v2)'
133 '.gitlab/': [
134 'UNKNOWN',
136 'wsutil/safe-math.h': [ # Public domain (CC0)
137 'UNKNOWN',
141 def check_licenses(options, args):
142 if options.list_allowed:
143 print('\n'.join(ALLOWED_LICENSES))
144 sys.exit(0)
146 # Figure out which directory we have to check.
147 if len(args) == 0:
148 # No directory to check specified, use the repository root.
149 start_dir = options.base_directory
150 elif len(args) == 1:
151 # Directory specified. Start here. It's supposed to be relative to the
152 # base directory.
153 start_dir = os.path.abspath(os.path.join(options.base_directory, args[0]))
154 else:
155 # More than one argument, we don't handle this.
156 PrintUsage()
157 return 1
159 print("Using base directory: %s" % options.base_directory)
160 print("Checking: %s" % start_dir)
161 print("")
163 licensecheck_path = os.path.abspath(os.path.join(options.base_directory,
164 'tools',
165 'licensecheck.pl'))
167 licensecheck = subprocess.Popen([licensecheck_path,
168 '-l', '160',
169 '-r', start_dir],
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')
175 if options.verbose:
176 print('----------- licensecheck stdout -----------')
177 print(stdout)
178 print('--------- end licensecheck stdout ---------')
179 if licensecheck.returncode != 0 or stderr:
180 print('----------- licensecheck stderr -----------')
181 print(stderr)
182 print('--------- end licensecheck stderr ---------')
183 print("\nFAILED\n")
184 return 1
186 success = True
187 exit_status = 0
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'):
195 continue
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:
202 continue
204 # Support files which provide a choice between licenses.
205 if any(item in ALLOWED_LICENSES for item in license.split(';')):
206 continue
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
214 break
215 if found_path_specific:
216 continue
218 reason = "License '%s' for '%s' is not allowed." % (license, filename)
219 success = False
220 print(reason)
221 exit_status = 1
223 if success:
224 print("\nSUCCESS\n")
225 return 0
226 else:
227 print("\nFAILED\n")
228 return exit_status
231 def main():
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',
243 action='store_true',
244 default=False,
245 help='Print a list of allowed licenses and exit.')
246 option_parser.add_option('--ignore-suppressions',
247 action='store_true',
248 default=False,
249 help='Ignore path-specific allowed license.')
250 options, args = option_parser.parse_args()
251 return check_licenses(options, args)
254 if '__main__' == __name__:
255 sys.exit(main())