[debhelper-devel] [Git][debian/debhelper][master] 2 commits: dh_usrlocal: prerm must not remove dir in usr/local
Niels Thykier
gitlab at salsa.debian.org
Sat Apr 7 10:32:29 UTC 2018
Niels Thykier pushed to branch master at Debian / debhelper
Commits:
778a9174 by Nicolas Boulenguez at 2018-04-07T10:20:44+00:00
dh_usrlocal: prerm must not remove dir in usr/local
Signed-off-by: Niels Thykier <niels at thykier.net>
- - - - -
47bb3b44 by Niels Thykier at 2018-04-07T10:30:25+00:00
t: Add test for dh_usrlocal
Signed-off-by: Niels Thykier <niels at thykier.net>
- - - - -
3 changed files:
- debian/changelog
- dh_usrlocal
- + t/dh_usrlocal/01-basic.t
Changes:
=====================================
debian/changelog
=====================================
--- a/debian/changelog
+++ b/debian/changelog
@@ -27,6 +27,9 @@ debhelper (11.2) UNRELEASED; urgency=medium
* dh_installxfonts: Fix typo that causes a misc:Depends on
non-existing xfont-utils. (Closes: #894835)
* dh_installwm.1: Document --all. (Closes: #895011)
+ * dh_usrlocal: Fix bug where the generated prerm script generated
+ by dh_usrlocal could remove a directory directly in /usr/local.
+ (Closes: #894549)
[ Mattia Rizzolo ]
* Lower the version restrictions on dpkg and dpkg-dev. They are not
=====================================
dh_usrlocal
=====================================
--- a/dh_usrlocal
+++ b/dh_usrlocal
@@ -77,54 +77,49 @@ foreach my $package (@{$dh{DOPACKAGES}}) {
if (-d "$tmp/usr/local") {
my (@dirs, @justdirs);
- find({bydepth => 1,
- no_chdir => 1,
- wanted => sub {
- my $fn = $File::Find::name;
- if (-d $fn) {
- my $user = 'root';
- my $group = 'staff';
- my $mode = '02775';
- if (should_use_root()) {
- my $stat = stat $fn;
- $user = getpwuid $stat->uid;
- $group = getgrgid $stat->gid;
- $mode = sprintf "%04lo", ($stat->mode & 07777);
- if ($stat->uid == 0 && $stat->gid == 0) {
- $group = 'staff';
- $mode = '02775';
- }
- }
-
-
-
- $fn =~ s!^\Q$tmp\E!!;
- return if $fn eq '/usr/local';
-
- # @dirs is in parents-first order for dir creation...
- unshift @dirs, "$fn $mode $user $group";
- # ...whereas @justdirs is depth-first for removal.
- push @justdirs, $fn;
- doit('rmdir', $_);
- }
- else {
- warning("$fn is not a directory");
- }
+ find({no_chdir => 1,
+ preprocess => sub {
+ # Ensure a reproducible traversal.
+ return sort @_;
+ },
+ postprocess => sub {
+ # Uninstall, unless a direct child of /usr/local.
+ $_ = $File::Find::dir;
+ s!^\Q$tmp\E!!;
+ push @justdirs, $_ if m!/usr/local/.*/!;
+ # Remove a directory after its childs.
+ doit('rmdir', $File::Find::dir);
+ },
+ wanted => sub {
+ # rmdir would fail later anyways.
+ error("${File::Find::name} is not a directory")
+ if not -d $File::Find::name;
+ # Install directory before its childs.
+ my $fn = $File::Find::name;
+ $fn =~ s!^\Q$tmp\E!!;
+ return if $fn eq '/usr/local';
+ if (should_use_root()) {
+ my $stat = stat $File::Find::dir;
+ if ($stat->uid == 0 && $stat->gid == 0) {
+ push @dirs, "$fn 02775 root staff";
+ } else {
+ my $user = getpwuid $stat->uid;
+ my $group = getgrgid $stat->gid;
+ my $mode = sprintf "%04lo", ($stat->mode & 07777);
+ push @dirs, "$fn $mode $user $group";
+ }
+ } else {
+ push @dirs, "$fn 02775 root staff";
+ }
}}, "$tmp/usr/local");
- doit('rmdir', "$tmp/usr/local");
-
- my $bs = "\\"; # A single plain backslash
- my $ebs = $bs x 2; # Escape the backslash from the shell
+
# This constructs the body of a 'sed' c\ expression which
# is parsed by the shell in double-quotes
- my $dirs = join("$ebs\n", sort @dirs);
- pop @justdirs; # don't remove directories directly in /usr/local
- my $justdirs = join("$ebs\n", reverse sort @justdirs);
if (! $dh{NOSCRIPTS}) {
autoscript($package,"postinst", "postinst-usrlocal",
- "/#DIRS#/ c${ebs}\n${dirs}");
+ { 'DIRS' => join ("\n", @dirs)}) if @dirs;
autoscript($package,"prerm", "prerm-usrlocal",
- "/#JUSTDIRS#/ c${ebs}\n${justdirs}") if length $justdirs;
+ { 'JUSTDIRS' => join ("\n", @justdirs)}) if @justdirs;
}
}
}
=====================================
t/dh_usrlocal/01-basic.t
=====================================
--- /dev/null
+++ b/t/dh_usrlocal/01-basic.t
@@ -0,0 +1,87 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More;
+plan(tests => 1);
+
+use File::Path qw(remove_tree);
+use File::Basename qw(dirname);
+use lib dirname(dirname(__FILE__));
+use Test::DH;
+use Debian::Debhelper::Dh_Lib qw(!dirname);
+
+sub extract_generated_lines {
+ my ($file) = @_;
+ my (@lines, $marker);
+ return if not -f $file;
+ open(my $fd, '<', $file) or error("open($file) failed: $!");
+ while (my $line = <$fd>) {
+ chomp($line);
+ if (defined($marker)) {
+ last if $line eq $marker;
+ push(@lines, $line);
+ next;
+ }
+ if ($line =~ m{\s*<<\s*(\S+)\s*$}) {
+ $marker = $1;
+ }
+ }
+ close($fd);
+ return @lines;
+}
+
+each_compat_subtest {
+
+ my (@postinst, @prerm);
+ my @scripts = qw(
+ debian/debhelper.postinst.debhelper
+ debian/debhelper.prerm.debhelper
+ );
+
+ rm_files(@scripts);
+ remove_tree('debian/debhelper');
+ install_dir('debian/debhelper/usr/local/foo');
+ install_dir('debian/debhelper/usr/local/bar');
+
+ ok(run_dh_tool('dh_usrlocal'));
+ @postinst = extract_generated_lines("debian/debhelper.postinst.debhelper");
+ @prerm = extract_generated_lines("debian/debhelper.prerm.debhelper");
+
+ is_deeply(\@postinst, [
+ '/usr/local/bar 02775 root staff',
+ '/usr/local/foo 02775 root staff',
+ ], "Correct dir creation")
+ or do { diag("postinst: $_") for @postinst; };
+ is_deeply(\@prerm, [], "No removal of top level dirs #894549")
+ or do { diag("prerm: $_") for @prerm; };
+
+ remove_tree('debian/debhelper');
+ rm_files(@scripts);
+ install_dir('debian/debhelper/usr/local/foo/dir/somewhere');
+ install_dir('debian/debhelper/usr/local/bar/another-dir/elsewhere');
+
+ ok(run_dh_tool('dh_usrlocal'));
+
+ @postinst = extract_generated_lines("debian/debhelper.postinst.debhelper");
+ @prerm = extract_generated_lines("debian/debhelper.prerm.debhelper");
+
+ is_deeply(\@postinst, [
+ '/usr/local/bar 02775 root staff',
+ '/usr/local/bar/another-dir 02775 root staff',
+ '/usr/local/bar/another-dir/elsewhere 02775 root staff',
+ '/usr/local/foo 02775 root staff',
+ '/usr/local/foo/dir 02775 root staff',
+ '/usr/local/foo/dir/somewhere 02775 root staff',
+ ], "Correct dir creation")
+ or do { diag("postinst: $_") for @postinst; };
+ is_deeply(\@prerm, [
+ '/usr/local/bar/another-dir/elsewhere',
+ '/usr/local/bar/another-dir',
+ '/usr/local/foo/dir/somewhere',
+ '/usr/local/foo/dir',
+ ], "Correct dir removal")
+ or do { diag("prerm: $_") for @prerm; };
+};
+
View it on GitLab: https://salsa.debian.org/debian/debhelper/compare/f1d6cad9c7a709455acf26887c0263ab96af9772...47bb3b44de87adcbcfb3a041dacd3880f1e4d4b2
---
View it on GitLab: https://salsa.debian.org/debian/debhelper/compare/f1d6cad9c7a709455acf26887c0263ab96af9772...47bb3b44de87adcbcfb3a041dacd3880f1e4d4b2
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.alioth.debian.org/pipermail/debhelper-devel/attachments/20180407/22a0c79c/attachment-0001.html>
More information about the debhelper-devel
mailing list