1 # Copyright 1999-2017 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
4 # @ECLASS: systemd.eclass
7 # @SUPPORTED_EAPIS: 0 1 2 3 4 5 6 7
8 # @BLURB: helper functions to install systemd units
10 # This eclass provides a set of functions to install unit files for
11 # sys-apps/systemd within ebuilds.
20 # --with-systemdsystemunitdir="$(systemd_get_systemunitdir)"
23 # econf "${myconf[@]}"
27 inherit toolchain-funcs
31 *) die "${ECLASS}.eclass API in EAPI ${EAPI} not yet established."
34 if [[ ${EAPI:-0} == [0123456] ]]; then
35 DEPEND="virtual/pkgconfig"
37 BDEPEND="virtual/pkgconfig"
40 # @FUNCTION: _systemd_get_dir
41 # @USAGE: <variable-name> <fallback-directory>
44 # Try to obtain the <variable-name> variable from systemd.pc.
45 # If pkg-config or systemd is not installed, return <fallback-directory>
48 [[ ${#} -eq 2 ]] || die "Usage: ${FUNCNAME} <variable-name> <fallback-directory>"
49 local variable=${1} fallback=${2} d
51 if $(tc-getPKG_CONFIG) --exists systemd; then
52 d=$($(tc-getPKG_CONFIG) --variable="${variable}" systemd) || die
61 # @FUNCTION: _systemd_get_unitdir
64 # Get unprefixed unitdir.
65 _systemd_get_systemunitdir() {
66 _systemd_get_dir systemdsystemunitdir /lib/systemd/system
69 # @FUNCTION: systemd_get_systemunitdir
71 # Output the path for the systemd system unit directory (not including
72 # ${D}). This function always succeeds, even if systemd is not
74 systemd_get_systemunitdir() {
75 has "${EAPI:-0}" 0 1 2 && ! use prefix && EPREFIX=
76 debug-print-function ${FUNCNAME} "${@}"
78 echo "${EPREFIX}$(_systemd_get_systemunitdir)"
81 # @FUNCTION: systemd_get_unitdir
83 # Deprecated alias for systemd_get_systemunitdir.
84 systemd_get_unitdir() {
85 [[ ${EAPI} == [012345] ]] || die "${FUNCNAME} is banned in EAPI 6, use systemd_get_systemunitdir instead"
87 systemd_get_systemunitdir
90 # @FUNCTION: _systemd_get_userunitdir
93 # Get unprefixed userunitdir.
94 _systemd_get_userunitdir() {
95 _systemd_get_dir systemduserunitdir /usr/lib/systemd/user
98 # @FUNCTION: systemd_get_userunitdir
100 # Output the path for the systemd user unit directory (not including
101 # ${D}). This function always succeeds, even if systemd is not
103 systemd_get_userunitdir() {
104 has "${EAPI:-0}" 0 1 2 && ! use prefix && EPREFIX=
105 debug-print-function ${FUNCNAME} "${@}"
107 echo "${EPREFIX}$(_systemd_get_userunitdir)"
110 # @FUNCTION: _systemd_get_utildir
113 # Get unprefixed utildir.
114 _systemd_get_utildir() {
115 _systemd_get_dir systemdutildir /lib/systemd
118 # @FUNCTION: systemd_get_utildir
120 # Output the path for the systemd utility directory (not including
121 # ${D}). This function always succeeds, even if systemd is not
123 systemd_get_utildir() {
124 has "${EAPI:-0}" 0 1 2 && ! use prefix && EPREFIX=
125 debug-print-function ${FUNCNAME} "${@}"
127 echo "${EPREFIX}$(_systemd_get_utildir)"
130 # @FUNCTION: _systemd_get_systemgeneratordir
133 # Get unprefixed systemgeneratordir.
134 _systemd_get_systemgeneratordir() {
135 _systemd_get_dir systemdsystemgeneratordir /lib/systemd/system-generators
138 # @FUNCTION: systemd_get_systemgeneratordir
140 # Output the path for the systemd system generator directory (not including
141 # ${D}). This function always succeeds, even if systemd is not
143 systemd_get_systemgeneratordir() {
144 has "${EAPI:-0}" 0 1 2 && ! use prefix && EPREFIX=
145 debug-print-function ${FUNCNAME} "${@}"
147 echo "${EPREFIX}$(_systemd_get_systemgeneratordir)"
150 # @FUNCTION: systemd_dounit
153 # Install systemd unit(s). Uses doins, thus it is fatal in EAPI 4
154 # and non-fatal in earlier EAPIs.
156 debug-print-function ${FUNCNAME} "${@}"
160 insinto "$(_systemd_get_systemunitdir)"
165 # @FUNCTION: systemd_newunit
166 # @USAGE: <old-name> <new-name>
168 # Install systemd unit with a new name. Uses newins, thus it is fatal
169 # in EAPI 4 and non-fatal in earlier EAPIs.
171 debug-print-function ${FUNCNAME} "${@}"
175 insinto "$(_systemd_get_systemunitdir)"
180 # @FUNCTION: systemd_douserunit
183 # Install systemd user unit(s). Uses doins, thus it is fatal in EAPI 4
184 # and non-fatal in earlier EAPIs.
185 systemd_douserunit() {
186 debug-print-function ${FUNCNAME} "${@}"
190 insinto "$(_systemd_get_userunitdir)"
195 # @FUNCTION: systemd_newuserunit
196 # @USAGE: <old-name> <new-name>
198 # Install systemd user unit with a new name. Uses newins, thus it
199 # is fatal in EAPI 4 and non-fatal in earlier EAPIs.
200 systemd_newuserunit() {
201 debug-print-function ${FUNCNAME} "${@}"
205 insinto "$(_systemd_get_userunitdir)"
210 # @FUNCTION: systemd_install_serviced
211 # @USAGE: <conf-file> [<service>]
213 # Install <conf-file> as the template <service>.d/00gentoo.conf.
214 # If <service> is not specified
215 # <conf-file> with the .conf suffix stripped is used
216 # (e.g. foo.service.conf -> foo.service.d/00gentoo.conf).
217 systemd_install_serviced() {
218 debug-print-function ${FUNCNAME} "${@}"
223 [[ ${src} ]] || die "No file specified"
225 if [[ ! ${service} ]]; then
226 [[ ${src} == *.conf ]] || die "Source file needs .conf suffix"
228 service=${service%.conf}
230 # avoid potentially common mistake
231 [[ ${service} == *.d ]] && die "Service must not have .d suffix"
235 insinto /etc/systemd/system/"${service}".d
236 newins "${src}" 00gentoo.conf
240 # @FUNCTION: systemd_dotmpfilesd
241 # @USAGE: <tmpfilesd>...
243 # Install systemd tmpfiles.d files. Uses doins, thus it is fatal
244 # in EAPI 4 and non-fatal in earlier EAPIs.
245 systemd_dotmpfilesd() {
246 debug-print-function ${FUNCNAME} "${@}"
249 [[ ${f} == *.conf ]] \
250 || die 'tmpfiles.d files need to have .conf suffix.'
255 insinto /usr/lib/tmpfiles.d/
260 # @FUNCTION: systemd_newtmpfilesd
261 # @USAGE: <old-name> <new-name>.conf
263 # Install systemd tmpfiles.d file under a new name. Uses newins, thus it
264 # is fatal in EAPI 4 and non-fatal in earlier EAPIs.
265 systemd_newtmpfilesd() {
266 debug-print-function ${FUNCNAME} "${@}"
268 [[ ${2} == *.conf ]] \
269 || die 'tmpfiles.d files need to have .conf suffix.'
273 insinto /usr/lib/tmpfiles.d/
278 # @FUNCTION: systemd_enable_service
279 # @USAGE: <target> <service>
281 # Enable service in desired target, e.g. install a symlink for it.
282 # Uses dosym, thus it is fatal in EAPI 4 and non-fatal in earlier
284 systemd_enable_service() {
285 debug-print-function ${FUNCNAME} "${@}"
287 [[ ${#} -eq 2 ]] || die "Synopsis: systemd_enable_service target service"
291 local ud=$(_systemd_get_systemunitdir)
292 local destname=${service##*/}
294 dodir "${ud}"/"${target}".wants && \
295 dosym ../"${service}" "${ud}"/"${target}".wants/"${destname}"
298 # @FUNCTION: systemd_enable_ntpunit
299 # @USAGE: <NN-name> <service>...
301 # Add an NTP service provider to the list of implementations
302 # in timedated. <NN-name> defines the newly-created ntp-units.d priority
303 # and name, while the remaining arguments list service units that will
304 # be added to that file.
306 # Uses doins, thus it is fatal in EAPI 4 and non-fatal in earlier
309 # Doc: https://www.freedesktop.org/wiki/Software/systemd/timedated/
310 systemd_enable_ntpunit() {
311 debug-print-function ${FUNCNAME} "${@}"
312 if [[ ${#} -lt 2 ]]; then
313 die "Usage: systemd_enable_ntpunit <NN-name> <service>..."
316 local ntpunit_name=${1}
317 local services=( "${@:2}" )
319 if [[ ${ntpunit_name} != [0-9][0-9]-* ]]; then
320 die "ntpunit.d file must be named NN-name where NN are digits."
321 elif [[ ${ntpunit_name} == *.list ]]; then
322 die "The .list suffix is appended implicitly to ntpunit.d name."
325 local unitdir=$(systemd_get_systemunitdir)
327 for s in "${services[@]}"; do
328 if [[ ! -f "${D}${unitdir}/${s}" ]]; then
329 die "ntp-units.d provider ${s} not installed (yet?) in \${D}."
331 echo "${s}" >> "${T}"/${ntpunit_name}.list || die
336 insinto "$(_systemd_get_utildir)"/ntp-units.d
337 doins "${T}"/${ntpunit_name}.list
341 rm "${T}"/${ntpunit_name}.list || die
346 # @FUNCTION: systemd_with_unitdir
347 # @USAGE: [<configure-option-name>]
349 # Note: deprecated and banned in EAPI 6. Please use full --with-...=
350 # parameter for improved ebuild readability.
352 # Output '--with-systemdsystemunitdir' as expected by systemd-aware configure
353 # scripts. This function always succeeds. Its output may be quoted in order
354 # to preserve whitespace in paths. systemd_to_myeconfargs() is preferred over
357 # If upstream does use invalid configure option to handle installing systemd
358 # units (e.g. `--with-systemdunitdir'), you can pass the 'suffix' as an optional
359 # argument to this function (`$(systemd_with_unitdir systemdunitdir)'). Please
360 # remember to report a bug upstream as well.
361 systemd_with_unitdir() {
362 [[ ${EAPI:-0} != [012345] ]] && die "${FUNCNAME} is banned in EAPI ${EAPI}, use --with-${1:-systemdsystemunitdir}=\"\$(systemd_get_systemunitdir)\" instead"
364 debug-print-function ${FUNCNAME} "${@}"
365 local optname=${1:-systemdsystemunitdir}
367 echo --with-${optname}="$(systemd_get_systemunitdir)"
370 # @FUNCTION: systemd_with_utildir
372 # Note: deprecated and banned in EAPI 6. Please use full --with-...=
373 # parameter for improved ebuild readability.
375 # Output '--with-systemdsystemutildir' as used by some packages to install
376 # systemd helpers. This function always succeeds. Its output may be quoted
377 # in order to preserve whitespace in paths.
378 systemd_with_utildir() {
379 [[ ${EAPI:-0} != [012345] ]] && die "${FUNCNAME} is banned in EAPI ${EAPI}, use --with-systemdutildir=\"\$(systemd_get_utildir)\" instead"
381 debug-print-function ${FUNCNAME} "${@}"
383 echo --with-systemdutildir="$(systemd_get_utildir)"
386 # @FUNCTION: systemd_update_catalog
388 # Update the journald catalog. This needs to be called after installing
389 # or removing catalog files. This must be called in pkg_post* phases.
391 # If systemd is not installed, no operation will be done. The catalog
392 # will be (re)built once systemd is installed.
394 # See: https://www.freedesktop.org/wiki/Software/systemd/catalog
395 systemd_update_catalog() {
396 debug-print-function ${FUNCNAME} "${@}"
398 [[ ${EBUILD_PHASE} == post* ]] \
399 || die "${FUNCNAME} disallowed during ${EBUILD_PHASE_FUNC:-${EBUILD_PHASE}}"
401 # Make sure to work on the correct system.
403 local journalctl=${EPREFIX}/usr/bin/journalctl
404 if [[ -x ${journalctl} ]]; then
405 ebegin "Updating systemd journal catalogs"
406 journalctl --update-catalog
409 debug-print "${FUNCNAME}: journalctl not found."
413 # @FUNCTION: systemd_is_booted
415 # Check whether the system was booted using systemd.
417 # This should be used purely for informational purposes, e.g. warning
418 # user that he needs to use systemd. Installed files or application
419 # behavior *must not* rely on this. Please remember to check MERGE_TYPE
420 # to not trigger the check on binary package build hosts!
422 # Returns 0 if systemd is used to boot the system, 1 otherwise.
425 systemd_is_booted() {
426 debug-print-function ${FUNCNAME} "${@}"
428 [[ -d /run/systemd/system ]]
431 debug-print "${FUNCNAME}: [[ -d /run/systemd/system ]] -> ${ret}"
435 # @FUNCTION: systemd_tmpfiles_create
436 # @USAGE: <tmpfilesd> ...
438 # Invokes systemd-tmpfiles --create with given arguments.
439 # Does nothing if ROOT != / or systemd-tmpfiles is not in PATH.
440 # This function should be called from pkg_postinst.
442 # Generally, this function should be called with the names of any tmpfiles
443 # fragments which have been installed, either by the build system or by a
444 # previous call to systemd_dotmpfilesd. This ensures that any tmpfiles are
445 # created without the need to reboot the system.
446 systemd_tmpfiles_create() {
447 debug-print-function ${FUNCNAME} "${@}"
449 [[ ${EBUILD_PHASE} == postinst ]] || die "${FUNCNAME}: Only valid in pkg_postinst"
450 [[ ${#} -gt 0 ]] || die "${FUNCNAME}: Must specify at least one filename"
451 [[ ${ROOT} == / ]] || return 0
452 type systemd-tmpfiles &> /dev/null || return 0
453 systemd-tmpfiles --create "${@}"
456 # @FUNCTION: systemd_reenable
459 # Re-enables units if they are currently enabled. This resets symlinks to the
460 # defaults specified in the [Install] section.
462 # This function is intended to fix broken symlinks that result from moving
463 # the systemd system unit directory. It should be called from pkg_postinst
464 # for system units that define the 'Alias' option in their [Install] section.
465 # It is not necessary to call this function to fix dependency symlinks
466 # generated by the 'WantedBy' and 'RequiredBy' options.
468 type systemctl &>/dev/null || return 0
471 if systemctl --quiet --root="${ROOT:-/}" is-enabled "${x}"; then
472 systemctl --root="${ROOT:-/}" reenable "${x}"