kde-apps/ksirk: x86 stable (bug #661810)
[gentoo.git] / eclass / systemd.eclass
1 # Copyright 1999-2017 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3
4 # @ECLASS: systemd.eclass
5 # @MAINTAINER:
6 # systemd@gentoo.org
7 # @BLURB: helper functions to install systemd units
8 # @DESCRIPTION:
9 # This eclass provides a set of functions to install unit files for
10 # sys-apps/systemd within ebuilds.
11 # @EXAMPLE:
12 #
13 # @CODE
14 # inherit systemd
15 #
16 # src_configure() {
17 #       local myconf=(
18 #               --enable-foo
19 #               --with-systemdsystemunitdir="$(systemd_get_systemunitdir)"
20 #       )
21 #
22 #       econf "${myconf[@]}"
23 # }
24 # @CODE
25
26 inherit toolchain-funcs
27
28 case ${EAPI:-0} in
29         0|1|2|3|4|5|6) ;;
30         *) die "${ECLASS}.eclass API in EAPI ${EAPI} not yet established."
31 esac
32
33 DEPEND="virtual/pkgconfig"
34
35 # @FUNCTION: _systemd_get_dir
36 # @USAGE: <variable-name> <fallback-directory>
37 # @INTERNAL
38 # @DESCRIPTION:
39 # Try to obtain the <variable-name> variable from systemd.pc.
40 # If pkg-config or systemd is not installed, return <fallback-directory>
41 # instead.
42 _systemd_get_dir() {
43         [[ ${#} -eq 2 ]] || die "Usage: ${FUNCNAME} <variable-name> <fallback-directory>"
44         local variable=${1} fallback=${2} d
45
46         if $(tc-getPKG_CONFIG) --exists systemd; then
47                 d=$($(tc-getPKG_CONFIG) --variable="${variable}" systemd) || die
48                 d=${d#${EPREFIX}}
49         else
50                 d=${fallback}
51         fi
52
53         echo "${d}"
54 }
55
56 # @FUNCTION: _systemd_get_unitdir
57 # @INTERNAL
58 # @DESCRIPTION:
59 # Get unprefixed unitdir.
60 _systemd_get_systemunitdir() {
61         _systemd_get_dir systemdsystemunitdir /lib/systemd/system
62 }
63
64 # @FUNCTION: systemd_get_systemunitdir
65 # @DESCRIPTION:
66 # Output the path for the systemd system unit directory (not including
67 # ${D}).  This function always succeeds, even if systemd is not
68 # installed.
69 systemd_get_systemunitdir() {
70         has "${EAPI:-0}" 0 1 2 && ! use prefix && EPREFIX=
71         debug-print-function ${FUNCNAME} "${@}"
72
73         echo "${EPREFIX}$(_systemd_get_systemunitdir)"
74 }
75
76 # @FUNCTION: systemd_get_unitdir
77 # @DESCRIPTION:
78 # Deprecated alias for systemd_get_systemunitdir.
79 systemd_get_unitdir() {
80         [[ ${EAPI} == [012345] ]] || die "${FUNCNAME} is banned in EAPI 6, use systemd_get_systemunitdir instead"
81
82         systemd_get_systemunitdir
83 }
84
85 # @FUNCTION: _systemd_get_userunitdir
86 # @INTERNAL
87 # @DESCRIPTION:
88 # Get unprefixed userunitdir.
89 _systemd_get_userunitdir() {
90         _systemd_get_dir systemduserunitdir /usr/lib/systemd/user
91 }
92
93 # @FUNCTION: systemd_get_userunitdir
94 # @DESCRIPTION:
95 # Output the path for the systemd user unit directory (not including
96 # ${D}). This function always succeeds, even if systemd is not
97 # installed.
98 systemd_get_userunitdir() {
99         has "${EAPI:-0}" 0 1 2 && ! use prefix && EPREFIX=
100         debug-print-function ${FUNCNAME} "${@}"
101
102         echo "${EPREFIX}$(_systemd_get_userunitdir)"
103 }
104
105 # @FUNCTION: _systemd_get_utildir
106 # @INTERNAL
107 # @DESCRIPTION:
108 # Get unprefixed utildir.
109 _systemd_get_utildir() {
110         _systemd_get_dir systemdutildir /lib/systemd
111 }
112
113 # @FUNCTION: systemd_get_utildir
114 # @DESCRIPTION:
115 # Output the path for the systemd utility directory (not including
116 # ${D}). This function always succeeds, even if systemd is not
117 # installed.
118 systemd_get_utildir() {
119         has "${EAPI:-0}" 0 1 2 && ! use prefix && EPREFIX=
120         debug-print-function ${FUNCNAME} "${@}"
121
122         echo "${EPREFIX}$(_systemd_get_utildir)"
123 }
124
125 # @FUNCTION: _systemd_get_systemgeneratordir
126 # @INTERNAL
127 # @DESCRIPTION:
128 # Get unprefixed systemgeneratordir.
129 _systemd_get_systemgeneratordir() {
130         _systemd_get_dir systemdsystemgeneratordir /lib/systemd/system-generators
131 }
132
133 # @FUNCTION: systemd_get_systemgeneratordir
134 # @DESCRIPTION:
135 # Output the path for the systemd system generator directory (not including
136 # ${D}). This function always succeeds, even if systemd is not
137 # installed.
138 systemd_get_systemgeneratordir() {
139         has "${EAPI:-0}" 0 1 2 && ! use prefix && EPREFIX=
140         debug-print-function ${FUNCNAME} "${@}"
141
142         echo "${EPREFIX}$(_systemd_get_systemgeneratordir)"
143 }
144
145 # @FUNCTION: systemd_dounit
146 # @USAGE: <unit>...
147 # @DESCRIPTION:
148 # Install systemd unit(s). Uses doins, thus it is fatal in EAPI 4
149 # and non-fatal in earlier EAPIs.
150 systemd_dounit() {
151         debug-print-function ${FUNCNAME} "${@}"
152
153         (
154                 insopts -m 0644
155                 insinto "$(_systemd_get_systemunitdir)"
156                 doins "${@}"
157         )
158 }
159
160 # @FUNCTION: systemd_newunit
161 # @USAGE: <old-name> <new-name>
162 # @DESCRIPTION:
163 # Install systemd unit with a new name. Uses newins, thus it is fatal
164 # in EAPI 4 and non-fatal in earlier EAPIs.
165 systemd_newunit() {
166         debug-print-function ${FUNCNAME} "${@}"
167
168         (
169                 insopts -m 0644
170                 insinto "$(_systemd_get_systemunitdir)"
171                 newins "${@}"
172         )
173 }
174
175 # @FUNCTION: systemd_douserunit
176 # @USAGE: <unit>...
177 # @DESCRIPTION:
178 # Install systemd user unit(s). Uses doins, thus it is fatal in EAPI 4
179 # and non-fatal in earlier EAPIs.
180 systemd_douserunit() {
181         debug-print-function ${FUNCNAME} "${@}"
182
183         (
184                 insopts -m 0644
185                 insinto "$(_systemd_get_userunitdir)"
186                 doins "${@}"
187         )
188 }
189
190 # @FUNCTION: systemd_newuserunit
191 # @USAGE: <old-name> <new-name>
192 # @DESCRIPTION:
193 # Install systemd user unit with a new name. Uses newins, thus it
194 # is fatal in EAPI 4 and non-fatal in earlier EAPIs.
195 systemd_newuserunit() {
196         debug-print-function ${FUNCNAME} "${@}"
197
198         (
199                 insopts -m 0644
200                 insinto "$(_systemd_get_userunitdir)"
201                 newins "${@}"
202         )
203 }
204
205 # @FUNCTION: systemd_install_serviced
206 # @USAGE: <conf-file> [<service>]
207 # @DESCRIPTION:
208 # Install <conf-file> as the template <service>.d/00gentoo.conf.
209 # If <service> is not specified
210 # <conf-file> with the .conf suffix stripped is used
211 # (e.g. foo.service.conf -> foo.service.d/00gentoo.conf).
212 systemd_install_serviced() {
213         debug-print-function ${FUNCNAME} "${@}"
214
215         local src=${1}
216         local service=${2}
217
218         [[ ${src} ]] || die "No file specified"
219
220         if [[ ! ${service} ]]; then
221                 [[ ${src} == *.conf ]] || die "Source file needs .conf suffix"
222                 service=${src##*/}
223                 service=${service%.conf}
224         fi
225         # avoid potentially common mistake
226         [[ ${service} == *.d ]] && die "Service must not have .d suffix"
227
228         (
229                 insopts -m 0644
230                 insinto /etc/systemd/system/"${service}".d
231                 newins "${src}" 00gentoo.conf
232         )
233 }
234
235 # @FUNCTION: systemd_dotmpfilesd
236 # @USAGE: <tmpfilesd>...
237 # @DESCRIPTION:
238 # Install systemd tmpfiles.d files. Uses doins, thus it is fatal
239 # in EAPI 4 and non-fatal in earlier EAPIs.
240 systemd_dotmpfilesd() {
241         debug-print-function ${FUNCNAME} "${@}"
242
243         for f; do
244                 [[ ${f} == *.conf ]] \
245                         || die 'tmpfiles.d files need to have .conf suffix.'
246         done
247
248         (
249                 insopts -m 0644
250                 insinto /usr/lib/tmpfiles.d/
251                 doins "${@}"
252         )
253 }
254
255 # @FUNCTION: systemd_newtmpfilesd
256 # @USAGE: <old-name> <new-name>.conf
257 # @DESCRIPTION:
258 # Install systemd tmpfiles.d file under a new name. Uses newins, thus it
259 # is fatal in EAPI 4 and non-fatal in earlier EAPIs.
260 systemd_newtmpfilesd() {
261         debug-print-function ${FUNCNAME} "${@}"
262
263         [[ ${2} == *.conf ]] \
264                 || die 'tmpfiles.d files need to have .conf suffix.'
265
266         (
267                 insopts -m 0644
268                 insinto /usr/lib/tmpfiles.d/
269                 newins "${@}"
270         )
271 }
272
273 # @FUNCTION: systemd_enable_service
274 # @USAGE: <target> <service>
275 # @DESCRIPTION:
276 # Enable service in desired target, e.g. install a symlink for it.
277 # Uses dosym, thus it is fatal in EAPI 4 and non-fatal in earlier
278 # EAPIs.
279 systemd_enable_service() {
280         debug-print-function ${FUNCNAME} "${@}"
281
282         [[ ${#} -eq 2 ]] || die "Synopsis: systemd_enable_service target service"
283
284         local target=${1}
285         local service=${2}
286         local ud=$(_systemd_get_systemunitdir)
287         local destname=${service##*/}
288
289         dodir "${ud}"/"${target}".wants && \
290         dosym ../"${service}" "${ud}"/"${target}".wants/"${destname}"
291 }
292
293 # @FUNCTION: systemd_enable_ntpunit
294 # @USAGE: <NN-name> <service>...
295 # @DESCRIPTION:
296 # Add an NTP service provider to the list of implementations
297 # in timedated. <NN-name> defines the newly-created ntp-units.d priority
298 # and name, while the remaining arguments list service units that will
299 # be added to that file.
300 #
301 # Uses doins, thus it is fatal in EAPI 4 and non-fatal in earlier
302 # EAPIs.
303 #
304 # Doc: https://www.freedesktop.org/wiki/Software/systemd/timedated/
305 systemd_enable_ntpunit() {
306         debug-print-function ${FUNCNAME} "${@}"
307         if [[ ${#} -lt 2 ]]; then
308                 die "Usage: systemd_enable_ntpunit <NN-name> <service>..."
309         fi
310
311         local ntpunit_name=${1}
312         local services=( "${@:2}" )
313
314         if [[ ${ntpunit_name} != [0-9][0-9]-* ]]; then
315                 die "ntpunit.d file must be named NN-name where NN are digits."
316         elif [[ ${ntpunit_name} == *.list ]]; then
317                 die "The .list suffix is appended implicitly to ntpunit.d name."
318         fi
319
320         local unitdir=$(systemd_get_systemunitdir)
321         local s
322         for s in "${services[@]}"; do
323                 if [[ ! -f "${D}${unitdir}/${s}" ]]; then
324                         die "ntp-units.d provider ${s} not installed (yet?) in \${D}."
325                 fi
326                 echo "${s}" >> "${T}"/${ntpunit_name}.list || die
327         done
328
329         (
330                 insopts -m 0644
331                 insinto "$(_systemd_get_utildir)"/ntp-units.d
332                 doins "${T}"/${ntpunit_name}.list
333         )
334         local ret=${?}
335
336         rm "${T}"/${ntpunit_name}.list || die
337
338         return ${ret}
339 }
340
341 # @FUNCTION: systemd_with_unitdir
342 # @USAGE: [<configure-option-name>]
343 # @DESCRIPTION:
344 # Note: deprecated and banned in EAPI 6. Please use full --with-...=
345 # parameter for improved ebuild readability.
346 #
347 # Output '--with-systemdsystemunitdir' as expected by systemd-aware configure
348 # scripts. This function always succeeds. Its output may be quoted in order
349 # to preserve whitespace in paths. systemd_to_myeconfargs() is preferred over
350 # this function.
351 #
352 # If upstream does use invalid configure option to handle installing systemd
353 # units (e.g. `--with-systemdunitdir'), you can pass the 'suffix' as an optional
354 # argument to this function (`$(systemd_with_unitdir systemdunitdir)'). Please
355 # remember to report a bug upstream as well.
356 systemd_with_unitdir() {
357         [[ ${EAPI:-0} != [012345] ]] && die "${FUNCNAME} is banned in EAPI ${EAPI}, use --with-${1:-systemdsystemunitdir}=\"\$(systemd_get_systemunitdir)\" instead"
358
359         debug-print-function ${FUNCNAME} "${@}"
360         local optname=${1:-systemdsystemunitdir}
361
362         echo --with-${optname}="$(systemd_get_systemunitdir)"
363 }
364
365 # @FUNCTION: systemd_with_utildir
366 # @DESCRIPTION:
367 # Note: deprecated and banned in EAPI 6. Please use full --with-...=
368 # parameter for improved ebuild readability.
369 #
370 # Output '--with-systemdsystemutildir' as used by some packages to install
371 # systemd helpers. This function always succeeds. Its output may be quoted
372 # in order to preserve whitespace in paths.
373 systemd_with_utildir() {
374         [[ ${EAPI:-0} != [012345] ]] && die "${FUNCNAME} is banned in EAPI ${EAPI}, use --with-systemdutildir=\"\$(systemd_get_utildir)\" instead"
375
376         debug-print-function ${FUNCNAME} "${@}"
377
378         echo --with-systemdutildir="$(systemd_get_utildir)"
379 }
380
381 # @FUNCTION: systemd_update_catalog
382 # @DESCRIPTION:
383 # Update the journald catalog. This needs to be called after installing
384 # or removing catalog files. This must be called in pkg_post* phases.
385 #
386 # If systemd is not installed, no operation will be done. The catalog
387 # will be (re)built once systemd is installed.
388 #
389 # See: https://www.freedesktop.org/wiki/Software/systemd/catalog
390 systemd_update_catalog() {
391         debug-print-function ${FUNCNAME} "${@}"
392
393         [[ ${EBUILD_PHASE} == post* ]] \
394                 || die "${FUNCNAME} disallowed during ${EBUILD_PHASE_FUNC:-${EBUILD_PHASE}}"
395
396         # Make sure to work on the correct system.
397
398         local journalctl=${EPREFIX}/usr/bin/journalctl
399         if [[ -x ${journalctl} ]]; then
400                 ebegin "Updating systemd journal catalogs"
401                 journalctl --update-catalog
402                 eend $?
403         else
404                 debug-print "${FUNCNAME}: journalctl not found."
405         fi
406 }
407
408 # @FUNCTION: systemd_is_booted
409 # @DESCRIPTION:
410 # Check whether the system was booted using systemd.
411 #
412 # This should be used purely for informational purposes, e.g. warning
413 # user that he needs to use systemd. Installed files or application
414 # behavior *must not* rely on this. Please remember to check MERGE_TYPE
415 # to not trigger the check on binary package build hosts!
416 #
417 # Returns 0 if systemd is used to boot the system, 1 otherwise.
418 #
419 # See: man sd_booted
420 systemd_is_booted() {
421         debug-print-function ${FUNCNAME} "${@}"
422
423         [[ -d /run/systemd/system ]]
424         local ret=${?}
425
426         debug-print "${FUNCNAME}: [[ -d /run/systemd/system ]] -> ${ret}"
427         return ${ret}
428 }
429
430 # @FUNCTION: systemd_tmpfiles_create
431 # @USAGE: <tmpfilesd> ...
432 # @DESCRIPTION:
433 # Invokes systemd-tmpfiles --create with given arguments.
434 # Does nothing if ROOT != / or systemd-tmpfiles is not in PATH.
435 # This function should be called from pkg_postinst.
436 #
437 # Generally, this function should be called with the names of any tmpfiles
438 # fragments which have been installed, either by the build system or by a
439 # previous call to systemd_dotmpfilesd. This ensures that any tmpfiles are
440 # created without the need to reboot the system.
441 systemd_tmpfiles_create() {
442         debug-print-function ${FUNCNAME} "${@}"
443
444         [[ ${EBUILD_PHASE} == postinst ]] || die "${FUNCNAME}: Only valid in pkg_postinst"
445         [[ ${#} -gt 0 ]] || die "${FUNCNAME}: Must specify at least one filename"
446         [[ ${ROOT} == / ]] || return 0
447         type systemd-tmpfiles &> /dev/null || return 0
448         systemd-tmpfiles --create "${@}"
449 }
450
451 # @FUNCTION: systemd_reenable
452 # @USAGE: <unit> ...
453 # @DESCRIPTION:
454 # Re-enables units if they are currently enabled. This resets symlinks to the
455 # defaults specified in the [Install] section.
456 #
457 # This function is intended to fix broken symlinks that result from moving
458 # the systemd system unit directory. It should be called from pkg_postinst
459 # for system units that define the 'Alias' option in their [Install] section.
460 # It is not necessary to call this function to fix dependency symlinks
461 # generated by the 'WantedBy' and 'RequiredBy' options.
462 systemd_reenable() {
463         type systemctl &>/dev/null || return 0
464         local x
465         for x; do
466                 if systemctl --quiet --root="${ROOT}" is-enabled "${x}"; then
467                         systemctl --root="${ROOT}" reenable "${x}"
468                 fi
469         done
470 }