diff -Nru init-system-helpers-1.51/debian/changelog init-system-helpers-1.54/debian/changelog --- init-system-helpers-1.51/debian/changelog 2017-10-25 15:38:42.000000000 +0000 +++ init-system-helpers-1.54/debian/changelog 2018-08-17 13:33:08.000000000 +0000 @@ -1,3 +1,74 @@ +init-system-helpers (1.54) unstable; urgency=medium + + * Revert "Drop fallback for old versions of systemd that didn't have + is-enabled" + If a package ships both init script and systemd service file, the + systemd unit will not be enabled by the time invoke-rc.d is called + (with current debhelper sequence). This would make systemctl is-enabled + report the wrong status, and then the service would not be started. + Add a comment noting this to avoid removing again in the future. + This reverts commit 6f95680ffc9b1605841eb7d3d8eb92c790e6c73a. + (Closes: #906421, #906051) + + -- Felipe Sateler Fri, 17 Aug 2018 10:33:08 -0300 + +init-system-helpers (1.53) unstable; urgency=medium + + * tests: only load Linux::Clone if not testing on real system + 'use' directive is evaluated at compile time, so having it inside an 'if' + statement does not have the expected effect. Use the 'use if' directive instead. + This fixes running the autopkgtests in clean systems without Linux::Clone module + + -- Felipe Sateler Wed, 15 Aug 2018 23:52:53 -0300 + +init-system-helpers (1.52) unstable; urgency=medium + + [ Felipe Sateler ] + * Change Vcs-* urls to point to the new salsa service + * Drop fallback for old versions of systemd that didn't have is-enabled. + This reverts commit 0e43de3196a68e59d8a543d1cf7f5b4bfbb27451 + * invoke-rc.d: add option to do nothing for native systemd units. + It is useful to simplify maintainer scripts, since it allows executing + this command for sysvinit/openrc + systems, and deb-systemd-invoke for systemd systems + * Update Standards-Version + * deb-systemd-*: Invoke perl interpreter directly in /usr/bin. + Do not go through PATH, and avoid possibly using a user-installed + interpreter + * Bump debhelper compat level to 11 + * Fix manpage references in d/copyright. + They were not updated when the manpages were converted to rst + * Replace usage of dpkg-parsechangelog with pkg-info.mk provided by dpkg-dev + + [ Daniele Nicolodi ] + * deb-systemd-helper: Fix typo in man page + * d/rules: Fix man pages header and footer. + Pass options to pod2mn to get correct header and footer content. + * deb-systemd-helper: Add comment explaining why 'systemctl preset' is used + * tests: Move common setup code and test functions to a new helpers.pm module + * tests: Fix setup when TEST_ON_REAL_SYSTEM is not set + * tests: Do not require Linux::Clone Perl module if TEST_ON_REAL_SYSTEM is + set. + If the TEST_ON_REAL_SYSTEM environment variable is set, the bind + mounting of empty directories not top of system difrectoried affected + by the tests is skipt. Therefore, there is no need to isolate the + tests in a mount namespace. + * tests: Make sure that the tests do not clutter the host system. + In the mount namespace created for the tests, remount the root + filesystem read-only. To be able to create temporary files and + directories, mount a tmpfs on /tmp. + * autopkgtests: Drop seteup steps that are not required anymore + * deb-systemd-helper: Implement user instance's service handling + * tests: Add tests for user instance's service handling + * tests: Make calling 'deb-systemd-helper' in tests less verbose. + Removing the shell interposition in the system() calls avoids edge + cases in parameters handling (there were places where the randomly + generated unit names were not correctly quoted) and speeds up tests + execution. + * tests: Check that the root filesystemd has been marked private + + -- Felipe Sateler Sun, 12 Aug 2018 10:19:38 -0300 + init-system-helpers (1.51) unstable; urgency=high [ Michael Biebl ] @@ -7,7 +78,8 @@ [ Felipe Sateler ] * Fix errors in pod2man invocations. - Catch errors when building pod manpages, and stop trying to build documentation for the debhelper tools + Catch errors when building pod manpages, and stop trying to build + documentation for the debhelper tools * Convert manpages into reStructuredText * update-rc.d: fix typo that was disabling all sysv scripts in defaults mode (Closes: #879771). diff -Nru init-system-helpers-1.51/debian/compat init-system-helpers-1.54/debian/compat --- init-system-helpers-1.51/debian/compat 2017-10-25 15:38:42.000000000 +0000 +++ init-system-helpers-1.54/debian/compat 2018-08-17 13:33:08.000000000 +0000 @@ -1 +1 @@ -9 +11 diff -Nru init-system-helpers-1.51/debian/control init-system-helpers-1.54/debian/control --- init-system-helpers-1.51/debian/control 2017-10-25 15:38:42.000000000 +0000 +++ init-system-helpers-1.54/debian/control 2018-08-17 13:33:08.000000000 +0000 @@ -5,12 +5,12 @@ Uploaders: Michael Biebl , Martin Pitt , Felipe Sateler -Build-Depends: debhelper (>= 9), +Build-Depends: debhelper (>= 11), perl:any, python3-docutils -Standards-Version: 4.0.0 -Vcs-Git: https://anonscm.debian.org/git/collab-maint/init-system-helpers.git -Vcs-Browser: https://anonscm.debian.org/git/collab-maint/init-system-helpers.git +Standards-Version: 4.2.0 +Vcs-Git: https://salsa.debian.org/debian/init-system-helpers.git +Vcs-Browser: https://salsa.debian.org/debian/init-system-helpers Package: init-system-helpers Architecture: all diff -Nru init-system-helpers-1.51/debian/copyright init-system-helpers-1.54/debian/copyright --- init-system-helpers-1.51/debian/copyright 2017-10-25 15:38:42.000000000 +0000 +++ init-system-helpers-1.54/debian/copyright 2018-08-17 13:33:08.000000000 +0000 @@ -13,11 +13,11 @@ 2008 Canonical Ltd License: GPL-2+ -Files: script/invoke-rc.d man8/invoke-rc.d.8 +Files: script/invoke-rc.d man8/invoke-rc.d.8.rst Copyright: 2000,2001 Henrique de Moraes Holschuh License: GPL-2+ -Files: script/update-rc.d man8/update-rc.d.8 +Files: script/update-rc.d man8/update-rc.d.8.rst Copyright: 1997-2005 Miquel van Smoorenburg Members of the pkg-sysvinit project License: GPL-2+ diff -Nru init-system-helpers-1.51/debian/rules init-system-helpers-1.54/debian/rules --- init-system-helpers-1.51/debian/rules 2017-10-25 15:38:42.000000000 +0000 +++ init-system-helpers-1.54/debian/rules 2018-08-17 13:33:08.000000000 +0000 @@ -9,7 +9,7 @@ # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 -VERSION = $(shell dpkg-parsechangelog -S Version) +include /usr/share/dpkg/pkg-info.mk override_dh_perl: dh_perl -d --package=init-system-helpers @@ -19,7 +19,7 @@ dh_auto_build set -e ; \ for file in script/deb-*; do \ - pod2man --section=1p --utf8 $$file $$file.1p; \ + pod2man --section=1p --utf8 --center="init-system-helpers" --release=$(DEB_VERSION) $$file $$file.1p; \ done set -e ; \ for file in man8/*.rst ; do \ @@ -28,7 +28,7 @@ override_dh_install: dh_install - [ ! -d debian/init-system-helpers ] || sed -i 's/__VERSION__/$(VERSION)/' debian/init-system-helpers/usr/sbin/service + [ ! -d debian/init-system-helpers ] || sed -i 's/__VERSION__/$(DEB_VERSION)/' debian/init-system-helpers/usr/sbin/service override_dh_gencontrol: diff -Nru init-system-helpers-1.51/debian/tests/control init-system-helpers-1.54/debian/tests/control --- init-system-helpers-1.51/debian/tests/control 2017-10-25 15:38:42.000000000 +0000 +++ init-system-helpers-1.54/debian/tests/control 2018-08-17 13:33:08.000000000 +0000 @@ -1,5 +1,4 @@ Tests: t Depends: @, - cpanminus, build-essential Restrictions: needs-root, breaks-testbed, allow-stderr, isolation-container diff -Nru init-system-helpers-1.51/debian/tests/t init-system-helpers-1.54/debian/tests/t --- init-system-helpers-1.51/debian/tests/t 2017-10-25 15:38:42.000000000 +0000 +++ init-system-helpers-1.54/debian/tests/t 2018-08-17 13:33:08.000000000 +0000 @@ -1,9 +1,6 @@ #!/bin/sh set -eu -mount --make-rprivate / -cpanm Linux::Clone - export TEST_ON_REAL_SYSTEM=1 for test in t/*.t; do diff -Nru init-system-helpers-1.51/man8/invoke-rc.d.rst init-system-helpers-1.54/man8/invoke-rc.d.rst --- init-system-helpers-1.51/man8/invoke-rc.d.rst 2017-10-25 15:38:42.000000000 +0000 +++ init-system-helpers-1.54/man8/invoke-rc.d.rst 2018-08-17 13:33:08.000000000 +0000 @@ -101,6 +101,12 @@ this is usually a very bad idea for any actions other than start. +*--skip-systemd-native* + Exits before doing anything if a systemd environment is detected + and the requested service is a native systemd unit. + This is useful for maintainer scripts that want to defer systemd + actions to ``deb-systemd-invoke``\(1p\) + STATUS CODES ============ diff -Nru init-system-helpers-1.51/script/deb-systemd-helper init-system-helpers-1.54/script/deb-systemd-helper --- init-system-helpers-1.51/script/deb-systemd-helper 2017-10-25 15:38:42.000000000 +0000 +++ init-system-helpers-1.54/script/deb-systemd-helper 2018-08-17 13:33:08.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/env perl +#!/usr/bin/perl # vim:ts=4:sw=4:expandtab # © 2013-2014 Michael Stapelberg # @@ -43,7 +43,7 @@ the enable, disable, is-enabled and reenable commands from systemctl. The "enable" action will only be performed once (when first installing the -package). On the first "enable", an state file is created which will be deleted +package). On the first "enable", a state file is created which will be deleted upon "purge". The "mask" action will keep state on whether the service was enabled/disabled @@ -90,9 +90,17 @@ # only have perl-base, not perl). eval { require Data::Dumper; } or *Data::Dumper::Dumper = sub { "no Data::Dumper" }; +use constant { + SYSTEM_INSTANCE_ENABLED_STATE_DIR => '/var/lib/systemd/deb-systemd-helper-enabled', + USER_INSTANCE_ENABLED_STATE_DIR => '/var/lib/systemd/deb-systemd-user-helper-enabled', + SYSTEM_INSTANCE_MASKED_STATE_DIR => '/var/lib/systemd/deb-systemd-helper-masked', + USER_INSTANCE_MASKED_STATE_DIR => '/var/lib/systemd/deb-systemd-user-helper-masked', +}; + my $quiet = 0; -my $enabled_state_dir = '/var/lib/systemd/deb-systemd-helper-enabled'; -my $masked_state_dir = '/var/lib/systemd/deb-systemd-helper-masked'; +my $instance = 'system'; +my $enabled_state_dir = SYSTEM_INSTANCE_ENABLED_STATE_DIR; +my $masked_state_dir = SYSTEM_INSTANCE_MASKED_STATE_DIR; # Globals are bad, but in this specific case, it really makes things much # easier to write and understand. @@ -118,11 +126,15 @@ my ($scriptname) = @_; my $service_path = $scriptname; - if (-f "/etc/systemd/system/$scriptname") { - $service_path = "/etc/systemd/system/$scriptname"; - } elsif (-f "/lib/systemd/system/$scriptname") { - $service_path = "/lib/systemd/system/$scriptname"; + + if (-f "/etc/systemd/$instance/$scriptname") { + $service_path = "/etc/systemd/$instance/$scriptname"; + } elsif (-f "/lib/systemd/$instance/$scriptname") { + $service_path = "/lib/systemd/$instance/$scriptname"; + } elsif (-f "/usr/lib/systemd/$instance/$scriptname") { + $service_path = "/usr/lib/systemd/$instance/$scriptname"; } + return $service_path; } @@ -195,7 +207,7 @@ if ($line =~ /^\s*(WantedBy|RequiredBy)=(.+)$/i) { for my $value (split(/\s+/, $2)) { $value =~ s/^(["'])(.*)\g1$/$2/; - my $wants_dir = "/etc/systemd/system/$value"; + my $wants_dir = "/etc/systemd/$instance/$value"; $wants_dir .= '.wants' if $1 eq 'WantedBy'; $wants_dir .= '.requires' if $1 eq 'RequiredBy'; push @links, { dest => $service_path, src => "$wants_dir/$scriptname" }; @@ -215,7 +227,7 @@ for my $value (split(/\s+/, $1)) { $value =~ s/^(["'])(.*)\g1$/$2/; if ($value ne $unit_name) { - push @links, { dest => $service_path, src => "/etc/systemd/system/$1" }; + push @links, { dest => $service_path, src => "/etc/systemd/$instance/$1" }; } } } @@ -246,17 +258,21 @@ sub enable { my ($scriptname, $service_path) = @_; if ($has_systemctl) { - # We use systemctl preset on the initial installation only - # On upgrade, we manually add the missing symlinks only if - # the service already has some links installed. + # We use 'systemctl preset' on the initial installation only. + # On upgrade, we manually add the missing symlinks only if the + # service already has some links installed. Using 'systemctl + # preset' allows administrators and downstreams to alter the + # enable policy using systemd-native tools. my $create_links = 0; if (debian_installed($scriptname)) { $create_links = 1 unless no_link_installed($scriptname, $service_path); } else { debug "Using systemctl preset to enable $scriptname"; - system("/bin/systemctl", "--preset-mode=enable-only", - "preset", $scriptname) == 0 or - error("systemctl preset failed on $scriptname: $!"); + system("/bin/systemctl", + $instance eq "user" ? "--global" : "--system", + "--preset-mode=enable-only", + "preset", $scriptname) == 0 + or error("systemctl preset failed on $scriptname: $!"); } make_systemd_links($scriptname, $service_path, create_links => $create_links); } else { @@ -279,7 +295,7 @@ record_in_statefile($dsh_state, $service_link); my $statefile = $service_link; - $statefile =~ s,^/etc/systemd/system/,$enabled_state_dir/,; + $statefile =~ s,^/etc/systemd/$instance/,$enabled_state_dir/,; next if -e $statefile; if ($opts{'create_links'} && ! -l $service_link) { @@ -378,7 +394,7 @@ # but not re-created when re-installing the package. if (is_purge() || -l $link) { my $link_state = $link; - $link_state =~ s,^/etc/systemd/system/,$enabled_state_dir/,; + $link_state =~ s,^/etc/systemd/$instance/,$enabled_state_dir/,; unlink($link_state); } @@ -425,7 +441,7 @@ sub mask_service { my ($scriptname, $service_path) = @_; - my $mask_link = '/etc/systemd/system/' . basename($service_path); + my $mask_link = "/etc/systemd/$instance/" . basename($service_path); if (-e $mask_link) { # If the link already exists, don’t do anything. @@ -447,7 +463,7 @@ $changed_sth = 1; my $statefile = $mask_link; - $statefile =~ s,^/etc/systemd/system/,$masked_state_dir/,; + $statefile =~ s,^/etc/systemd/$instance/,$masked_state_dir/,; # Store the fact that we masked this service, so that we can unmask it on # installation time. We cannot unconditionally unmask because that would @@ -460,7 +476,7 @@ sub unmask_service { my ($scriptname, $service_path) = @_; - my $mask_link = '/etc/systemd/system/' . basename($service_path); + my $mask_link = "/etc/systemd/$instance/" . basename($service_path); # Not masked? Nothing to do. return unless -e $mask_link; @@ -471,7 +487,7 @@ } my $statefile = $mask_link; - $statefile =~ s,^/etc/systemd/system/,$masked_state_dir/,; + $statefile =~ s,^/etc/systemd/$instance/,$masked_state_dir/,; if (! -e $statefile) { debug "Not unmasking $mask_link because the state file $statefile does not exist"; @@ -486,8 +502,16 @@ my $result = GetOptions( "quiet" => \$quiet, + "user" => sub { $instance = 'user'; }, + "system" => sub { $instance = 'system'; }, # default ); +if ($instance eq 'user') { + debug "is user unit = yes"; + $enabled_state_dir = USER_INSTANCE_ENABLED_STATE_DIR; + $masked_state_dir = USER_INSTANCE_MASKED_STATE_DIR; +} + my $action = shift; if (!defined($action)) { # Called without arguments. Explain that this script should not be run interactively. @@ -557,12 +581,14 @@ remove_links($service_path); # Clean up the state dir if it’s empty, or at least clean up all empty # subdirectories. Necessary to cleanly pass a piuparts run. - rmdir_if_empty('/var/lib/systemd/deb-systemd-helper-enabled'); + rmdir_if_empty(SYSTEM_INSTANCE_ENABLED_STATE_DIR); + rmdir_if_empty(USER_INSTANCE_ENABLED_STATE_DIR); # Same with directories below /etc/systemd, where we create symlinks. # If systemd is not installed (and no other package shipping service # files), this would make piuparts fail, too. rmdir_if_empty($_) for (grep { -d } ); + rmdir_if_empty($_) for (grep { -d } ); } if ($action eq 'enable') { @@ -584,7 +610,7 @@ # If we changed anything and this machine is running systemd, tell # systemd to reload so that it will immediately pick up our # changes. -if ($changed_sth && -d "/run/systemd/system") { +if ($changed_sth && $instance eq 'system' && -d "/run/systemd/system") { system("systemctl", "daemon-reload"); } diff -Nru init-system-helpers-1.51/script/deb-systemd-invoke init-system-helpers-1.54/script/deb-systemd-invoke --- init-system-helpers-1.51/script/deb-systemd-invoke 2017-10-25 15:38:42.000000000 +0000 +++ init-system-helpers-1.54/script/deb-systemd-invoke 2018-08-17 13:33:08.000000000 +0000 @@ -1,4 +1,4 @@ -#!/usr/bin/env perl +#!/usr/bin/perl # vim:ts=4:sw=4:expandtab # © 2013 Michael Stapelberg # diff -Nru init-system-helpers-1.51/script/invoke-rc.d init-system-helpers-1.54/script/invoke-rc.d --- init-system-helpers-1.51/script/invoke-rc.d 2017-10-25 15:38:42.000000000 +0000 +++ init-system-helpers-1.54/script/invoke-rc.d 2018-08-17 13:33:08.000000000 +0000 @@ -39,6 +39,7 @@ RC= is_systemd= is_openrc= +SKIP_SYSTEMD_NATIVE= # Shell options set +e @@ -83,6 +84,11 @@ Ignores any fallback action requests by the policy layer. Warning: this is usually a very *bad* idea for any actions other than "start". + --skip-systemd-native + Exits before doing anything if a systemd environment is detected + and the requested service is a native systemd unit. + This is useful for maintainer scripts that want to defer systemd + actions to deb-systemd-invoke --help Outputs help message to stdout @@ -240,6 +246,8 @@ ;; --no-fallback) NOFALLBACK=yes + ;; + --skip-systemd-native) SKIP_SYSTEMD_NATIVE=yes ;; --*) printerror syntax error: unknown option \"$1\" exit 103 @@ -366,9 +374,12 @@ if [ -n "$is_systemd" ]; then case ${ACTION} in start|restart|try-restart) - # Note that systemd 215 does not yet support is-enabled for SysV scripts, - # this works only with systemd >= 220-1 (systemd-sysv-install). Add a - # simple fallback check which can be dropped after releasing stretch. + # If a package ships both init script and systemd service file, the + # systemd unit will not be enabled by the time invoke-rc.d is called + # (with current debhelper sequence). This would make systemctl is-enabled + # report the wrong status, and then the service would not be started. + # This check cannot be removed as long as we support not passing --skip-systemd-native + if systemctl --quiet is-enabled "${UNIT}" 2>/dev/null || \ ls ${RCDPREFIX}[S2345].d/S[0-9][0-9]${INITSCRIPTID} >/dev/null 2>&1; then RC=104 @@ -479,6 +490,18 @@ # pick up any changes. systemctl daemon-reload fi + if [ "$SKIP_SYSTEMD_NATIVE" = yes ] ; then + case $(systemctl show --value --property SourcePath "${UNIT}") in + /etc/init.d/*) + ;; + *) + # We were asked to skip native systemd units, and this one was not generated by the sysv generator + # exit cleanly + exit 0 + ;; + esac + + fi _state=$(systemctl -p LoadState show "${UNIT}" 2>/dev/null) # avoid deadlocks during bootup and shutdown from units/hooks diff -Nru init-system-helpers-1.51/t/001-deb-systemd-helper.t init-system-helpers-1.54/t/001-deb-systemd-helper.t --- init-system-helpers-1.51/t/001-deb-systemd-helper.t 2017-10-25 15:38:42.000000000 +0000 +++ init-system-helpers-1.54/t/001-deb-systemd-helper.t 2018-08-17 13:33:08.000000000 +0000 @@ -8,47 +8,11 @@ use File::Path qw(make_path); # in core since Perl 5.001 use File::Basename; # in core since Perl 5 use FindBin; # in core since Perl 5.00307 -use Linux::Clone; # neither in core nor in Debian :-/ -# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ SETUP: in a new mount namespace, bindmount tmpdirs on /etc/systemd and ┃ -# ┃ /var/lib/systemd to start with clean directories yet use the actual ┃ -# ┃ locations and code paths. ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - -my $dsh = "$FindBin::Bin/../script/deb-systemd-helper"; - -sub _unit_check { - my ($unit_file, $cmd, $cb, $verb) = @_; - - my $retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh $cmd '$unit_file'"); - isnt($retval, -1, 'deb-systemd-helper could be executed'); - ok(!($retval & 127), 'deb-systemd-helper did not exit due to a signal'); - $cb->($retval >> 8, 0, "random unit file $verb $cmd"); -} - -sub is_enabled { _unit_check($_[0], 'is-enabled', \&is, 'is') } -sub isnt_enabled { _unit_check($_[0], 'is-enabled', \&isnt, 'isnt') } +use lib "$FindBin::Bin/."; +use helpers; -sub is_debian_installed { _unit_check($_[0], 'debian-installed', \&is, 'is') } -sub isnt_debian_installed { _unit_check($_[0], 'debian-installed', \&isnt, 'isnt') } - -my $retval = Linux::Clone::unshare Linux::Clone::NEWNS; -BAIL_OUT("Cannot unshare(NEWNS): $!") if $retval != 0; - -sub bind_mount_tmp { - my ($dir) = @_; - my $tmp = tempdir(CLEANUP => 1); - system("mount -n --bind $tmp $dir") == 0 - or BAIL_OUT("bind-mounting $tmp to $dir failed: $!"); - return $tmp; -} - -unless ($ENV{'TEST_ON_REAL_SYSTEM'}) { - my $etc_systemd = bind_mount_tmp('/etc/systemd'); - my $lib_systemd = bind_mount_tmp('/lib/systemd'); - my $var_lib_systemd = bind_mount_tmp('/var/lib/systemd'); -} +test_setup(); # ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ # ┃ Verify “is-enabled” is not true for a random, non-existing unit file. ┃ @@ -96,7 +60,7 @@ 'multi-user.target.wants does not exist yet'); } -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh enable '$random_unit'"); +my $retval = dsh('enable', $random_unit); is($retval, 0, "enable command succeeded"); my $symlink_path = "/etc/systemd/system/multi-user.target.wants/$random_unit"; ok(-l $symlink_path, "$random_unit was enabled"); @@ -120,7 +84,7 @@ isnt_enabled($random_unit); is_debian_installed($random_unit); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh enable '$random_unit'"); +$retval = dsh('enable', $random_unit); is($retval, 0, "enable command succeeded"); isnt_enabled($random_unit); @@ -133,7 +97,9 @@ ok(-f $statefile, 'state file exists'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test _DEB_SYSTEMD_HELPER_PURGE=1 $dsh disable '$random_unit'"); +$ENV{'_DEB_SYSTEMD_HELPER_PURGE'} = '1'; +$retval = dsh('disable', $random_unit); +delete $ENV{'_DEB_SYSTEMD_HELPER_PURGE'}; is($retval, 0, "disable command succeeded"); ok(! -f $statefile, 'state file does not exist anymore after purging'); isnt_debian_installed($random_unit); @@ -145,7 +111,7 @@ ok(! -l $symlink_path, 'symlink does not exist yet'); isnt_enabled($random_unit); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh enable '$random_unit'"); +$retval = dsh('enable', $random_unit); is($retval, 0, "enable command succeeded"); is_enabled($random_unit); @@ -155,7 +121,9 @@ # ┃ Verify “disable” removes the symlinks. ┃ # ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test _DEB_SYSTEMD_HELPER_PURGE=1 $dsh disable '$random_unit'"); +$ENV{'_DEB_SYSTEMD_HELPER_PURGE'} = '1'; +$retval = dsh('disable', $random_unit); +delete $ENV{'_DEB_SYSTEMD_HELPER_PURGE'}; is($retval, 0, "disable command succeeded"); isnt_enabled($random_unit); @@ -167,7 +135,7 @@ ok(! -l $symlink_path, 'symlink does not exist yet'); isnt_enabled($random_unit); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh enable '$random_unit'"); +$retval = dsh('enable', $random_unit); is($retval, 0, "enable command succeeded"); is_enabled($random_unit); @@ -177,7 +145,7 @@ # ┃ Verify the “purge” verb works. ┃ # ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh purge '$random_unit'"); +$retval = dsh('purge', $random_unit); is($retval, 0, "purge command succeeded"); isnt_enabled($random_unit); @@ -190,7 +158,7 @@ ok(! -l $symlink_path, 'symlink does not exist yet'); isnt_enabled($random_unit); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh enable '$random_unit'"); +$retval = dsh('enable', $random_unit); is($retval, 0, "enable command succeeded"); is_enabled($random_unit); @@ -203,12 +171,12 @@ my $mask_path = "/etc/systemd/system/$random_unit"; ok(! -l $mask_path, 'mask link does not exist yet'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh mask '$random_unit'"); +$retval = dsh('mask', $random_unit); is($retval, 0, "mask command succeeded"); ok(-l $mask_path, 'mask link exists'); is(readlink($mask_path), '/dev/null', 'service masked'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh unmask '$random_unit'"); +$retval = dsh('unmask', $random_unit); is($retval, 0, "unmask command succeeded"); ok(! -e $mask_path, 'mask link does not exist anymore'); @@ -216,16 +184,16 @@ # ┃ Verify “mask” (when disabled) works the same way ┃ # ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh disable '$random_unit'"); +$retval = dsh('disable', $random_unit); is($retval, 0, "disable command succeeded"); ok(! -e $symlink_path, 'symlink no longer exists'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh mask '$random_unit'"); +$retval = dsh('mask', $random_unit); is($retval, 0, "mask command succeeded"); ok(-l $mask_path, 'mask link exists'); is(readlink($mask_path), '/dev/null', 'service masked'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh unmask '$random_unit'"); +$retval = dsh('unmask', $random_unit); is($retval, 0, "unmask command succeeded"); ok(! -e $mask_path, 'symlink no longer exists'); @@ -238,12 +206,12 @@ ok(-l $mask_path, 'mask link exists'); is(readlink($mask_path), '/dev/null', 'service masked'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh mask '$random_unit'"); +$retval = dsh('mask', $random_unit); is($retval, 0, "mask command succeeded"); ok(-l $mask_path, 'mask link exists'); is(readlink($mask_path), '/dev/null', 'service still masked'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh unmask '$random_unit'"); +$retval = dsh('unmask', $random_unit); is($retval, 0, "unmask command succeeded"); ok(-l $mask_path, 'mask link exists'); is(readlink($mask_path), '/dev/null', 'service still masked'); @@ -270,14 +238,14 @@ ok(-e $mask_path, 'local service file exists'); ok(! -l $mask_path, 'local service file is not a symlink'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh mask '$random_unit'"); +$retval = dsh('mask', $random_unit); isnt($retval, -1, 'deb-systemd-helper could be executed'); ok(!($retval & 127), 'deb-systemd-helper did not exit due to a signal'); is($retval >> 8, 0, 'deb-systemd-helper exited with exit code 0'); ok(-e $mask_path, 'local service file still exists'); ok(! -l $mask_path, 'local service file is still not a symlink'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh unmask '$random_unit'"); +$retval = dsh('unmask', $random_unit); isnt($retval, -1, 'deb-systemd-helper could be executed'); ok(!($retval & 127), 'deb-systemd-helper did not exit due to a signal'); is($retval >> 8, 0, 'deb-systemd-helper exited with exit code 0'); @@ -290,7 +258,7 @@ # ┃ Verify Alias= handling. ┃ # ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh purge '$random_unit'"); +$retval = dsh('purge', $random_unit); is($retval, 0, "purge command succeeded"); open($fh, '>', $servicefile_path); @@ -311,23 +279,23 @@ isnt_enabled('foo\x2dtest.service'); my $alias_path = '/etc/systemd/system/foo\x2dtest.service'; ok(! -l $alias_path, 'alias link does not exist yet'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh enable '$random_unit'"); +$retval = dsh('enable', $random_unit); is($retval, 0, "enable command succeeded"); is(readlink($alias_path), $servicefile_path, 'correct alias link'); is_enabled($random_unit); ok(! -l $mask_path, 'mask link does not exist yet'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh mask '$random_unit'"); +$retval = dsh('mask', $random_unit); is($retval, 0, "mask command succeeded"); is(readlink($alias_path), $servicefile_path, 'correct alias link'); is(readlink($mask_path), '/dev/null', 'service masked'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh unmask '$random_unit'"); +$retval = dsh('unmask', $random_unit); is($retval, 0, "unmask command succeeded"); is(readlink($alias_path), $servicefile_path, 'correct alias link'); ok(! -l $mask_path, 'mask link does not exist any more'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh disable '$random_unit'"); +$retval = dsh('disable', $random_unit); isnt_enabled($random_unit); ok(! -l $alias_path, 'alias link does not exist any more'); @@ -335,25 +303,25 @@ # ┃ Verify Alias/mask with removed package (as in postrm) ┃ # ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh purge '$random_unit'"); +$retval = dsh('purge', $random_unit); is($retval, 0, "purge command succeeded"); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh enable '$random_unit'"); +$retval = dsh('enable', $random_unit); is($retval, 0, "enable command succeeded"); is(readlink($alias_path), $servicefile_path, 'correct alias link'); unlink($servicefile_path); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh mask '$random_unit'"); +$retval = dsh('mask', $random_unit); is($retval, 0, "mask command succeeded with uninstalled unit"); is(readlink($alias_path), $servicefile_path, 'correct alias link'); is(readlink($mask_path), '/dev/null', 'service masked'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh purge '$random_unit'"); +$retval = dsh('purge', $random_unit); is($retval, 0, "purge command succeeded with uninstalled unit"); ok(! -l $alias_path, 'alias link does not exist any more'); is(readlink($mask_path), '/dev/null', 'service masked'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh unmask '$random_unit'"); +$retval = dsh('unmask', $random_unit); is($retval, 0, "unmask command succeeded with uninstalled unit"); ok(! -l $mask_path, 'mask link does not exist any more'); @@ -378,7 +346,7 @@ isnt_enabled($random_unit); isnt_enabled('foo\x2dtest.service'); # note that in this case $alias_path and $mask_path are identical -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh enable '$random_unit'"); +$retval = dsh('enable', $random_unit); is($retval, 0, "enable command succeeded"); is_enabled($random_unit); # systemctl enable does create the alias link even if it's not needed @@ -386,15 +354,15 @@ unlink($servicefile_path); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh mask '$random_unit'"); +$retval = dsh('mask', $random_unit); is($retval, 0, "mask command succeeded"); is(readlink($mask_path), '/dev/null', 'service masked'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh unmask '$random_unit'"); +$retval = dsh('unmask', $random_unit); is($retval, 0, "unmask command succeeded"); ok(! -l $mask_path, 'mask link does not exist any more'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh purge '$random_unit'"); +$retval = dsh('purge', $random_unit); isnt_enabled($random_unit); ok(! -l $mask_path, 'mask link does not exist any more'); diff -Nru init-system-helpers-1.51/t/002-deb-systemd-helper-update.t init-system-helpers-1.54/t/002-deb-systemd-helper-update.t --- init-system-helpers-1.51/t/002-deb-systemd-helper-update.t 2017-10-25 15:38:42.000000000 +0000 +++ init-system-helpers-1.54/t/002-deb-systemd-helper-update.t 2018-08-17 13:33:08.000000000 +0000 @@ -8,57 +8,11 @@ use File::Path qw(make_path); # in core since Perl 5.001 use File::Basename; # in core since Perl 5 use FindBin; # in core since Perl 5.00307 -use Linux::Clone; # neither in core nor in Debian :-/ -# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ SETUP: in a new mount namespace, bindmount tmpdirs on /etc/systemd and ┃ -# ┃ /var/lib/systemd to start with clean directories yet use the actual ┃ -# ┃ locations and code paths. ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - -my $dsh = "$FindBin::Bin/../script/deb-systemd-helper"; - -# reads in a whole file -sub slurp { - open my $fh, '<', shift; - local $/; - <$fh>; -} - -sub state_file_entries { - my ($path) = @_; - my $bytes = slurp($path); - return split("\n", $bytes); -} - -sub _unit_enabled { - my ($unit_file, $cb, $verb) = @_; - - my $retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh is-enabled $unit_file"); - isnt($retval, -1, 'deb-systemd-helper could be executed'); - ok(!($retval & 127), 'deb-systemd-helper did not exit due to a signal'); - $cb->($retval >> 8, 0, "random unit file $verb enabled"); -} - -sub is_enabled { _unit_enabled($_[0], \&is, 'is') } -sub isnt_enabled { _unit_enabled($_[0], \&isnt, 'isnt') } - -my $retval = Linux::Clone::unshare Linux::Clone::NEWNS; -BAIL_OUT("Cannot unshare(NEWNS): $!") if $retval != 0; - -sub bind_mount_tmp { - my ($dir) = @_; - my $tmp = tempdir(CLEANUP => 1); - system("mount -n --bind $tmp $dir") == 0 - or BAIL_OUT("bind-mounting $tmp to $dir failed: $!"); - return $tmp; -} - -unless ($ENV{'TEST_ON_REAL_SYSTEM'}) { - my $etc_systemd = bind_mount_tmp('/etc/systemd'); - my $lib_systemd = bind_mount_tmp('/lib/systemd'); - my $var_lib_systemd = bind_mount_tmp('/var/lib/systemd'); -} +use lib "$FindBin::Bin/."; +use helpers; + +test_setup(); # ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ # ┃ Verify “is-enabled” is not true for a random, non-existing unit file. ┃ @@ -91,7 +45,7 @@ # ┃ Verify “enable” creates the requested symlinks. ┃ # ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh enable $random_unit"); +my $retval = dsh('enable', $random_unit); my $symlink_path = "/etc/systemd/system/multi-user.target.wants/$random_unit"; ok(-l $symlink_path, "$random_unit was enabled"); is(readlink($symlink_path), $servicefile_path, @@ -117,7 +71,7 @@ # ┃ Verify “was-enabled” is still true (operates on the state file). ┃ # ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh was-enabled $random_unit"); +$retval = dsh('was-enabled', $random_unit); isnt($retval, -1, 'deb-systemd-helper could be executed'); ok(!($retval & 127), 'deb-systemd-helper did not exit due to a signal'); is($retval >> 8, 0, "random unit file was-enabled"); @@ -138,7 +92,7 @@ my $new_symlink_path = '/etc/systemd/system/newalias.service'; ok(! -l $new_symlink_path, 'new symlink does not exist yet'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh enable $random_unit"); +$retval = dsh('enable', $random_unit); ok(-l $new_symlink_path, 'new symlink was created'); is(readlink($new_symlink_path), $servicefile_path, "symlink points to $servicefile_path"); @@ -168,7 +122,7 @@ # ┃ Verify “was-enabled” is still true (operates on the state file). ┃ # ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh was-enabled $random_unit"); +$retval = dsh('was-enabled', $random_unit); isnt($retval, -1, 'deb-systemd-helper could be executed'); ok(!($retval & 127), 'deb-systemd-helper did not exit due to a signal'); is($retval >> 8, 0, "random unit file was-enabled"); @@ -190,7 +144,7 @@ my $new_symlink_path2 = '/etc/systemd/system/another.service'; ok(! -l $new_symlink_path2, 'new symlink does not exist yet'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh update-state $random_unit"); +$retval = dsh('update-state', $random_unit); ok(! -l $new_symlink_path2, 'new symlink still does not exist'); isnt_enabled($random_unit); @@ -223,7 +177,7 @@ ok(! -l $new_symlink_path, 'new symlink still does not exist'); ok(! -l $new_symlink_path2, 'new symlink 2 still does not exist'); -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh update-state $random_unit"); +$retval = dsh('update-state', $random_unit); ok(! -l $new_symlink_path, 'new symlink still does not exist'); ok(! -l $new_symlink_path2, 'new symlink 2 still does not exist'); diff -Nru init-system-helpers-1.51/t/003-deb-systemd-helper-complex.t init-system-helpers-1.54/t/003-deb-systemd-helper-complex.t --- init-system-helpers-1.51/t/003-deb-systemd-helper-complex.t 2017-10-25 15:38:42.000000000 +0000 +++ init-system-helpers-1.54/t/003-deb-systemd-helper-complex.t 2018-08-17 13:33:08.000000000 +0000 @@ -8,47 +8,11 @@ use File::Path qw(make_path); # in core since Perl 5.001 use File::Basename; # in core since Perl 5 use FindBin; # in core since Perl 5.00307 -use Linux::Clone; # neither in core nor in Debian :-/ -# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ SETUP: in a new mount namespace, bindmount tmpdirs on /etc/systemd and ┃ -# ┃ /var/lib/systemd to start with clean directories yet use the actual ┃ -# ┃ locations and code paths. ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - -my $dsh = "$FindBin::Bin/../script/deb-systemd-helper"; - -sub _unit_check { - my ($unit_file, $cmd, $cb, $verb) = @_; - - my $retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh $cmd $unit_file"); - isnt($retval, -1, 'deb-systemd-helper could be executed'); - ok(!($retval & 127), 'deb-systemd-helper did not exit due to a signal'); - $cb->($retval >> 8, 0, "random unit file $unit_file $verb $cmd"); -} - -sub is_enabled { _unit_check($_[0], 'is-enabled', \&is, 'is') } -sub isnt_enabled { _unit_check($_[0], 'is-enabled', \&isnt, 'isnt') } +use lib "$FindBin::Bin/."; +use helpers; -sub is_debian_installed { _unit_check($_[0], 'debian-installed', \&is, 'is') } -sub isnt_debian_installed { _unit_check($_[0], 'debian-installed', \&isnt, 'isnt') } - -my $retval = Linux::Clone::unshare Linux::Clone::NEWNS; -BAIL_OUT("Cannot unshare(NEWNS): $!") if $retval != 0; - -sub bind_mount_tmp { - my ($dir) = @_; - my $tmp = tempdir(CLEANUP => 1); - system("mount -n --bind $tmp $dir") == 0 - or BAIL_OUT("bind-mounting $tmp to $dir failed: $!"); - return $tmp; -} - -unless ($ENV{'TEST_ON_REAL_SYSTEM'}) { - my $etc_systemd = bind_mount_tmp('/etc/systemd'); - my $lib_systemd = bind_mount_tmp('/lib/systemd'); - my $var_lib_systemd = bind_mount_tmp('/var/lib/systemd'); -} +test_setup(); # ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ # ┃ Create two unit files with random names; one refers to the other (Also=). ┃ @@ -114,7 +78,7 @@ 'multi-user.target.wants does not exist yet'); } -$retval = system("DPKG_MAINTSCRIPT_PACKAGE=test $dsh enable $random_unit1"); +my $retval = dsh('enable', $random_unit1); my %links = map { (basename($_), readlink($_)) } ("/etc/systemd/system/multi-user.target.wants/$random_unit1", "/etc/systemd/system/multi-user.target.wants/$random_unit2"); diff -Nru init-system-helpers-1.51/t/004-deb-systemd-helper-user.t init-system-helpers-1.54/t/004-deb-systemd-helper-user.t --- init-system-helpers-1.51/t/004-deb-systemd-helper-user.t 1970-01-01 00:00:00.000000000 +0000 +++ init-system-helpers-1.54/t/004-deb-systemd-helper-user.t 2018-08-17 13:33:08.000000000 +0000 @@ -0,0 +1,411 @@ +#!perl +# vim:ts=4:sw=4:et + +use strict; +use warnings; +use Test::More; +use File::Temp qw(tempfile tempdir); # in core since perl 5.6.1 +use File::Path qw(make_path); # in core since Perl 5.001 +use File::Basename; # in core since Perl 5 +use FindBin; # in core since Perl 5.00307 + +use lib "$FindBin::Bin/."; +use helpers; + +test_setup(); + +# +# "is-enabled" is not true for a random, non-existing unit file +# + +my ($fh, $random_unit) = tempfile('unit\x2dXXXXX', + SUFFIX => '.service', + TMPDIR => 1, + UNLINK => 1); +close($fh); +$random_unit = basename($random_unit); + +isnt_enabled($random_unit); +isnt_enabled($random_unit, user => 1); +isnt_debian_installed($random_unit); +isnt_debian_installed($random_unit, user => 1); + +# +# "is-enabled" is not true for a random, existing user unit file +# + +my $servicefile_path = "/usr/lib/systemd/user/$random_unit"; +make_path('/usr/lib/systemd/user'); +open($fh, '>', $servicefile_path); +print $fh <<'EOT'; +[Unit] +Description=test unit + +[Service] +ExecStart=/bin/sleep 1 + +[Install] +WantedBy=default.target +EOT +close($fh); + +isnt_enabled($random_unit); +isnt_enabled($random_unit, user => 1); +isnt_debian_installed($random_unit); +isnt_debian_installed($random_unit, user => 1); + +# +# "enable" creates the requested symlinks +# + +unless ($ENV{'TEST_ON_REAL_SYSTEM'}) { + # This might exist if we don't start from a fresh directory + ok(! -d '/etc/systemd/user/default.target.wants', + 'default.target.wants does not exist yet'); +} + +my $retval = dsh('--user', 'enable', $random_unit); +is($retval, 0, "enable command succeeded"); +my $symlink_path = "/etc/systemd/user/default.target.wants/$random_unit"; +ok(-l $symlink_path, "$random_unit was enabled"); +is(readlink($symlink_path), $servicefile_path, + "symlink points to $servicefile_path"); + +# +# "is-enabled" now returns true for the user instance +# + +isnt_enabled($random_unit); +isnt_debian_installed($random_unit); +is_enabled($random_unit, user => 1); +is_debian_installed($random_unit, user => 1); + +# +# deleting the symlinks and running "enable" again does not re-create them +# + +unlink($symlink_path); +ok(! -l $symlink_path, 'symlink deleted'); +isnt_enabled($random_unit); +isnt_enabled($random_unit, user => 1); +isnt_debian_installed($random_unit); +is_debian_installed($random_unit, user => 1); + +$retval = dsh('--user', 'enable', $random_unit); +is($retval, 0, "enable command succeeded"); + +isnt_enabled($random_unit, user => 1); + +# +# "disable" deletes the statefile when purging +# + +my $statefile = "/var/lib/systemd/deb-systemd-user-helper-enabled/$random_unit.dsh-also"; + +ok(-f $statefile, 'state file exists'); + +$ENV{'_DEB_SYSTEMD_HELPER_PURGE'} = '1'; +$retval = dsh('--user', 'disable', $random_unit); +delete $ENV{'_DEB_SYSTEMD_HELPER_PURGE'}; +is($retval, 0, "disable command succeeded"); +ok(! -f $statefile, 'state file does not exist anymore after purging'); +isnt_debian_installed($random_unit); +isnt_debian_installed($random_unit, user => 1); + +# +# "enable" re-creates the symlinks after purging +# + +ok(! -l $symlink_path, 'symlink does not exist yet'); +isnt_enabled($random_unit); +isnt_enabled($random_unit, user => 1); + +$retval = dsh('--user', 'enable', $random_unit); +is($retval, 0, "enable command succeeded"); + +isnt_enabled($random_unit); +isnt_debian_installed($random_unit); +is_enabled($random_unit, user => 1); +is_debian_installed($random_unit, user => 1); + +# +# "disable" removes the symlinks +# + +$ENV{'_DEB_SYSTEMD_HELPER_PURGE'} = '1'; +$retval = dsh('--user', 'disable', $random_unit); +delete $ENV{'_DEB_SYSTEMD_HELPER_PURGE'}; +is($retval, 0, "disable command succeeded"); + +isnt_enabled($random_unit); +isnt_enabled($random_unit, user => 1); + +# +# "enable" re-creates the symlinks +# + +ok(! -l $symlink_path, 'symlink does not exist yet'); +isnt_enabled($random_unit); +isnt_enabled($random_unit, user => 1); + +$retval = dsh('--user', 'enable', $random_unit); +is($retval, 0, "enable command succeeded"); + +isnt_enabled($random_unit); +isnt_debian_installed($random_unit); +is_enabled($random_unit, user => 1); +is_debian_installed($random_unit, user => 1); + +# +# "purge" works +# + +$retval = dsh('--user', 'purge', $random_unit); +is($retval, 0, "purge command succeeded"); + +isnt_enabled($random_unit, user => 1); +isnt_debian_installed($random_unit, user => 1); + +# +# "enable" re-creates the symlinks after purging +# + +ok(! -l $symlink_path, 'symlink does not exist yet'); +isnt_enabled($random_unit, user => 1); + +$retval = dsh('--user', 'enable', $random_unit); +is($retval, 0, "enable command succeeded"); + +is_enabled($random_unit, user => 1); +is_debian_installed($random_unit, user => 1); + +# +# "mask" (when enabled) results in the symlink pointing to /dev/null +# + +my $mask_path = "/etc/systemd/user/$random_unit"; +ok(! -l $mask_path, 'mask link does not exist yet'); + +$retval = dsh('--user', 'mask', $random_unit); +is($retval, 0, "mask command succeeded"); +ok(-l $mask_path, 'mask link exists'); +is(readlink($mask_path), '/dev/null', 'service masked'); + +$retval = dsh('--user', 'unmask', $random_unit); +is($retval, 0, "unmask command succeeded"); +ok(! -e $mask_path, 'mask link does not exist anymore'); + +# +# "mask" (when disabled) works the same way +# + +$retval = dsh('--user', 'disable', $random_unit); +is($retval, 0, "disable command succeeded"); +ok(! -e $symlink_path, 'symlink no longer exists'); + +$retval = dsh('--user', 'mask', $random_unit); +is($retval, 0, "mask command succeeded"); +ok(-l $mask_path, 'mask link exists'); +is(readlink($mask_path), '/dev/null', 'service masked'); + +$retval = dsh('--user', 'unmask', $random_unit); +is($retval, 0, "unmask command succeeded"); +ok(! -e $mask_path, 'symlink no longer exists'); + +# +# "mask" / "unmask" don't do anything when the unit is already masked +# + +ok(! -l $mask_path, 'mask link does not exist yet'); +symlink('/dev/null', $mask_path); +ok(-l $mask_path, 'mask link exists'); +is(readlink($mask_path), '/dev/null', 'service masked'); + +$retval = dsh('--user', 'mask', $random_unit); +is($retval, 0, "mask command succeeded"); +ok(-l $mask_path, 'mask link exists'); +is(readlink($mask_path), '/dev/null', 'service still masked'); + +$retval = dsh('--user', 'unmask', $random_unit); +is($retval, 0, "unmask command succeeded"); +ok(-l $mask_path, 'mask link exists'); +is(readlink($mask_path), '/dev/null', 'service still masked'); + +# +# "mask" / "unmask" don't do anything when the user copied the .service. +# + +unlink($mask_path); + +open($fh, '>', $mask_path); +print $fh <<'EOT'; +[Unit] +Description=test unit + +[Service] +ExecStart=/bin/sleep 1 + +[Install] +WantedBy=default.target +EOT +close($fh); + +ok(-e $mask_path, 'local service file exists'); +ok(! -l $mask_path, 'local service file is not a symlink'); + +$retval = dsh('--user', 'mask', $random_unit); +isnt($retval, -1, 'deb-systemd-helper could be executed'); +ok(!($retval & 127), 'deb-systemd-helper did not exit due to a signal'); +is($retval >> 8, 0, 'deb-systemd-helper exited with exit code 0'); +ok(-e $mask_path, 'local service file still exists'); +ok(! -l $mask_path, 'local service file is still not a symlink'); + +$retval = dsh('--user', 'unmask', $random_unit); +isnt($retval, -1, 'deb-systemd-helper could be executed'); +ok(!($retval & 127), 'deb-systemd-helper did not exit due to a signal'); +is($retval >> 8, 0, 'deb-systemd-helper exited with exit code 0'); +ok(-e $mask_path, 'local service file still exists'); +ok(! -l $mask_path, 'local service file is still not a symlink'); + +unlink($mask_path); + +# +# "Alias=" handling +# + +$retval = dsh('--user', 'purge', $random_unit); +is($retval, 0, "purge command succeeded"); + +open($fh, '>', $servicefile_path); +print $fh <<'EOT'; +[Unit] +Description=test unit + +[Service] +ExecStart=/bin/sleep 1 + +[Install] +WantedBy=default.target +Alias=foo\x2dtest.service +EOT +close($fh); + +isnt_enabled($random_unit, user => 1); +isnt_enabled('foo\x2dtest.service', user => 1); +my $alias_path = '/etc/systemd/user/foo\x2dtest.service'; +ok(! -l $alias_path, 'alias link does not exist yet'); +$retval = dsh('--user', 'enable', $random_unit); +is($retval, 0, "enable command succeeded"); +is(readlink($alias_path), $servicefile_path, 'correct alias link'); +is_enabled($random_unit, user => 1); +ok(! -l $mask_path, 'mask link does not exist yet'); + +$retval = dsh('--user', 'mask', $random_unit); +is($retval, 0, "mask command succeeded"); +is(readlink($alias_path), $servicefile_path, 'correct alias link'); +is(readlink($mask_path), '/dev/null', 'service masked'); + +$retval = dsh('--user', 'unmask', $random_unit); +is($retval, 0, "unmask command succeeded"); +is(readlink($alias_path), $servicefile_path, 'correct alias link'); +ok(! -l $mask_path, 'mask link does not exist any more'); + +$retval = dsh('--user', 'disable', $random_unit); +isnt_enabled($random_unit, user => 1); +ok(! -l $alias_path, 'alias link does not exist any more'); + +# +# "Alias=" / "mask" with removed package (as in postrm) +# + +$retval = dsh('--user', 'purge', $random_unit); +is($retval, 0, "purge command succeeded"); +$retval = dsh('--user', 'enable', $random_unit); +is($retval, 0, "enable command succeeded"); +is(readlink($alias_path), $servicefile_path, 'correct alias link'); + +unlink($servicefile_path); + +$retval = dsh('--user', 'mask', $random_unit); +is($retval, 0, "mask command succeeded with uninstalled unit"); +is(readlink($alias_path), $servicefile_path, 'correct alias link'); +is(readlink($mask_path), '/dev/null', 'service masked'); + +$retval = dsh('--user', 'purge', $random_unit); +is($retval, 0, "purge command succeeded with uninstalled unit"); +ok(! -l $alias_path, 'alias link does not exist any more'); +is(readlink($mask_path), '/dev/null', 'service masked'); + +$retval = dsh('--user', 'unmask', $random_unit); +is($retval, 0, "unmask command succeeded with uninstalled unit"); +ok(! -l $mask_path, 'mask link does not exist any more'); + +# +# "Alias=" to the same unit name +# + +open($fh, '>', $servicefile_path); +print $fh <<"EOT"; +[Unit] +Description=test unit + +[Service] +ExecStart=/bin/sleep 1 + +[Install] +WantedBy=default.target +Alias=$random_unit +EOT +close($fh); + +isnt_enabled($random_unit, user => 1); +isnt_enabled('foo\x2dtest.service', user => 1); +# note that in this case $alias_path and $mask_path are identical +$retval = dsh('--user', 'enable', $random_unit); +is($retval, 0, "enable command succeeded"); +is_enabled($random_unit, user => 1); +# systemctl enable does create the alias link even if it's not needed +#ok(! -l $mask_path, 'mask link does not exist yet'); + +unlink($servicefile_path); + +$retval = dsh('--user', 'mask', $random_unit); +is($retval, 0, "mask command succeeded"); +is(readlink($mask_path), '/dev/null', 'service masked'); + +$retval = dsh('--user', 'unmask', $random_unit); +is($retval, 0, "unmask command succeeded"); +ok(! -l $mask_path, 'mask link does not exist any more'); + +$retval = dsh('--user', 'purge', $random_unit); +isnt_enabled($random_unit, user => 1); +ok(! -l $mask_path, 'mask link does not exist any more'); + +# +# "Alias=" without "WantedBy=" +# + +open($fh, '>', $servicefile_path); +print $fh <<'EOT'; +[Unit] +Description=test unit + +[Service] +ExecStart=/bin/sleep 1 + +[Install] +Alias=baz\x2dtest.service +EOT +close($fh); + +isnt_enabled($random_unit, user => 1); +isnt_enabled('baz\x2dtest.service', user => 1); +$alias_path = '/etc/systemd/user/baz\x2dtest.service'; +ok(! -l $alias_path, 'alias link does not exist yet'); +$retval = dsh('--user', 'enable', $random_unit); +is($retval, 0, "enable command succeeded"); +is_enabled($random_unit, user => 1); +ok(-l $alias_path, 'alias link does exist'); +is(readlink($alias_path), $servicefile_path, 'correct alias link'); + +done_testing; diff -Nru init-system-helpers-1.51/t/helpers.pm init-system-helpers-1.54/t/helpers.pm --- init-system-helpers-1.51/t/helpers.pm 1970-01-01 00:00:00.000000000 +0000 +++ init-system-helpers-1.54/t/helpers.pm 2018-08-17 13:33:08.000000000 +0000 @@ -0,0 +1,88 @@ +use File::Temp qw(tempdir); # in core since perl 5.6.1 +use if !$ENV{'TEST_ON_REAL_SYSTEM'}, "Linux::Clone"; # neither in core nor in Debian :-/ + +sub bind_mount_tmp { + my ($dir) = @_; + my $tmp = tempdir(CLEANUP => 1); + system("mount -n --bind $tmp $dir") == 0 + or BAIL_OUT("bind-mounting $tmp to $dir failed: $!"); + return $tmp; +} + +# In a new mount namespace, bindmount tmpdirs on /etc/systemd, +# /lib/systemd/system, and /var/lib/systemd to start with clean state +# yet use the actual locations and code paths. The test harnesses use +# systemctl which is linked to /lib/systemd/libsystemd-shared-$ver.so, +# thus do not bindmount a tmpdir on /lib/systemd. +sub test_setup() { + unless ($ENV{'TEST_ON_REAL_SYSTEM'}) { + open(my $fh, '<', "/proc/$$/mountinfo") + or BAIL_OUT("Cannot open(/proc/$$/mountinfo): $!"); + + # Check that the root filesystem has been made private. + @shared = grep { /shared:\d+/ } grep { /^\d+ \d+ \d+:\d+ \/ \/ / } <$fh>; + BAIL_OUT("Root filesystem not marked as a private subtree. " . + "Execute 'mount --make-private /'") if @shared; + + close($fh); + + my $retval = Linux::Clone::unshare Linux::Clone::NEWNS; + BAIL_OUT("Cannot unshare(NEWNS): $!") if $retval != 0; + + # Make sure that the tests do not clutter the system by + # remounting the root filesystem read-only. + system("mount -n -o bind,ro / /") == 0 + or BAIL_OUT("bind-mounting / read-only failed: $!"); + + # We still need to be able to create temporary files and + # directories: mount a tmpfs on /tmp. + system("mount -n -t tmpfs tmpfs /tmp") == 0 + or BAIL_OUT("mounting tmpfs on /tmp failed: $!"); + + my $etc_systemd = bind_mount_tmp('/etc/systemd'); + my $lib_systemd_system = bind_mount_tmp('/lib/systemd/system'); + my $lib_systemd_user = bind_mount_tmp('/usr/lib/systemd/user'); + my $var_lib_systemd = bind_mount_tmp('/var/lib/systemd'); + + # Tell `systemctl` to do not speak with the world outside our namespace. + $ENV{'SYSTEMCTL_INSTALL_CLIENT_SIDE'} = '1' + } +} + +# reads in a whole file +sub slurp { + open my $fh, '<', shift; + local $/; + <$fh>; +} + +sub state_file_entries { + my ($path) = @_; + my $bytes = slurp($path); + return split("\n", $bytes); +} + +my $dsh = "$FindBin::Bin/../script/deb-systemd-helper"; +$ENV{'DPKG_MAINTSCRIPT_PACKAGE'} = 'deb-systemd-helper-test'; + +sub dsh { + return system($dsh, @_); +} + +sub _unit_check { + my ($cmd, $cb, $verb, $unit, %opts) = @_; + + my $retval = dsh($opts{'user'} ? '--user' : '--system', $cmd, $unit); + + isnt($retval, -1, 'deb-systemd-helper could be executed'); + ok(!($retval & 127), 'deb-systemd-helper did not exit due to a signal'); + $cb->($retval >> 8, 0, "random unit file '$unit' $verb $cmd"); +} + +sub is_enabled { _unit_check('is-enabled', \&is, 'is', @_) } +sub isnt_enabled { _unit_check('is-enabled', \&isnt, 'isnt', @_) } + +sub is_debian_installed { _unit_check('debian-installed', \&is, 'is', @_) } +sub isnt_debian_installed { _unit_check('debian-installed', \&isnt, 'isnt', @_) } + +1;