1 #!/usr/bin/python2.6
   2 #
   3 # CDDL HEADER START
   4 #
   5 # The contents of this file are subject to the terms of the
   6 # Common Development and Distribution License (the "License").
   7 # You may not use this file except in compliance with the License.
   8 #
   9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10 # or http://www.opensolaris.org/os/licensing.
  11 # See the License for the specific language governing permissions
  12 # and limitations under the License.
  13 #
  14 # When distributing Covered Code, include this CDDL HEADER in each
  15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16 # If applicable, add the following below this CDDL HEADER, with the
  17 # fields enclosed by brackets "[]" replaced with your own identifying
  18 # information: Portions Copyright [yyyy] [name of copyright owner]
  19 #
  20 # CDDL HEADER END
  21 #
  22 
  23 #
  24 # Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  25 #
  26 
  27 #
  28 # Check for valid CDDL blocks in source files.
  29 #
  30 
  31 import sys, os, getopt, fnmatch
  32 
  33 sys.path.insert(1, os.path.join(os.path.dirname(__file__), "..", "lib",
  34                                 "python%d.%d" % sys.version_info[:2]))
  35 
  36 # Allow running from the source tree, using the modules in the source tree
  37 sys.path.insert(2, os.path.join(os.path.dirname(__file__), '..'))
  38 
  39 from onbld.Checks.Cddl import cddlchk
  40 
  41 class ExceptionList(object):
  42         def __init__(self):
  43                 self.dirs = []
  44                 self.files = []
  45                 self.extensions = []
  46 
  47         def load(self, exfile):
  48                 fh = None
  49                 try:
  50                         fh = open(exfile, 'r')
  51                 except IOError, e:
  52                         sys.stderr.write('Failed to open exception list: '
  53                                          '%s: %s\n' % (e.filename, e.strerror))
  54                         sys.exit(2)
  55 
  56                 for line in fh:
  57                         line = line.strip()
  58 
  59                         if line.strip().endswith('/'):
  60                                 self.dirs.append(line[0:-1])
  61                         elif line.startswith('*.'):
  62                                 self.extensions.append(line)
  63                         else:
  64                                 self.files.append(line)
  65 
  66                 fh.close()
  67 
  68         def match(self, filename):
  69                 if os.path.isdir(filename):
  70                         return filename in self.dirs
  71                 else:
  72                         if filename in self.files:
  73                                 return True
  74 
  75                         for pat in self.extensions:
  76                                 if fnmatch.fnmatch(filename, pat):
  77                                         return True
  78 
  79         def __contains__(self, elt):
  80                 return self.match(elt)
  81 
  82 def usage():
  83         progname = os.path.split(sys.argv[0])[1]
  84         sys.stderr.write('''Usage: %s [-av] [-x exceptions] paths...
  85         -a              check that all the specified files have a CDDL block.
  86         -v              report on all files, not just those with errors.
  87         -x exceptions   load an exceptions file
  88 ''' % progname)
  89         sys.exit(2)
  90 
  91 
  92 def check(filename, opts):
  93         try:
  94                 fh = open(filename, 'r')
  95         except IOError, e:
  96                 sys.stderr.write("failed to open '%s': %s\n" %
  97                                  (e.filename, e.strerror))
  98                 return 1
  99         else:
 100                 return cddlchk(fh, verbose=opts['verbose'],
 101                                lenient=opts['lenient'],
 102                                output=sys.stdout)
 103 
 104 def walker(opts, dirname, fnames):
 105         for f in fnames:
 106                 path = os.path.join(dirname, f)
 107 
 108                 if not os.path.isdir(path):
 109                         if not path in opts['exclude']:
 110                                 opts['status'] |= check(path, opts)
 111                 else:
 112                         if path in opts['exclude']:
 113                                 fnames.remove(f)
 114 
 115 def walkpath(path, opts):
 116         if os.path.isdir(path):
 117                 os.path.walk(path, walker, opts)
 118         else:
 119                 if not path in opts['exclude']:
 120                         opts['status'] |= check(path, opts)
 121 
 122 def main(args):
 123         options = {
 124                 'status': 0,
 125                 'lenient': True,
 126                 'verbose': False,
 127                 'exclude': ExceptionList()
 128         }
 129 
 130         try:
 131                 opts, args = getopt.getopt(sys.argv[1:], 'avx:')
 132         except getopt.GetoptError:
 133                 usage()
 134                 sys.exit(2)
 135 
 136         for opt, arg in opts:
 137                 if opt == '-a':
 138                         options['lenient'] = False
 139                 elif opt == '-v':
 140                         options['verbose'] = True
 141                 elif opt == '-x':
 142                         options['exclude'].load(arg)
 143 
 144         for path in args:
 145                 walkpath(path, options)
 146 
 147         return options['status']
 148 
 149 if __name__ == '__main__':
 150         sys.exit(main(sys.argv[1:]))