summaryrefslogtreecommitdiff
path: root/script/deb-systemd-helper
diff options
context:
space:
mode:
Diffstat (limited to 'script/deb-systemd-helper')
-rwxr-xr-xscript/deb-systemd-helper82
1 files changed, 77 insertions, 5 deletions
diff --git a/script/deb-systemd-helper b/script/deb-systemd-helper
index 62ffc79..ae83cfa 100755
--- a/script/deb-systemd-helper
+++ b/script/deb-systemd-helper
@@ -35,7 +35,7 @@ deb-systemd-helper - subset of systemctl for machines not running systemd
=head1 SYNOPSIS
-B<deb-systemd-helper> enable|disable|is-enabled|was-enabled|debian-installed|update-state|reenable S<I<unit file> ...>
+B<deb-systemd-helper> enable|disable|mask|unmask|is-enabled|was-enabled|debian-installed|update-state|reenable S<I<unit file> ...>
=head1 DESCRIPTION
@@ -47,6 +47,9 @@ package). On the first "enable", an state file is created which will be deleted
upon "disable", but only when _DEB_SYSTEMD_HELPER_PURGE=1 to distinguish purge
from remove.
+The "mask" action will keep state on whether the service was enabled/disabled
+before and will properly return to that state on "unmask".
+
The "was-enabled" action is not present in systemctl, but is required in Debian
so that we can figure out whether a service was enabled before we installed an
updated service file. See http://bugs.debian.org/717603 for details.
@@ -89,7 +92,8 @@ use Getopt::Long; # in core since Perl 5
use Data::Dumper;
my $quiet = 0;
-my $state_dir = '/var/lib/systemd/deb-systemd-helper-enabled';
+my $enabled_state_dir = '/var/lib/systemd/deb-systemd-helper-enabled';
+my $masked_state_dir = '/var/lib/systemd/deb-systemd-helper-masked';
# Globals are bad, but in this specific case, it really makes things much
# easier to write and understand.
@@ -124,7 +128,7 @@ sub find_unit {
sub dsh_state_path {
my ($scriptname) = @_;
- return $state_dir . '/' . basename($scriptname) . '.dsh-also';
+ return $enabled_state_dir . '/' . basename($scriptname) . '.dsh-also';
}
sub state_file_entries {
@@ -221,7 +225,7 @@ sub make_systemd_links {
record_in_statefile($dsh_state, $service_link);
my $statefile = $service_link;
- $statefile =~ s,^/etc/systemd/system/,$state_dir/,;
+ $statefile =~ s,^/etc/systemd/system/,$enabled_state_dir/,;
next if -e $statefile;
if (! -l $service_link) {
@@ -321,7 +325,7 @@ sub remove_links {
# but not re-created when re-installing the package.
if (is_purge() || -l $link) {
my $link_state = $link;
- $link_state =~ s,^/etc/systemd/system/,$state_dir/,;
+ $link_state =~ s,^/etc/systemd/system/,$enabled_state_dir/,;
unlink($link_state);
}
@@ -365,6 +369,66 @@ sub rmdir_if_empty {
}
}
+sub mask_service {
+ my ($scriptname, $service_path) = @_;
+
+ my @links = get_link_closure($scriptname, $service_path);
+ for my $link (@links) {
+ my $service_link = $link->{src};
+
+ my $statefile = $service_link;
+ $statefile =~ s,^/etc/systemd/system/,$masked_state_dir/,;
+ next if -e $statefile;
+
+ my $old_dest;
+ if (-l $service_link) {
+ $old_dest = readlink($service_link);
+ unlink($service_link);
+ } else {
+ make_path(dirname($service_link));
+ }
+ print STDERR "ln -s '/dev/null' '$service_link'\n" unless $quiet;
+ symlink('/dev/null', $service_link) or
+ error("unable to link $service_link to /dev/null: $!");
+ $changed_sth = 1;
+
+ # Store the old destination of the symlink so that we can unmask
+ # properly later.
+ make_path(dirname($statefile));
+ open(my $fh, '>>', $statefile);
+ print $fh $old_dest if defined($old_dest);
+ close($fh);
+ }
+}
+
+sub unmask_service {
+ my ($scriptname, $service_path) = @_;
+
+ my @links = get_link_closure($scriptname, $service_path);
+ for my $link (@links) {
+ my $service_link = $link->{src};
+
+ my $statefile = $service_link;
+ $statefile =~ s,^/etc/systemd/system/,$masked_state_dir/,;
+ next if ! -e $statefile;
+
+ my @entries = state_file_entries($statefile);
+
+ unlink($service_link) if -l $service_link;
+
+ if (@entries > 0) {
+ my $service_path = $entries[0];
+ make_path(dirname($service_link));
+ print STDERR "ln -s '$service_path' '$service_link'\n" unless $quiet;
+ symlink($service_path, $service_link) or
+ error("unable to link $service_link to $service_path: $!");
+ $changed_sth = 1;
+ }
+
+ unlink($statefile);
+ }
+}
+
my $result = GetOptions(
"quiet" => \$quiet,
);
@@ -446,6 +510,14 @@ for my $scriptname (@ARGV) {
if ($action eq 'enable') {
make_systemd_links($scriptname, $service_path);
}
+
+ if ($action eq 'mask') {
+ mask_service($scriptname, $service_path);
+ }
+
+ if ($action eq 'unmask') {
+ unmask_service($scriptname, $service_path);
+ }
}
# If we changed anything and this machine is running systemd, tell