diff options
author | Nicolas Boulenguez <nicolas.boulenguez@free.fr> | 2018-04-07 10:20:38 +0000 |
---|---|---|
committer | Niels Thykier <niels@thykier.net> | 2018-04-07 10:20:44 +0000 |
commit | 778a9174cafc20340455d726b7ece4243f5fa070 (patch) | |
tree | cafee816b29ac16239d89697c93fbfb1e3d9ed7c /dh_usrlocal | |
parent | f1d6cad9c7a709455acf26887c0263ab96af9772 (diff) | |
download | debhelper-778a9174cafc20340455d726b7ece4243f5fa070.tar.gz |
dh_usrlocal: prerm must not remove dir in usr/local
Signed-off-by: Niels Thykier <niels@thykier.net>
Diffstat (limited to 'dh_usrlocal')
-rwxr-xr-x | dh_usrlocal | 79 |
1 files changed, 37 insertions, 42 deletions
diff --git a/dh_usrlocal b/dh_usrlocal index 5e06e658..31269ee6 100755 --- 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; } } } |