2017-05-01 03:26:56 +03:00
#!/usr/bin/env python3
2017-11-18 19:32:46 +03:00
# SPDX-License-Identifier: LGPL-2.1+
#
2010-09-21 14:45:52 +04:00
# Simple udev rules syntax checker
#
# (C) 2010 Canonical Ltd.
# Author: Martin Pitt <martin.pitt@ubuntu.com>
#
2013-08-15 00:55:40 +04:00
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
2010-09-21 14:45:52 +04:00
# (at your option) any later version.
2013-08-15 00:55:40 +04:00
# systemd is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
2010-09-21 14:45:52 +04:00
#
2013-08-15 00:55:40 +04:00
# You should have received a copy of the GNU Lesser General Public License
# along with systemd; If not, see <http://www.gnu.org/licenses/>.
2010-09-21 14:45:52 +04:00
import re
import sys
2015-01-20 22:50:35 +03:00
import os
from glob import glob
2010-09-21 14:45:52 +04:00
2017-11-22 14:42:28 +03:00
rules_files = sys . argv [ 1 : ]
if not rules_files :
sys . exit ( ' Specify files to test as arguments ' )
2010-09-21 14:45:52 +04:00
2016-12-02 02:29:54 +03:00
no_args_tests = re . compile ( r ' (ACTION|DEVPATH|KERNELS?|NAME|SYMLINK|SUBSYSTEMS?|DRIVERS?|TAG|RESULT|TEST) \ s*(?:=|!)= \ s* " ([^ " ]*) " $ ' )
args_tests = re . compile ( r ' (ATTRS?|ENV|TEST) { ([a-zA-Z0-9/_.* % -]+)} \ s*(?:=|!)= \ s* " ([^ " ]*) " $ ' )
no_args_assign = re . compile ( r ' (NAME|SYMLINK|OWNER|GROUP|MODE|TAG|PROGRAM|RUN|LABEL|GOTO|OPTIONS|IMPORT) \ s*(?: \ +=|:=|=) \ s* " ([^ " ]*) " $ ' )
args_assign = re . compile ( r ' (ATTR|ENV|IMPORT|RUN) { ([a-zA-Z0-9/_.* % -]+)} \ s*(=| \ +=) \ s* " ([^ " ]*) " $ ' )
2010-09-21 14:45:52 +04:00
result = 0
buffer = ' '
2015-01-20 22:50:35 +03:00
for path in rules_files :
2017-11-22 14:29:46 +03:00
print ( ' # looking at {} ' . format ( path ) )
2010-09-21 14:45:52 +04:00
lineno = 0
for line in open ( path ) :
lineno + = 1
# handle line continuation
if line . endswith ( ' \\ \n ' ) :
buffer + = line [ : - 2 ]
continue
else :
line = buffer + line
buffer = ' '
# filter out comments and empty lines
line = line . strip ( )
if not line or line . startswith ( ' # ' ) :
continue
for clause in line . split ( ' , ' ) :
clause = clause . strip ( )
if not ( no_args_tests . match ( clause ) or args_tests . match ( clause ) or
no_args_assign . match ( clause ) or args_assign . match ( clause ) ) :
2017-11-22 14:29:46 +03:00
print ( ' Invalid line {} : {} : {} ' . format ( path , lineno , line ) )
print ( ' clause: ' , clause )
print ( )
2010-09-21 14:45:52 +04:00
result = 1
break
sys . exit ( result )