Bug#704197: Please review: systemd checks
On 2013-03-29 11:11, Michael Stapelberg wrote:
> Package: lintian
> Version: 2.5.10.4
> Severity: wishlist
> 
> Attached you can find my first stab at systemd-related checks for
> lintian. While some details in parsing the service files are not
> implemented (see the TODOs in the code), I’d like you to have a look at
> the checks in general. Is there anything that needs to be improved
> before these can be shipped with lintian?
> 
> Thanks!
> 
Hi,
Thanks for working on Lintian checks, it is much appreciated it.  :)
I have annotated some comments with "[style]", which are minor stylistic
guidelines.  I know Lintian's code style is a mess in general, so it
describes the style I hope we will eventually reach[1].  :)
  Note that I will try to (remember to) not repeat style hints, even if
the same "mistake" is made multiple times.
~Niels
[1] When in doubt, I tend to use:
  http://www.eyrie.org/~eagle/notes/style/perl.html
> 
> systemd.desc
> 
> 
> Check-Script: systemd
> Author: Michael Stapelberg <stapelberg@debian.org>
> Abbrev: systemd
Abrrev is optional and is only useful if the name is shorter than the
name in Check-Script (it is an abbrevation of the name, like "manpages"
is aliased "man").
> Type: binary
> Info: Checks various systemd policy things
> Needs-Info: scripts, index, unpacked, file-info
> 
> [... some tags ...]
I noticed that there appear to be no use of references (Ref: URL, #bug,
policy X.Y ...).  I would recommend finding such so people can quickly
find more information.  Links to systemd documentation, specification or
even just a Debian wiki page.
> 
> systemd
> 
> [...]
> 
> use File::Basename;
[style] I like to group Lintian modules separately (and after) external
modules.  That basically gives 3-4 groups; pragmas[, constants],
external modules and then Lintian modules.
> use Lintian::Collect::Binary ();
This import is not needed (in general, Perl do not require you to load
modules just because you use instances of classes from that module).
> use Lintian::Relation qw(:constants);
Does not appear to be used?
> use Data::Dumper;
Left-over from debugging?
> 
> sub run {
>     my ($pkg, $type, $info) = @_;
> 
>     if ($type eq 'binary') {
This condition will always be true - the "Type:"-field determines what
values $type can have.  In this particular case, it is set to "binary".
If you do not need $pkg or $type, then you can replace them with undef. E.g.
    my (undef, undef, $info) = @_;
That has the advantage that we know that argument is unused.  (As far as
I can tell, $pkg is passed around to various subs but never actually used).
> [...]
> 
>         for my $file ($info->sorted_index) {
>             if ($file =~ m,^etc/tmpfiles\.d/.*\.conf$,) {
>                 tag('systemd-tmpfiles.d-outside-usr-lib', $file);
[style] The tag sub is a special case in regards to style; it tends to
be treated like a "perl built-in" or "die-like sub" (i.e. no parentheses
unless needed for understanding or semantic reasons).  So:
    tag 'systemd-tmpfiles.d-outside-usr-lib', $file;
Note if you must use parentheses around tag, a built-in or a "die"-like
sub, please use the same style as for regular subs (see next comment).
> [...]
>             if ($file =~ m,/systemd/system/.*\.service$,) {
>                 check_systemd_service_file($pkg, $info, $file);
[style] For "non-built" sub, we tend to have space between the sub name
and the argument parentheses.  For subs that takes no arguments, the
parentheses are omitted where possible.  So:
    check_systemd_service_file ($pkg, $info, $file);
>  [...]
>         my @init_scripts = grep(m,^etc/init\.d/.+,, $info->sorted_index);
> 
Erh, I think "," might have been a poor choice of regex delimiter here
(as it is also the argument delimiter).  For this you could use ":"
(among others) or alternatively call grep with a block:
     my @init_scripts = grep {m,^etc/init\.d/.+,} $info->sorted_index;
>  [...]
>         if ($ships_systemd_file) {
>             for my $init_script (@init_scripts) {
>                 if (grep(/\Q$init_script\E\.service/, @systemd_targets) == 0) {
>                     tag('systemd-no-service-for-init-script', $init_script);
>                 }
We sometimes use the "reversed" form of if/unless to reduce scope level.
 E.g. something like:
    tag 'systemd-no-service-for-init-script', $init_script
	unless grep /\Q$init_script\E\.service/, @systemd_targets;
There is no hard rule on went; just an FYI that you are free to use it.
>  [...]
> 
> sub check_init_script {
>     my ($pkg, $info, $file) = @_;
$pkg argument does not appear to be used?
>     
>     my $lsb_source_seen;
>     open(my $fh, '<', $info->unpacked($file));
No error handling if open fails!  Something as simple as:
   or fail "open $file: $!";
is fine.
Secondly, there is no check for file type.  If someone (deliberately)
creates $file as a fifo-pipe or a symlink it will DoS or (possibly) read
"host system" files (respectively).  Usually, a
    $info->index ($file)->is_regular_file
should do (if symlinks/hardlinks can be ignored).  Alternatively, (for
symlinks) please check that the symlink can be safely resolved before
opening the file (e.g. via the link_resolved method).  For more
information, please see the Lintian::Path module's API.
>  [...]
> 
> sub check_systemd_service_file {
>     my ($pkg, $info, $file) = @_;
> 
$pkg not used here either?
>     my $filename =  $info->unpacked ($file);
>     open(my $fh, '<', $filename);
Missing error handling.
>  [...]
> }
> 
> sub split_quoted {
>     [...]
> }
> 
Is this something that could be done by Text::ParseWords?
> sub extract_service_file_names {
>     my ($pkg, $info, $file) = @_;
> 
$pkg is not used?
>     my @aliases;
>     my $section;
>     open(my $fh, '<', $info->unpacked($file));
No error handling here
>     while (<$fh>) {
> [...]
> 
>     return (basename($file), @aliases);
> }
> 
> sub check_maintainer_scripts {
>     my ($info) = @_;
> 
> # TODO: use lab_data_path before submitting
Indeed!
>     open my $fd, '<', $info->base_dir . '/control-scripts'
>         or fail "cannot open lintian control-scripts file: $!";
> 
> [...]
Error handling! \o/
~Niels
Reply to: