Niels suggested to me on IRC to move the test deb from t/debs/ to t/tests/ and split it in two, one for the udev and one for the appstream check. In the process of doing this I discovered bugs in the udev check, so this proved very valuable. Here is a set of updated patches. -- Vennlig hilsen Petter Reinholdtsen
>From 09f0d85756dc7a30d938de0313f12b40e7988496 Mon Sep 17 00:00:00 2001 From: Petter Reinholdtsen <p...@hungry.com> Date: Wed, 26 Oct 2016 12:01:16 +0000 Subject: [PATCH 1/3] Added two new test debs udev-rules and appstream-metadata for AppStream and udev checks.
--- .../appstream-metadata-obsolete.metadata.xml | 2 ++ .../debian/debian/appstream-metadata.desktop | 8 ++++++++ .../debian/debian/appstream-metadata.dirs | 2 ++ .../debian/debian/appstream-metadata.metadata.xml | 22 ++++++++++++++++++++++ .../debian/debian/appstream-metadata.udev | 14 ++++++++++++++ t/tests/appstream-metadata/debian/debian/rules | 14 ++++++++++++++ t/tests/appstream-metadata/desc | 8 ++++++++ t/tests/appstream-metadata/tags | 6 ++++++ t/tests/udev-rules/debian/debian/rules | 13 +++++++++++++ t/tests/udev-rules/debian/debian/udev-rules.dirs | 2 ++ .../debian/debian/udev-rules.metadata.xml | 22 ++++++++++++++++++++++ t/tests/udev-rules/debian/debian/udev-rules.udev | 17 +++++++++++++++++ t/tests/udev-rules/desc | 7 +++++++ t/tests/udev-rules/tags | 4 ++++ 14 files changed, 141 insertions(+) create mode 100644 t/tests/appstream-metadata/debian/debian/appstream-metadata-obsolete.metadata.xml create mode 100644 t/tests/appstream-metadata/debian/debian/appstream-metadata.desktop create mode 100644 t/tests/appstream-metadata/debian/debian/appstream-metadata.dirs create mode 100644 t/tests/appstream-metadata/debian/debian/appstream-metadata.metadata.xml create mode 100644 t/tests/appstream-metadata/debian/debian/appstream-metadata.udev create mode 100644 t/tests/appstream-metadata/debian/debian/rules create mode 100644 t/tests/appstream-metadata/desc create mode 100644 t/tests/appstream-metadata/tags create mode 100644 t/tests/udev-rules/debian/debian/rules create mode 100644 t/tests/udev-rules/debian/debian/udev-rules.dirs create mode 100644 t/tests/udev-rules/debian/debian/udev-rules.metadata.xml create mode 100644 t/tests/udev-rules/debian/debian/udev-rules.udev create mode 100644 t/tests/udev-rules/desc create mode 100644 t/tests/udev-rules/tags diff --git a/t/tests/appstream-metadata/debian/debian/appstream-metadata-obsolete.metadata.xml b/t/tests/appstream-metadata/debian/debian/appstream-metadata-obsolete.metadata.xml new file mode 100644 index 0000000..31d281e --- /dev/null +++ b/t/tests/appstream-metadata/debian/debian/appstream-metadata-obsolete.metadata.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +<application/> diff --git a/t/tests/appstream-metadata/debian/debian/appstream-metadata.desktop b/t/tests/appstream-metadata/debian/debian/appstream-metadata.desktop new file mode 100644 index 0000000..4c91430 --- /dev/null +++ b/t/tests/appstream-metadata/debian/debian/appstream-metadata.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Version=1.0 +Type=Application +Name=appstream-udev-data +Terminal=true +Exec=true +Categories=ConsoleOnly;Game; +Keywords=Text; diff --git a/t/tests/appstream-metadata/debian/debian/appstream-metadata.dirs b/t/tests/appstream-metadata/debian/debian/appstream-metadata.dirs new file mode 100644 index 0000000..402f5d5 --- /dev/null +++ b/t/tests/appstream-metadata/debian/debian/appstream-metadata.dirs @@ -0,0 +1,2 @@ +usr/share/metainfo +usr/share/appdata diff --git a/t/tests/appstream-metadata/debian/debian/appstream-metadata.metadata.xml b/t/tests/appstream-metadata/debian/debian/appstream-metadata.metadata.xml new file mode 100644 index 0000000..82294c1 --- /dev/null +++ b/t/tests/appstream-metadata/debian/debian/appstream-metadata.metadata.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<component> + <id>appstream-udev-data</id> + <metadata_license>MIT</metadata_license> + <name>lintian appstream-udev-data</name> + <summary>Test AppStream and udev related checks in lintian</summary> + <description> + <p> + This is a test package designed to exercise some feature or tag + of Lintian. It is part of the Lintian test suite and may do + very odd things. It should not be installed like a regular + package. It may be an empty package. + </p> + </description> + <provides> + <modalias>usb:v0000p0001d*</modalias> + <modalias>usb:v0000p0002d*</modalias> + <modalias>usb:v0000p0003d*</modalias> + <modalias>usb:v0000p0004d*</modalias> + <modalias>usb:v0000p000ad*</modalias> + </provides> +</component> diff --git a/t/tests/appstream-metadata/debian/debian/appstream-metadata.udev b/t/tests/appstream-metadata/debian/debian/appstream-metadata.udev new file mode 100644 index 0000000..e2f2841 --- /dev/null +++ b/t/tests/appstream-metadata/debian/debian/appstream-metadata.udev @@ -0,0 +1,14 @@ +SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="0000", ATTR{idProduct}=="0001", \ + MODE="0666" + +SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="0000", ATTR{idProduct}=="0002", \ + MODE="0660", GROUP="plugdev" + +SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="0000", ATTR{idProduct}=="0003", \ + TAG+="uaccess" + +SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="0000", ATTR{idProduct}=="0004", \ + MODE="0660", GROUP="plugdev", TAG+="uaccess" + +SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="0000", ATTR{idProduct}=="000a", \ + ID_TEST_DEVICE="1" diff --git a/t/tests/appstream-metadata/debian/debian/rules b/t/tests/appstream-metadata/debian/debian/rules new file mode 100644 index 0000000..5302e21 --- /dev/null +++ b/t/tests/appstream-metadata/debian/debian/rules @@ -0,0 +1,14 @@ +#!/usr/bin/make -f + +DESTDIR = debian/$(shell dh_listpackages) +APPSYNC_DIR=$(DESTDIR)/usr/share/metainfo/ +OBSOLETE_APPSYNC_DIR=$(DESTDIR)/usr/share/appdata/ +UDEV_DIR=$(DESTDIR)/lib/udev/rules.d/ + +%: + dh $@ + +override_dh_install: + dh_install + install -m 0644 debian/appstream-metadata.metadata.xml $(APPSYNC_DIR) + install -m 0644 debian/appstream-metadata-obsolete.metadata.xml $(OBSOLETE_APPSYNC_DIR) diff --git a/t/tests/appstream-metadata/desc b/t/tests/appstream-metadata/desc new file mode 100644 index 0000000..2a424af --- /dev/null +++ b/t/tests/appstream-metadata/desc @@ -0,0 +1,8 @@ +Testname: appstream-metadata +Version: 1.0 +Description: Test AppStream and udev metadata in binary package +Test-For: + appstream-metadata-in-legacy-location + appstream-metadata-legacy-format + appstream-metadata-missing-modalias-provide + appstream-metadata-malformed-modalias-provide diff --git a/t/tests/appstream-metadata/tags b/t/tests/appstream-metadata/tags new file mode 100644 index 0000000..03eeba9 --- /dev/null +++ b/t/tests/appstream-metadata/tags @@ -0,0 +1,6 @@ +E: appstream-metadata: appstream-metadata-legacy-format usr/share/appdata/appstream-metadata-obsolete.metadata.xml +W: appstream-metadata: appstream-metadata-in-legacy-location usr/share/appdata/appstream-metadata-obsolete.metadata.xml +W: appstream-metadata: appstream-metadata-malformed-modalias-provide usr/share/metainfo/appstream-metadata.metadata.xml include non-valid hex digit in USB matching rule 'usb:v0000p000ad*' +W: appstream-metadata: appstream-metadata-missing-modalias-provide lib/udev/rules.d/60-appstream-metadata.rules match rule usb:v0000p000Ad* +W: appstream-metadata: udev-rule-missing-uaccess lib/udev/rules.d/60-appstream-metadata.rules:2 user accessible device missing TAG+="uaccess" +W: appstream-metadata: udev-rule-missing-uaccess lib/udev/rules.d/60-appstream-metadata.rules:5 user accessible device missing TAG+="uaccess" diff --git a/t/tests/udev-rules/debian/debian/rules b/t/tests/udev-rules/debian/debian/rules new file mode 100644 index 0000000..1ecb975 --- /dev/null +++ b/t/tests/udev-rules/debian/debian/rules @@ -0,0 +1,13 @@ +#!/usr/bin/make -f + +DESTDIR = debian/$(shell dh_listpackages) +APPSYNC_DIR=$(DESTDIR)/usr/share/metainfo/ +UDEV_DIR=$(DESTDIR)/lib/udev/rules.d/ + +%: + dh $@ + +override_dh_install: + dh_install + install -m 0644 debian/udev-rules.metadata.xml $(APPSYNC_DIR) + ln -s dangling $(UDEV_DIR)/60-dangling-symlink.rules diff --git a/t/tests/udev-rules/debian/debian/udev-rules.dirs b/t/tests/udev-rules/debian/debian/udev-rules.dirs new file mode 100644 index 0000000..d0cd146 --- /dev/null +++ b/t/tests/udev-rules/debian/debian/udev-rules.dirs @@ -0,0 +1,2 @@ +lib/udev/rules.d +usr/share/metainfo diff --git a/t/tests/udev-rules/debian/debian/udev-rules.metadata.xml b/t/tests/udev-rules/debian/debian/udev-rules.metadata.xml new file mode 100644 index 0000000..2564e98 --- /dev/null +++ b/t/tests/udev-rules/debian/debian/udev-rules.metadata.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<component> + <id>udev-rules</id> + <metadata_license>MIT</metadata_license> + <name>lintian udev-rules test</name> + <summary>Test udev related checks in lintian</summary> + <description> + <p> + This is a test package designed to exercise some feature or tag + of Lintian. It is part of the Lintian test suite and may do + very odd things. It should not be installed like a regular + package. It may be an empty package. + </p> + </description> + <provides> + <modalias>usb:v0000p0001d*</modalias> + <modalias>usb:v0000p0002d*</modalias> + <modalias>usb:v0000p0003d*</modalias> + <modalias>usb:v0000p0004d*</modalias> + <modalias>usb:v0000p000Ad*</modalias> + </provides> +</component> diff --git a/t/tests/udev-rules/debian/debian/udev-rules.udev b/t/tests/udev-rules/debian/debian/udev-rules.udev new file mode 100644 index 0000000..dd3442b --- /dev/null +++ b/t/tests/udev-rules/debian/debian/udev-rules.udev @@ -0,0 +1,17 @@ +SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="0000", ATTR{idProduct}=="0001", \ + MODE="0666" + +SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="0000", ATTR{idProduct}=="0002", \ + MODE="0660", GROUP="plugdev" + +SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="0000", ATTR{idProduct}=="0003", \ + TAG+="uaccess" + +SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="0000", ATTR{idProduct}=="0004", \ + MODE="0660", GROUP="plugdev", TAG+="uaccess" + +ACTION=="add", ATTR{idVendor}=="0000", ATTR{idProduct}=="0005", \ + MODE="0660", GROUP="plugdev", TAG+="uaccess" + +SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="0000", ATTR{idProduct}=="000a", \ + ID_TEST_DEVICE="1" diff --git a/t/tests/udev-rules/desc b/t/tests/udev-rules/desc new file mode 100644 index 0000000..b633996 --- /dev/null +++ b/t/tests/udev-rules/desc @@ -0,0 +1,7 @@ +Testname: udev-rules +Version: 1.0 +Description: Check udev rules for mistakes +Test-For: + udev-rule-unreadable + udev-rule-missing-uaccess + udev-rule-missing-subsystem diff --git a/t/tests/udev-rules/tags b/t/tests/udev-rules/tags new file mode 100644 index 0000000..5798a00 --- /dev/null +++ b/t/tests/udev-rules/tags @@ -0,0 +1,4 @@ +E: udev-rules: udev-rule-unreadable lib/udev/rules.d/60-dangling-symlink.rules +W: udev-rules: udev-rule-missing-subsystem lib/udev/rules.d/60-udev-rules.rules:14 vendor/product matching missing SUBSYSTEM specifier +W: udev-rules: udev-rule-missing-uaccess lib/udev/rules.d/60-udev-rules.rules:2 user accessible device missing TAG+="uaccess" +W: udev-rules: udev-rule-missing-uaccess lib/udev/rules.d/60-udev-rules.rules:5 user accessible device missing TAG+="uaccess" -- 2.9.3
>From eab5a1d25afa7a590fe4f59561c92c6f07851c49 Mon Sep 17 00:00:00 2001 From: Petter Reinholdtsen <p...@hungry.com> Date: Sun, 23 Oct 2016 23:33:22 +0200 Subject: [PATCH 2/3] Added new check for udev rule files. Mostly check USB rules. --- checks/udev.desc | 32 +++++++++++++ checks/udev.pm | 114 +++++++++++++++++++++++++++++++++++++++++++++++ t/scripts/pod-spelling.t | 2 +- 3 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 checks/udev.desc create mode 100644 checks/udev.pm diff --git a/checks/udev.desc b/checks/udev.desc new file mode 100644 index 0000000..7ccfdf8 --- /dev/null +++ b/checks/udev.desc @@ -0,0 +1,32 @@ +Check-Script: udev +Author: Petter Reinholdtsen <p...@hungry.com> +Type: binary +Needs-Info: unpacked +Info: This script checks the udev rules for problems. + +Tag: udev-rule-unreadable +Severity: serious +Certainty: certain +Ref: https://wiki.debian.org/USB/GadgetSetup +Info: The udev rule entry should be a file + The package contain a non-file in /lib/udev/rules.d/. The directory + should only contain readable files. + +Tag: udev-rule-missing-uaccess +Severity: normal +Certainty: possible +Ref: https://wiki.debian.org/USB/GadgetSetup +Info: The package set up a device for user access without using the + uaccess tag. Some udev rules get the same effect using other markers + enabling console user access using rules in + /lib/udev/rules.d/70-uaccess.rules. Others should specify + TAG+="uaccess" in the udev rule. + +Tag: udev-rule-missing-subsystem +Severity: normal +Certainty: possible +Ref: https://wiki.debian.org/USB/GadgetSetup +Info: The package matches vendor/product IDs without specifying + subsystem. The vendor/product IDs are subsystem specific. Matching + rules using those should specify subsystem too, for example by using + SUBSYSTEM=="usb" at the start of the matching rule. diff --git a/checks/udev.pm b/checks/udev.pm new file mode 100644 index 0000000..3aa5e2a --- /dev/null +++ b/checks/udev.pm @@ -0,0 +1,114 @@ +# udev -- lintian check script -*- perl -*- + +# Copyright © 2016 Petter Reinholdtsen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, you can find it on the World Wide +# Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free +# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +# MA 02110-1301, USA. + +package Lintian::udev; + +use strict; +use warnings; + +use Lintian::Tags qw(tag); + +# Check /lib/udev/rules.d/, detect use of MODE="0666" and use of +# GROUP="plugdev" without TAG+="uaccess". + +sub run { + my ($pkg, $type, $info, $proc, $group) = @_; + my $rules_dir = $info->index_resolved_path('lib/udev/rules.d/'); + return unless $rules_dir; + foreach my $file ($rules_dir->children) { + if (! $file->is_open_ok()) { + tag('udev-rule-unreadable', $file); + next; + } + check_udev_rules($file, \&check_rule); + } + return; +} + +sub check_rule { + my ($file, $linenum, $rule) = @_; + + # for USB, if everyone or the plugdev group members are + # allowed access, the uaccess tag should be used too. + if ($rule =~ m/SUBSYSTEM=="usb"/ + && ($rule =~ m/GROUP="plugdev"/ + || $rule =~ m/MODE="0666"/) + && $rule !~ m/ENV\{COLOR_MEASUREMENT_DEVICE\}/ + && $rule !~ m/ENV\{DDC_DEVICE\}/ + && $rule !~ m/ENV\{ID_CDROM\}/ + && $rule !~ m/ENV\{ID_FFADO\}/ + && $rule !~ m/ENV\{ID_GPHOTO2\}/ + && $rule !~ m/ENV\{ID_HPLIP\}/ + && $rule !~ m/ENV\{ID_INPUT_JOYSTICK\}/ + && $rule !~ m/ENV\{ID_MAKER_TOOL\}/ + && $rule !~ m/ENV\{ID_MEDIA_PLAYER\}/ + && $rule !~ m/ENV\{ID_PDA\}/ + && $rule !~ m/ENV\{ID_REMOTE_CONTROL\}/ + && $rule !~ m/ENV\{ID_SECURITY_TOKEN\}/ + && $rule !~ m/ENV\{ID_SMARTCARD_READER\}/ + && $rule !~ m/ENV\{ID_SOFTWARE_RADIO\}/ + && $rule !~ m/TAG\+="uaccess"/) { + tag('udev-rule-missing-uaccess', "$file:$linenum", + 'user accessible device missing TAG+="uaccess"'); + } + + # Matching rules mentioning vendor/product should also specify + # subsystem, as vendor/product is subsystem specific. + if ($rule =~ m/ATTR\{idVendor\}=="[0-9a-fA-F]+"/ + && $rule =~ m/ATTR\{idProduct\}=="[0-9a-fA-F]*"/ + && $rule !~ m/SUBSYSTEM=="[^"]+"/ ) { + tag('udev-rule-missing-subsystem', "$file:$linenum", + 'vendor/product matching missing SUBSYSTEM specifier'); + } + return 0; +} + +sub check_udev_rules { + my ($file, $check) = @_; + + my $fd = $file->open(); + my $linenum = 0; + my $cont; + my $retval = 0; + while (<$fd>) { + chomp; + $linenum++; + if (defined $cont) { + $_ = $cont . $_; + $cont = undef; + } + if (/^(.*)\\$/) { + $cont = $1; + next; + } + next if /^#.*/; # Skip comments + $retval |= $check->($file, $linenum, $_); + } + close($fd); + return $retval; +} + +1; + +# Local Variables: +# indent-tabs-mode: nil +# cperl-indent-level: 4 +# End: +# vim: syntax=perl sw=4 sts=4 sr et diff --git a/t/scripts/pod-spelling.t b/t/scripts/pod-spelling.t index 75787eb..6973488 100755 --- a/t/scripts/pod-spelling.t +++ b/t/scripts/pod-spelling.t @@ -121,7 +121,7 @@ hashrefs namespace subdir SIGPIPE SIG blocknumber blocksub readwindow REMOVESLASH STAMPFILE TAGNAME TCODE TESTDATA BLOCKSIZE jN POSIX t1c2pfb init runtime txt executability writability INHANDLE OUTHANDLES UTC timestamp faux tagname READMEs Testname -debhelper dh buildpackage +debhelper dh buildpackage uaccess udev __END__ -- 2.9.3
>From 3b24ddaf0a6ec0178b3431715696c954eeae8edb Mon Sep 17 00:00:00 2001 From: Petter Reinholdtsen <p...@hungry.com> Date: Sun, 23 Oct 2016 23:41:47 +0200 Subject: [PATCH 3/3] Added checks for AppStream metadata and compare the metadata to udev rules. --- checks/appstream-metadata.desc | 36 +++++++ checks/appstream-metadata.pm | 215 +++++++++++++++++++++++++++++++++++++++++ t/scripts/pod-spelling.t | 2 +- 3 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 checks/appstream-metadata.desc create mode 100644 checks/appstream-metadata.pm diff --git a/checks/appstream-metadata.desc b/checks/appstream-metadata.desc new file mode 100644 index 0000000..3eea7cc --- /dev/null +++ b/checks/appstream-metadata.desc @@ -0,0 +1,36 @@ +Check-Script: appstream-metadata +Author: Petter Reinholdtsen <p...@hungry.com> +Type: binary +Needs-Info: unpacked +Info: This script checks the AppStream metadata files for problems. + +Tag: appstream-metadata-in-legacy-location +Severity: minor +Certainty: certain +Ref: https://wiki.debian.org/AppStream/Guidelines +Info: AppStream metadata file was found in /usr/share/appdata/. The + AppStream XML files should be placed in /usr/share/metadata/. + +Tag: appstream-metadata-legacy-format +Severity: important +Certainty: certain +Ref: https://wiki.debian.org/AppStream/Guidelines +Info: AppStream metadata with obsolete <application> root node found. + The XML root node should be <component>. + +Tag: appstream-metadata-missing-modalias-provide +Severity: normal +Certainty: certain +Ref: https://wiki.debian.org/AppStream/Guidelines +Info: This package contain a udev rule for providing device access to + the console user (using the uaccess udev TAG) or to members of the + plugdev file group without announcing the hardware support using + AppStream. + +Tag: appstream-metadata-malformed-modalias-provide +Severity: normal +Certainty: certain +Ref: https://wiki.debian.org/AppStream/Guidelines +Info: The modalias matching rule in the AppStream metadata file is + malformed. Hexadecimal numbers in vendor and product IDs must be + upper case. diff --git a/checks/appstream-metadata.pm b/checks/appstream-metadata.pm new file mode 100644 index 0000000..af65354 --- /dev/null +++ b/checks/appstream-metadata.pm @@ -0,0 +1,215 @@ +# appstream-metadata -- lintian check script -*- perl -*- + +# Copyright © 2016 Petter Reinholdtsen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, you can find it on the World Wide +# Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free +# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +# MA 02110-1301, USA. + +package Lintian::appstream_metadata; + +# For .desktop files, the lintian check would be really easy: Check if +# .desktop file is there, check if matching file exists in +# /usr/share/metainfo, if not throw a warning. Maybe while we're at it +# also check for legacy locations (stuff in /usr/share/appdata) and +# legacy data (metainfo files starting with `<application>`). +# +# For modaliases, maybe udev rules could give some hints. +# Check modalias values to ensure hex numbers are using capital A-F. + +use strict; +use warnings; + +use XML::Simple qw(:strict); +use File::Basename qw(basename); + +use Lintian::Tags qw(tag); + +sub run { + my ($pkg, $type, $info, $proc, $group) = @_; + + my %desktopfiles; + my %metainfo; + my @udevrules; + my $found_modalias = 0; + my $modaliases = []; + if (defined(my $dir = $info->index_resolved_path('usr/share/applications/'))) { + for my $file ($dir->children('breadth-first')) { + $desktopfiles{$file} = 1 if ($file->is_file); + } + } + if (defined(my $dir = $info->index_resolved_path('usr/share/metainfo/'))) { + for my $file ($dir->children) { + if ($file->is_file) { + $metainfo{$file} = 1; + $found_modalias |= check_modalias($info, $file, $modaliases); + } + } + } + if (defined(my $dir = $info->index_resolved_path('usr/share/appdata/'))) { + for my $file ($dir->children('breadth-first')) { + if ($file->is_file) { + tag('appstream-metadata-in-legacy-location', $file); + $found_modalias |= check_modalias($info, $file, $modaliases); + } + } + } + if (defined(my $dir = $info->index_resolved_path('lib/udev/rules.d/'))) { + for my $file ($dir->children('breadth-first')) { + push(@udevrules, $file) if ($file->is_file); + } + } + + for my $udevrule (@udevrules) { + if (check_udev_rules($udevrule, \&provides_user_device, $modaliases) + && !$found_modalias) { + tag('appstream-metadata-missing-modalias-provide', $udevrule); + } + } + return; +} + +=head1 NAME + +check_modalias + +=head1 DESCRIPTION + +Check if a AppStream XML file contain a provides->modalias block and +check its content. + +=cut +sub check_modalias { + my ($info, $metadatafile, $modaliases) = @_; +# my $metadatafile = $info->index_resolved_path($metadatapath); + if (! $metadatafile->is_open_ok()) { + # FIXME report this as an error + return; + } + my $xml = XMLin($metadatafile->fs_path(), + ForceArray => [ 'provides', 'modalias' ], + KeepRoot => 1, + KeyAttr => [], + ); + if (exists $xml->{'application'}) { + tag('appstream-metadata-legacy-format', $metadatafile); + return 0; + } + if (exists $xml->{'component'} + && exists $xml->{'component'}->{'provides'} + && exists $xml->{'component'}->{'provides'}[0]->{'modalias'}) { + for (@{$xml->{'component'}->{'provides'}[0]->{'modalias'}}) { + push(@{$modaliases}, $_); + if (m/^usb:v[0-9a-f]{4}p[0-9a-f]{4}d/i + && ! m/^usb:v[0-9A-F]{4}p[0-9A-F]{4}d/) { + tag('appstream-metadata-malformed-modalias-provide', + $metadatafile, + "include non-valid hex digit in USB matching rule '$_'" + ); + } + } + return 1; + } + return 0; +} + +=head1 NAME + +provides_user_device + +=head1 DESCRIPTION + +Check if a udev rule file contain rules for plugdev or uaccess. + +=cut +sub provides_user_device { + my ($udevrulefile, $linenum, $rule, $data) = @_; + my $retval = 0; + if ( + m/plugdev/ + || m/uaccess/ + || m/MODE=\"0666\"/ + ) { + $retval = 1; + } + if ($rule =~ m/SUBSYSTEM=="usb"/) { + my ($vmatch, $pmatch); + if ($rule =~ m/ATTR\{idVendor\}=="([0-9a-fA-F]{4})"/) { + $vmatch = "v" . uc($1); + } + if ($rule =~ m/ATTR\{idProduct\}=="([0-9a-fA-F]{4})"/) { + $pmatch = "p" . uc($1); + } + if (defined $vmatch && defined $pmatch) { + my $match = "usb:${vmatch}${pmatch}d"; + my $foundmatch; + for my $aliasmatch (@{$data}) { + if (0 == index($aliasmatch, $match)) { + $foundmatch = 1; + } + } + if (! $foundmatch) { + tag('appstream-metadata-missing-modalias-provide', + $udevrulefile, "match rule $match*"); + } + } + } + return $retval; +} + +=head1 NAME + +check_udev_rules + +=head1 DESCRIPTION + +Extract all udev rules from a rule file and pass them on one by one to +the callback function. + +This is a copy of a function in udev.pm. + +=cut +sub check_udev_rules { + my ($file, $check, $data) = @_; + + my $fd = $file->open(); + my $linenum = 0; + my $cont; + my $retval = 0; + while (<$fd>) { + chomp; + $linenum++; + if (defined $cont) { + $_ = $cont . $_; + $cont = undef; + } + if (/^(.*)\\$/) { + $cont = $1; + next; + } + next if /^#.*/; # Skip comments + $retval |= $check->($file, $linenum, $_, $data); + } + close($fd); + return $retval; +} + +1; + +# Local Variables: +# indent-tabs-mode: nil +# cperl-indent-level: 4 +# End: +# vim: syntax=perl sw=4 sts=4 sr et diff --git a/t/scripts/pod-spelling.t b/t/scripts/pod-spelling.t index 6973488..a5b07db 100755 --- a/t/scripts/pod-spelling.t +++ b/t/scripts/pod-spelling.t @@ -121,7 +121,7 @@ hashrefs namespace subdir SIGPIPE SIG blocknumber blocksub readwindow REMOVESLASH STAMPFILE TAGNAME TCODE TESTDATA BLOCKSIZE jN POSIX t1c2pfb init runtime txt executability writability INHANDLE OUTHANDLES UTC timestamp faux tagname READMEs Testname -debhelper dh buildpackage uaccess udev +debhelper dh buildpackage uaccess udev AppStream plugdev __END__ -- 2.9.3