1#!/usr/bin/python 2# Simple udev rules syntax checker 3# 4# (C) 2010 Canonical Ltd. 5# Author: Martin Pitt <martin.pitt@ubuntu.com> 6# 7# This program is free software; you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation; either version 2 of the License, or 10# (at your option) any later version. 11# 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License along 18# with this program; if not, write to the Free Software Foundation, Inc., 19# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 21import re 22import sys 23 24if len(sys.argv) < 2: 25 print >> sys.stderr, 'Usage: %s <rules file> [...]' % sys.argv[0] 26 sys.exit(2) 27 28no_args_tests = re.compile('(ACTION|DEVPATH|KERNELS?|NAME|SYMLINK|SUBSYSTEMS?|DRIVERS?|TAG|RESULT|TEST)\s*(?:=|!)=\s*"([^"]*)"$') 29args_tests = re.compile('(ATTRS?|ENV|TEST){([a-zA-Z0-9/_.*%-]+)}\s*(?:=|!)=\s*"([^"]*)"$') 30no_args_assign = re.compile('(NAME|SYMLINK|OWNER|GROUP|MODE|TAG|PROGRAM|RUN|LABEL|GOTO|WAIT_FOR|OPTIONS|IMPORT)\s*(?:\+=|:=|=)\s*"([^"]*)"$') 31args_assign = re.compile('(ATTR|ENV|IMPORT|RUN){([][a-zA-Z0-9/_.*%-]+)}\s*(=|==|\+=)\s*"([^"]*)"$') 32 33result = 0 34buffer = '' 35for path in sys.argv[1:]: 36 lineno = 0 37 for line in open(path): 38 lineno += 1 39 40 # handle line continuation 41 if line.endswith('\\\n'): 42 buffer += line[:-2] 43 continue 44 else: 45 line = buffer + line 46 buffer = '' 47 48 # filter out comments and empty lines 49 line = line.strip() 50 if not line or line.startswith('#'): 51 continue 52 53 for clause in line.split(','): 54 clause = clause.strip() 55 if not (no_args_tests.match(clause) or args_tests.match(clause) or 56 no_args_assign.match(clause) or args_assign.match(clause)): 57 58 print('Invalid line %s:%i: %s' % (path, lineno, line)) 59 print(' clause:', clause) 60 print() 61 result = 1 62 break 63 64sys.exit(result) 65