Package: init-system-helpers Version: 1.29 Systemd unit names can have valid \ escape characters. See systemd-escape(1) for examples. When a unit references a another unit with escaped characters, init-system-helpers handles them incorrectly. For example, a unit file having WantedBy=foo\x2dbar.target will have an /etc/systemd/system/foox2dbar.target.wants directory created without the x escaped by \.
The attached patch fixes this. -- Dan Nicholson | +1.206.437.0833 | Endless
From 4d2c003bd4f7739d1d075e7f7e067292030e47ce Mon Sep 17 00:00:00 2001 From: Dan Nicholson <nichol...@endlessm.com> Date: Thu, 7 Apr 2016 11:08:23 -0700 Subject: [PATCH] script: Handle \ escapes in unit names properly Unit names can contain valid \ escapes in systemd. See systemd-escape(1) for examples. Text::ParseWords::shellwords breaks that since it strips \ in addition to quotes. Use quotewords directly with keep set and strip the leading/trailing quotes as necessary. --- debian/changelog | 7 +++++++ script/deb-systemd-helper | 14 ++++++++++---- script/dh_systemd_enable | 1 - script/dh_systemd_start | 10 ++++++++-- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/debian/changelog b/debian/changelog index e5e0ce5..bd16993 100644 --- a/debian/changelog +++ b/debian/changelog @@ -11,6 +11,13 @@ init-system-helpers (1.30) UNRELEASED; urgency=medium * dh_systemd_*: Add DH promise to avoid being called for no reason. * Update Vcs-* fields to use https. + [ Dan Nicholson ] + * deb-systemd-helper, dh_systemd_start: Use Text::ParseWords::quotewords + rather than shellwords since the latter will strip valid \ escapes + from unit names. The returned values then need to have leading and + trailing quotes stripped. + * dh_systemd_enable: Drop unused Text::ParseWords use. + -- Felipe Sateler <fsate...@debian.org> Fri, 11 Mar 2016 18:48:39 -0300 init-system-helpers (1.29) unstable; urgency=medium diff --git a/script/deb-systemd-helper b/script/deb-systemd-helper index 2a87cb4..dc10b0c 100755 --- a/script/deb-systemd-helper +++ b/script/deb-systemd-helper @@ -85,7 +85,7 @@ use warnings; use File::Path qw(make_path); # in core since Perl 5.001 use File::Basename; # in core since Perl 5 use File::Temp qw(tempfile); # in core since Perl 5.6.1 -use Text::ParseWords qw(shellwords); # in core since Perl 5 +use Text::ParseWords qw(quotewords); # in core since Perl 5 use Getopt::Long; # in core since Perl 5 # Make Data::Dumper::Dumper available if present (not present on systems that # only have perl-base, not perl). @@ -183,13 +183,17 @@ sub get_link_closure { my $unit_name = basename($service_path); + # Use quotewords to split, but keep characters and remove + # leading/trailing quotes since \ is valid in systemd unit names. + # See systemd-escape(1). open my $fh, '<', $service_path or error("unable to read $service_path"); while (my $line = <$fh>) { chomp($line); my $service_link; if ($line =~ /^\s*(WantedBy|RequiredBy)=(.+)$/i) { - for my $value (shellwords($2)) { + for my $value (quotewords('\s+', 1, $2)) { + $value =~ s/^(["'])(.*)\g1$/$2/; my $wants_dir = "/etc/systemd/system/$value"; $wants_dir .= '.wants' if $1 eq 'WantedBy'; $wants_dir .= '.requires' if $1 eq 'RequiredBy'; @@ -198,7 +202,8 @@ sub get_link_closure { } if ($line =~ /^\s*Also=(.+)$/i) { - for my $value (shellwords($1)) { + for my $value (quotewords('\s+', 1, $1)) { + $value =~ s/^(["'])(.*)\g1$/$2/; if ($value ne $unit_name) { push @links, get_link_closure($value, find_unit($value)); } @@ -206,7 +211,8 @@ sub get_link_closure { } if ($line =~ /^\s*Alias=(.+)$/i) { - for my $value (shellwords($1)) { + for my $value (quotewords('\s+', 1, $1)) { + $value =~ s/^(["'])(.*)\g1$/$2/; if ($value ne $unit_name) { push @links, { dest => $service_path, src => "/etc/systemd/system/$1" }; } diff --git a/script/dh_systemd_enable b/script/dh_systemd_enable index 39955c4..a45615b 100755 --- a/script/dh_systemd_enable +++ b/script/dh_systemd_enable @@ -9,7 +9,6 @@ dh_systemd_enable - enable/disable systemd unit files use strict; use Debian::Debhelper::Dh_Lib; use File::Find; -use Text::ParseWords qw(shellwords); # in core since Perl 5 =head1 SYNOPSIS diff --git a/script/dh_systemd_start b/script/dh_systemd_start index 4e22d59..8b14d8e 100755 --- a/script/dh_systemd_start +++ b/script/dh_systemd_start @@ -9,7 +9,7 @@ dh_systemd_start - start/stop/restart systemd unit files use strict; use Debian::Debhelper::Dh_Lib; use File::Find; -use Text::ParseWords qw(shellwords); # in core since Perl 5 +use Text::ParseWords qw(quotewords); # in core since Perl 5 use Cwd qw(getcwd abs_path); =head1 SYNOPSIS @@ -107,8 +107,14 @@ sub extract_key { while (my $line = <$fh>) { chomp($line); + # Use quotewords to split, but keep characters and + # remove leading/trailing quotes since \ is valid in + # systemd unit names. See systemd-escape(1). if ($line =~ /^\s*$key=(.+)$/i) { - @values = (@values, shellwords($1)); + for my $value (quotewords('\s+', 1, $1)) { + $value =~ s/^(["'])(.*)\g1$/$2/; + push @values, $value; + } } } close($fh); -- 2.5.5