Author: rra
Date: 2006-05-06 23:10:50 +0200 (Sat, 06 May 2006)
New Revision: 661

Modified:
   trunk/checks/common_data.pm
   trunk/checks/menus
   trunk/checks/menus.desc
   trunk/debian/changelog
   trunk/testset/binary/debian/rules
   trunk/testset/tags.binary
Log:
* checks/menus{.desc,}:
  + [RA] Check that all files referenced in doc-base control files are
    present in the package, based on a patch by Robert Luberda.  Also
    check that Index references only one file and that Format names a
    known format.  (Closes: #196122)
  + [RA] Fix incomplete diagnosis of missing calls to update-menus.
  + [RA] Change postrm to prerm in the check for a useless install-docs
    call; calling install-docs in postrm is always a warning and useless
    calls in prerm were not being diagnosed.

Modified: trunk/checks/common_data.pm
===================================================================
--- trunk/checks/common_data.pm 2006-05-06 17:05:58 UTC (rev 660)
+++ trunk/checks/common_data.pm 2006-05-06 21:10:50 UTC (rev 661)
@@ -9,6 +9,7 @@
           %known_libstdcs %known_tcls %known_tclxs %known_tks %known_tkxs
           %known_libpngs %known_x_metapackages
           %non_standard_archs %all_cpus %all_oses
+          %known_doc_base_formats
           );
 
 # simple defines for commonly needed data
@@ -146,4 +147,8 @@
     ( 'x-window-system', 'x-window-system-dev', 'x-window-system-core',
       'xorg', 'xorg-dev', );
 
+# Supported documentation formats for doc-base files.
+%known_doc_base_formats = map { $_ => 1 }
+    ( 'html', 'text', 'pdf', 'postscript', 'info', 'dvi', 'debiandoc-sgml' );
+
 1;

Modified: trunk/checks/menus
===================================================================
--- trunk/checks/menus  2006-05-06 17:05:58 UTC (rev 660)
+++ trunk/checks/menus  2006-05-06 21:10:50 UTC (rev 661)
@@ -22,10 +22,13 @@
 
 package Lintian::menus;
 use strict;
+use common_data;
 use Tags;
 use Util;
 
 my $pkg;
+my @all_files = ();
+my %all_links = ();
 
 sub run {
 
@@ -72,7 +75,7 @@
     chomp;
     my ($perm,$owner,$size,$date,$time,$file) = split(' ', $_, 6);
     $file =~ s,^(\./),,;
-    my $temp_file = $file; # save this for the link checks to follow
+    add_file_link_info ($file);
     $file =~ s/ link to .*//;
     $file =~ s/ -> .*//;
 
@@ -115,6 +118,7 @@
        }
     }
 }
+close IN;
 
 # prerm scripts should not call update-menus
 if ($prerm{'calls-updatemenus'}) {
@@ -153,58 +157,96 @@
        tag "prerm-does-not-call-installdocs", "$docbase_file";
     }
 
-    # does postinst also call update-menus?
-    if ($postinst{'calls-updatemenus'}) {
-       # is there a menu file or menu-methods files?
-       if ($anymenu_file) {    # postrm has to call update-menus
-           if (not $postrm{'calls-updatemenus'}) {
-               tag "postrm-does-not-call-updatemenus", "$anymenu_file" unless 
$pkg eq 'menu';
-           }
-       } else { #no!
-           tag "postinst-has-useless-call-to-update-menus", "";
-       }
-    }
-
     # check the contents of the doc-base file(s)
     opendir DOCBASEDIR, "doc-base" or fail("cannot read doc-base directory.");
     while (my $dbfile = readdir DOCBASEDIR) {
-        next if -x "doc-base/$dbfile"; # don't try to parse executables, plus 
we already warned about it
-        open IN, "doc-base/$dbfile" or
-            fail("cannot open doc-base file $dbfile for reading.");
-        while (<IN>) {
-            if (/usr\/doc/) {
-                tag "doc-base-file-references-usr-doc", "$dbfile";
-            }
-        }
-        close IN;
+       next if -x "doc-base/$dbfile"; # don't try to parse executables, plus 
we already warned about it
+       open IN, "doc-base/$dbfile" or
+           fail("cannot open doc-base file $dbfile for reading.");
+
+       # Check if files referenced by doc-base are included in the package.
+       # The Index field should refer to only one file without wildcards.
+       # The Files field is a whitespace-separated list of files and may
+       # contain wildcards.  We skip without validating wildcard patterns
+       # containing character classes since otherwise we'd need to deal with
+       # wildcards inside character classes and aren't there yet.
+       #
+       # Defer checking files until we've read all possible continuation
+       # lines for the field.  As a result, all tags will be reported on the
+       # last continuation line of the field, rather than possibly where the
+       # offending file name is.
+       my (@files, $field);
+       while (1) {
+           $_ = <IN>;
+           if ((!defined ($_) || /^\S/ || /^$/) && $field) {
+               # Figure out the right line number.  It's actually the
+               # previous line, since we read ahead for continuation lines,
+               # unless we're at the end of the file.
+               my $line = $. - 1 + (defined ($_) ? 0 : 1);
+               if ($field eq 'index' && @files > 1) {
+                   tag "doc-base-index-references-multiple-files", 
"$dbfile:$line";
+               }
+               for my $file (@files) {
+                   if ($file =~ m%^/usr/doc%) {
+                       tag "doc-base-file-references-usr-doc", "$dbfile:$line";
+                   }
+                   my $regex = quotemeta (delink ($file));
+                   unless ($field eq 'index') {
+                       next if $regex =~ /\[/;
+                       $regex =~ s%\\\*%[^/]*%g;
+                       $regex =~ s%\\\?%[^/]%g;
+                       $regex .= '/?';
+                   }
+                   unless (grep { /^$regex\z/ } @all_files) {
+                       tag "doc-base-file-references-missing-file", 
"$dbfile:$line", $file;
+                   }
+               }
+               undef @files;
+               undef $field;
+           }
+           last unless defined $_;
+           if (/^\s/ && $field) {
+               push (@files, split ' ');
+           }
+           if (/^(Index|Files)\s*:\s*(.*)\s*$/i) {
+               $field = lc $1;
+               @files = split (' ', $2);
+           } elsif (/^Format\s*:\s*(.*)\s*$/i) {
+               my $format = lc $1;
+               tag "doc-base-file-unknown-format", "$dbfile:$.", $format
+                   unless $known_doc_base_formats{$format};
+           }
+       }
+       close IN;
     }
     closedir DOCBASEDIR;
+} else {
+    # postinst and postrm should not need to call install-docs
+    if ($postinst{'calls-installdocs'} or $postinst{'calls-installdocs-r'}) {
+       tag "postinst-has-useless-call-to-install-docs", "";
+    }
+    if ($prerm{'calls-installdocs'} or $prerm{'calls-installdocs-r'}) {
+       tag "prerm-has-useless-call-to-install-docs", "";
+    }
 }
-# no docbase file, but menu file?
-elsif ($anymenu_file) {        # postinst has to call update-menus
+
+if ($anymenu_file) {
+    # postinst has to call update-menus
     if (not $postinst{'calls-updatemenus'}) {
        tag "postinst-does-not-call-updatemenus", "$anymenu_file";
     }
     # postrm has to call update-menus
     if (not $postrm{'calls-updatemenus'}) {
-       tag "postrm-does-not-call-updatemenus", "$anymenu_file";
+       tag "postrm-does-not-call-updatemenus", "$anymenu_file" unless $pkg eq 
'menu';
     }
-}
-# no menu files and no doc-base files...
-else {
+} else {
     # postinst and postrm should not need to call update-menus
     if ($postinst{'calls-updatemenus'}) {
        tag "postinst-has-useless-call-to-update-menus", "";
     }
-    if ($postinst{'calls-installdocs'} or $postinst{'calls-installdocs-r'}) {
-       tag "postinst-has-useless-call-to-install-docs", "";
-    }
     if ($postrm{'calls-updatemenus'}) {
        tag "postrm-has-useless-call-to-update-menus", "";
     }
-    if ($postrm{'calls-installdocs'} or $postrm{'calls-installdocs-r'}) {
-       tag "postrm-has-useless-call-to-install-docs", "";
-    }
 }
 
 }
@@ -235,6 +277,82 @@
     return $o;
 }
 
+# Add file and link to %all_files and %all_links.  Note that both files and
+# links have to include a leading /.
+sub add_file_link_info {
+    my $file = shift;
+    my $link = undef;
+
+    $file = "/" . $file if (not $file =~ m%^/%); # make file absolute
+    $file =~ s%/+%/%g;                          # remove duplicated `/'
+    ($file, $link) = split(/ -> /, $file);
+
+    push (@all_files, $file);
+
+    if (defined $link) {
+       if (not $link =~ m,^/,) {                 # not absolute link
+           $link = "/" . $link;                  # make sure link starts with 
'/'
+           $link =~ s,/+\./+,/,g;                # remove all /./ parts
+           my $dcount = 1;
+           while ($link =~ s,^/+\.\./+,/,) {     #\ count & remove
+              $dcount++;                         #/ any leading /../ parts
+           }
+           my $f = $file;
+           while ($dcount--) {                   #\ remove last $dcount
+               $f =~ s,/[^/]*$,,;                #/ path components from $file
+           }
+           $link = $f . $link;                   # now we should have absolute 
link
+       }
+       $all_links{$file} = $link unless ($link eq $file);
+    }
+}
+
+
+# Dereference all symlinks in file.  Uses %all_links.
+sub delink {
+    my $file = shift;
+
+    $file =~ s%/+%/%g;                           # remove duplicated '/'
+    return $file unless %all_links;              # package doesn't symlinks
+
+    my $p1 = "";
+    my $p2 = $file;
+    my %used_links = ();
+
+    # In the loop below we split $file into two parts on each '/' until
+    # there's no remaining slashes.  We try substituting the first part with
+    # corresponding symlink and if it succeedes, we start the procedure from
+    # beginning.
+    #
+    # Example:
+    #   Let $all_links{"/a/b"} == "/d", and $file == "/a/b/c"
+    #   Then 0) $p1 == "",     $p2 == "/a/b/c"
+    #        1) $p1 == "/a",   $p2 == "/b/c"
+    #        2) $p1 == "/a/b", $p2 == "/c"      ; substitute "/d" for "/a/b"
+    #        3) $p1 == "",     $p2 == "/d/c"
+    #        4) $p1 == "/d",   $p2 == "/c"
+    #        5) $p1 == "/d/c", $p2 == ""
+    #
+    # Note that the algorithm supposes, that
+    #   i) $all_links{$X} != $X for each $X
+    #  ii) both keys and values of %all_links start with '/'
+
+    while (($p2 =~ s%^(/[^/]*)%%g) > 0) {
+       $p1 .= $1;
+       if (defined $all_links{$p1}) {
+           return '!!! SYMLINK LOOP !!!' if defined $used_links{$p1};
+           $p2 = $all_links{$p1} . $p2;
+           $p1 = "";
+           $used_links{$p1} = 1;
+       }
+    }
+
+    # After the loop $p2 should be empty and $p1 should contain the target
+    # file.  In some rare cases when $file contains no slashes, $p1 will be
+    # empty and $p2 will contain the result (which will be equal to $file).
+    return $p1 ne "" ? $p1 : $p2;
+}
+
 sub check_script {
     my ($script,$pres) = @_;
     my ($no_check_menu,$no_check_installdocs,$no_check_wmmenu,$calls_wmmenu);

Modified: trunk/checks/menus.desc
===================================================================
--- trunk/checks/menus.desc     2006-05-06 17:05:58 UTC (rev 660)
+++ trunk/checks/menus.desc     2006-05-06 21:10:50 UTC (rev 661)
@@ -140,9 +140,9 @@
 Info: The <tt>postinst</tt> script calls the <tt>install-docs</tt> program
  though no file is installed in <tt>/usr/share/doc-base</tt>.
 
-Tag: postrm-has-useless-call-to-install-docs
+Tag: prerm-has-useless-call-to-install-docs
 Type: error
-Info: The <tt>postrm</tt> script calls the <tt>install-docs</tt> program
+Info: The <tt>prerm</tt> script calls the <tt>install-docs</tt> program
  though no file is installed in <tt>/usr/share/doc-base</tt>.
 
 Tag: bad-menu-file-name
@@ -156,3 +156,24 @@
 Type: warning
 Info: Files in <tt>/usr/share/doc-base</tt> should only contain links to
  files in the <tt>/usr/share/doc</tt> directory.
+
+Tag: doc-base-index-references-multiple-files
+Type: error
+Info: The Index field in a doc-base file should reference the single index
+ file for that document.  Any other files belonging to the same document
+ should be listed in the Files field.
+Ref: Debian doc-base Manual, section 2.3
+
+Tag: doc-base-file-references-missing-file
+Type: error
+Info: One of the files referenced in an Index or Files field in this
+ doc-base control file does not exist in the package.  The doc-base
+ control files should be installed by the package that provides the
+ documents they are registering.
+
+Tag: doc-base-file-unknown-format
+Type: warning
+Info: The Format field in this doc-base control file declares a format
+ that is not supported.  Recognized formats are "HTML", "Text", "PDF",
+ "PostScript", "Info", "DVI", and "DebianDoc-SGML" (case-insensitive).
+Ref: Debian doc-base Manual, section 2.3

Modified: trunk/debian/changelog
===================================================================
--- trunk/debian/changelog      2006-05-06 17:05:58 UTC (rev 660)
+++ trunk/debian/changelog      2006-05-06 21:10:50 UTC (rev 661)
@@ -28,6 +28,15 @@
       require Pre-Depends on x11-common (>= 1:7.0.0).  Remove the
       duplicate check for files in /usr/bin/X11 since it no longer adds
       additional information.
+  * checks/menus{.desc,}:
+    + [RA] Check that all files referenced in doc-base control files are
+      present in the package, based on a patch by Robert Luberda.  Also
+      check that Index references only one file and that Format names a
+      known format.  (Closes: #196122)
+    + [RA] Fix incomplete diagnosis of missing calls to update-menus.
+    + [RA] Change postrm to prerm in the check for a useless install-docs
+      call; calling install-docs in postrm is always a warning and useless
+      calls in prerm were not being diagnosed.
   * checks/shared-libs.desc:
     + [RA] Document that exceptions to the -fPIC rule for shared libraries
       are possible and ask that such exceptions be documented with lintian
@@ -41,7 +50,7 @@
     + [RA] Update standards version to 3.7.2 (no changes required).
     + [RA] Update description to note calibration for Policy 3.7.2.
 
- -- Russ Allbery <[EMAIL PROTECTED]>  Sat,  6 May 2006 10:05:37 -0700
+ -- Russ Allbery <[EMAIL PROTECTED]>  Sat,  6 May 2006 14:08:15 -0700
 
 lintian (1.23.19) unstable; urgency=low
 

Modified: trunk/testset/binary/debian/rules
===================================================================
--- trunk/testset/binary/debian/rules   2006-05-06 17:05:58 UTC (rev 660)
+++ trunk/testset/binary/debian/rules   2006-05-06 21:10:50 UTC (rev 661)
@@ -25,11 +25,18 @@
        strip --remove-section=.comment --remove-section=.note 
$(tmp)/boot/hello/hello-static
        install -d $(tmp)/usr/share/doc/binary
        install -m 644 INSTALL $(tmp)/usr/share/doc/binary
+       install -d $(tmp)/usr/share/doc/binary/html
+       echo '<html></html>' > $(tmp)/usr/share/doc/binary/html/index.html
+       echo '<html></html>' > $(tmp)/usr/share/doc/binary/html/ch1.html
+       ln -s ../html/./ch1.html $(tmp)/usr/share/doc/binary/html/ch2.html
+       ln -s /usr/share/doc/binary/htm/ch1.html 
$(tmp)/usr/share/doc/binary/html/ch3.html
        install -d $(tmp)/usr/share/menu
        install -d $(tmp)/usr/lib/menu
        install -d $(tmp)/usr/share/binary
        install -m 644 debian/menu $(tmp)/usr/share/menu/binary
        install -m 644 debian/menu $(tmp)/usr/lib/menu/binary
+       install -d $(tmp)/usr/share/doc-base
+       install -m 644 debian/doc-base $(tmp)/usr/share/doc-base/binary
        install -m 644 debian/README.Debian $(tmp)/usr/share/doc/binary
        install -m 644 debian/copyright $(tmp)/usr/share/doc/binary
        install -m 644 debian/changelog $(tmp)/usr/share/doc/binary

Modified: trunk/testset/tags.binary
===================================================================
--- trunk/testset/tags.binary   2006-05-06 17:05:58 UTC (rev 660)
+++ trunk/testset/tags.binary   2006-05-06 21:10:50 UTC (rev 661)
@@ -2,19 +2,29 @@
 E: binary: changelog-file-not-compressed changelog
 E: binary: debian-changelog-file-missing-or-wrong-name
 E: binary: depends-on-x-metapackage depends: xorg
+E: binary: doc-base-file-references-missing-file binary:10 
/usr/share/doc/binary/binary.sgml.gz
+E: binary: doc-base-file-references-missing-file binary:14 
/usr/share/doc/binary/binary.txt
+E: binary: doc-base-file-references-missing-file binary:18 
/usr/share/doc/binary/html/ch4.html
+E: binary: doc-base-file-references-missing-file binary:23 
/usr/share/doc/binary/hml/*.html
+E: binary: doc-base-index-references-multiple-files binary:18
 E: binary: file-directly-in-usr-share usr/share/baz
+E: binary: lengthy-symlink usr/share/doc/binary/html/ch2.html 
../html/./ch1.html
 E: binary: menu-item-missing-required-tag section /usr/lib/menu/binary:1
 E: binary: menu-item-missing-required-tag section /usr/share/menu/binary:1
 E: binary: non-wm-in-windowmanager-menu-section x11 /usr/lib/menu/binary:4
 E: binary: non-wm-in-windowmanager-menu-section x11 /usr/share/menu/binary:4
+E: binary: postinst-does-not-call-installdocs usr/share/doc-base/binary
 E: binary: postinst-does-not-call-updatemenus usr/lib/menu/binary
 E: binary: postrm-does-not-call-updatemenus usr/lib/menu/binary
+E: binary: prerm-does-not-call-installdocs usr/share/doc-base/binary
 E: binary: statically-linked-binary ./usr/bin/static-hello
 E: binary: su-to-root-without--c /usr/lib/menu/binary:2
 E: binary: su-to-root-without--c /usr/lib/menu/binary:3
 E: binary: su-to-root-without--c /usr/share/menu/binary:2
 E: binary: su-to-root-without--c /usr/share/menu/binary:3
 E: binary: suidregister-used-in-maintainer-script postinst
+E: binary: symlink-contains-spurious-segments 
usr/share/doc/binary/html/ch2.html ../html/./ch1.html
+E: binary: symlink-should-be-relative usr/share/doc/binary/html/ch3.html 
/usr/share/doc/binary/htm/ch1.html
 E: binary: unstripped-binary-or-object ./usr/bin/hello
 I: binary source: non-standard-architecture amd64
 I: binary source: non-standard-architecture kfreebsd-i386
@@ -29,6 +39,7 @@
 W: binary: binary-without-manpage hello.static
 W: binary: binary-without-manpage iminusrbin
 W: binary: binary-without-manpage static-hello
+W: binary: doc-base-file-unknown-format binary:13 esp
 W: binary: executable-not-elf-or-script ./usr/bin/iminusrbin
 W: binary: file-in-unusual-dir usr/bar
 W: binary: menu-command-not-in-package /usr/lib/menu/binary:6 /imnothere


-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to