checkIncludes.py 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #!/usr/bin/python3
  2. # Copyright 2018 The Tor Project, Inc. See LICENSE file for licensing info.
  3. import fnmatch
  4. import os
  5. import re
  6. import sys
  7. trouble = False
  8. def err(msg):
  9. global trouble
  10. trouble = True
  11. print(msg, file=sys.stderr)
  12. def fname_is_c(fname):
  13. return fname.endswith(".h") or fname.endswith(".c")
  14. INCLUDE_PATTERN = re.compile(r'\s*#\s*include\s+"([^"]*)"')
  15. RULES_FNAME = ".may_include"
  16. class Rules(object):
  17. def __init__(self):
  18. self.patterns = []
  19. def addPattern(self, pattern):
  20. self.patterns.append(pattern)
  21. def includeOk(self, path):
  22. for pattern in self.patterns:
  23. if fnmatch.fnmatchcase(path, pattern):
  24. return True
  25. return False
  26. def applyToLines(self, lines, context=""):
  27. lineno = 0
  28. for line in lines:
  29. lineno += 1
  30. m = INCLUDE_PATTERN.match(line)
  31. if m:
  32. include = m.group(1)
  33. if not self.includeOk(include):
  34. err("Forbidden include of {} on line {}{}".format(
  35. include, lineno, context))
  36. def applyToFile(self, fname):
  37. with open(fname, 'r') as f:
  38. #print(fname)
  39. self.applyToLines(iter(f), " of {}".format(fname))
  40. def load_include_rules(fname):
  41. result = Rules()
  42. with open(fname, 'r') as f:
  43. for line in f:
  44. line = line.strip()
  45. if line.startswith("#") or not line:
  46. continue
  47. result.addPattern(line)
  48. return result
  49. for dirpath, dirnames, fnames in os.walk("src"):
  50. if ".may_include" in fnames:
  51. rules = load_include_rules(os.path.join(dirpath, RULES_FNAME))
  52. for fname in fnames:
  53. if fname_is_c(fname):
  54. rules.applyToFile(os.path.join(dirpath,fname))
  55. if trouble:
  56. err(
  57. """To change which includes are allowed in a C file, edit the {} files in its
  58. enclosing directory.""".format(RULES_FNAME))
  59. sys.exit(1)