1 # Copyright 1999-2017 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
4 # @ECLASS: systemd.eclass
7 # @BLURB: helper functions to install systemd units
9 # This eclass provides a set of functions to install unit files for
10 # sys-apps/systemd within ebuilds.
19 # --with-systemdsystemunitdir="$(systemd_get_systemunitdir)"
22 # econf "${myconf[@]}"
26 inherit toolchain-funcs
30 *) die "${ECLASS}.eclass API in EAPI ${EAPI} not yet established."
33 DEPEND="virtual/pkgconfig"
35 # @FUNCTION: _systemd_get_dir
36 # @USAGE: <variable-name> <fallback-directory>
39 # Try to obtain the <variable-name> variable from systemd.pc.
40 # If pkg-config or systemd is not installed, return <fallback-directory>
43 [[ ${#} -eq 2 ]] || die "Usage: ${FUNCNAME} <variable-name> <fallback-directory>"
44 local variable=${1} fallback=${2} d
46 if $(tc-getPKG_CONFIG) --exists systemd; then
47 d=$($(tc-getPKG_CONFIG) --variable="${variable}" systemd) || die
56 # @FUNCTION: _systemd_get_unitdir
59 # Get unprefixed unitdir.
60 _systemd_get_systemunitdir() {
61 _systemd_get_dir systemdsystemunitdir /lib/systemd/system
64 # @FUNCTION: systemd_get_systemunitdir
66 # Output the path for the systemd system unit directory (not including
67 # ${D}). This function always succeeds, even if systemd is not
69 systemd_get_systemunitdir() {
70 has "${EAPI:-0}" 0 1 2 && ! use prefix && EPREFIX=
71 debug-print-function ${FUNCNAME} "${@}"
73 echo "${EPREFIX}$(_systemd_get_systemunitdir)"
76 # @FUNCTION: systemd_get_unitdir
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"
82 systemd_get_systemunitdir
85 # @FUNCTION: _systemd_get_userunitdir
88 # Get unprefixed userunitdir.
89 _systemd_get_userunitdir() {
90 _systemd_get_dir systemduserunitdir /usr/lib/systemd/user
93 # @FUNCTION: systemd_get_userunitdir
95 # Output the path for the systemd user unit directory (not including
96 # ${D}). This function always succeeds, even if systemd is not
98 systemd_get_userunitdir() {
99 has "${EAPI:-0}" 0 1 2 && ! use prefix && EPREFIX=
100 debug-print-function ${FUNCNAME} "${@}"
102 echo "${EPREFIX}$(_systemd_get_userunitdir)"
105 # @FUNCTION: _systemd_get_utildir
108 # Get unprefixed utildir.
109 _systemd_get_utildir() {
110 _systemd_get_dir systemdutildir /lib/systemd
113 # @FUNCTION: systemd_get_utildir
115 # Output the path for the systemd utility directory (not including
116 # ${D}). This function always succeeds, even if systemd is not
118 systemd_get_utildir() {
119 has "${EAPI:-0}" 0 1 2 && ! use prefix && EPREFIX=
120 debug-print-function ${FUNCNAME} "${@}"
122 echo "${EPREFIX}$(_systemd_get_utildir)"
125 # @FUNCTION: _systemd_get_systemgeneratordir
128 # Get unprefixed systemgeneratordir.
129 _systemd_get_systemgeneratordir() {
130 _systemd_get_dir systemdsystemgeneratordir /lib/systemd/system-generators
133 # @FUNCTION: systemd_get_systemgeneratordir
135 # Output the path for the systemd system generator directory (not including
136 # ${D}). This function always succeeds, even if systemd is not
138 systemd_get_systemgeneratordir() {
139 has "${EAPI:-0}" 0 1 2 && ! use prefix && EPREFIX=
140 debug-print-function ${FUNCNAME} "${@}"
142 echo "${EPREFIX}$(_systemd_get_systemgeneratordir)"
145 # @FUNCTION: systemd_dounit
148 # Install systemd unit(s). Uses doins, thus it is fatal in EAPI 4
149 # and non-fatal in earlier EAPIs.
151 debug-print-function ${FUNCNAME} "${@}"
155 insinto "$(_systemd_get_systemunitdir)"
160 # @FUNCTION: systemd_newunit
161 # @USAGE: <old-name> <new-name>
163 # Install systemd unit with a new name. Uses newins, thus it is fatal
164 # in EAPI 4 and non-fatal in earlier EAPIs.
166 debug-print-function ${FUNCNAME} "${@}"
170 insinto "$(_systemd_get_systemunitdir)"
175 # @FUNCTION: systemd_douserunit
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} "${@}"
185 insinto "$(_systemd_get_userunitdir)"
190 # @FUNCTION: systemd_newuserunit
191 # @USAGE: <old-name> <new-name>
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} "${@}"
200 insinto "$(_systemd_get_userunitdir)"
205 # @FUNCTION: systemd_install_serviced
206 # @USAGE: <conf-file> [<service>]
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} "${@}"
218 [[ ${src} ]] || die "No file specified"
220 if [[ ! ${service} ]]; then
221 [[ ${src} == *.conf ]] || die "Source file needs .conf suffix"
223 service=${service%.conf}
225 # avoid potentially common mistake
226 [[ ${service} == *.d ]] && die "Service must not have .d suffix"
230 insinto /etc/systemd/system/"${service}".d
231 newins "${src}" 00gentoo.conf
235 # @FUNCTION: systemd_dotmpfilesd
236 # @USAGE: <tmpfilesd>...
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} "${@}"
244 [[ ${f} == *.conf ]] \
245 || die 'tmpfiles.d files need to have .conf suffix.'
250 insinto /usr/lib/tmpfiles.d/
255 # @FUNCTION: systemd_newtmpfilesd
256 # @USAGE: <old-name> <new-name>.conf
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} "${@}"
263 [[ ${2} == *.conf ]] \
264 || die 'tmpfiles.d files need to have .conf suffix.'
268 insinto /usr/lib/tmpfiles.d/
273 # @FUNCTION: systemd_enable_service
274 # @USAGE: <target> <service>
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
279 systemd_enable_service() {
280 debug-print-function ${FUNCNAME} "${@}"
282 [[ ${#} -eq 2 ]] || die "Synopsis: systemd_enable_service target service"
286 local ud=$(_systemd_get_systemunitdir)
287 local destname=${service##*/}
289 dodir "${ud}"/"${target}".wants && \
290 dosym ../"${service}" "${ud}"/"${target}".wants/"${destname}"
293 # @FUNCTION: systemd_enable_ntpunit
294 # @USAGE: <NN-name> <service>...
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.
301 # Uses doins, thus it is fatal in EAPI 4 and non-fatal in earlier
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>..."
311 local ntpunit_name=${1}
312 local services=( "${@:2}" )
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."
320 local unitdir=$(systemd_get_systemunitdir)
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}."
326 echo "${s}" >> "${T}"/${ntpunit_name}.list || die
331 insinto "$(_systemd_get_utildir)"/ntp-units.d
332 doins "${T}"/${ntpunit_name}.list
336 rm "${T}"/${ntpunit_name}.list || die
341 # @FUNCTION: systemd_with_unitdir
342 # @USAGE: [<configure-option-name>]
344 # Note: deprecated and banned in EAPI 6. Please use full --with-...=
345 # parameter for improved ebuild readability.
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
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"
359 debug-print-function ${FUNCNAME} "${@}"
360 local optname=${1:-systemdsystemunitdir}
362 echo --with-${optname}="$(systemd_get_systemunitdir)"
365 # @FUNCTION: systemd_with_utildir
367 # Note: deprecated and banned in EAPI 6. Please use full --with-...=
368 # parameter for improved ebuild readability.
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"
376 debug-print-function ${FUNCNAME} "${@}"
378 echo --with-systemdutildir="$(systemd_get_utildir)"
381 # @FUNCTION: systemd_update_catalog
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.
386 # If systemd is not installed, no operation will be done. The catalog
387 # will be (re)built once systemd is installed.
389 # See: https://www.freedesktop.org/wiki/Software/systemd/catalog
390 systemd_update_catalog() {
391 debug-print-function ${FUNCNAME} "${@}"
393 [[ ${EBUILD_PHASE} == post* ]] \
394 || die "${FUNCNAME} disallowed during ${EBUILD_PHASE_FUNC:-${EBUILD_PHASE}}"
396 # Make sure to work on the correct system.
398 local journalctl=${EPREFIX}/usr/bin/journalctl
399 if [[ -x ${journalctl} ]]; then
400 ebegin "Updating systemd journal catalogs"
401 journalctl --update-catalog
404 debug-print "${FUNCNAME}: journalctl not found."
408 # @FUNCTION: systemd_is_booted
410 # Check whether the system was booted using systemd.
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!
417 # Returns 0 if systemd is used to boot the system, 1 otherwise.
420 systemd_is_booted() {
421 debug-print-function ${FUNCNAME} "${@}"
423 [[ -d /run/systemd/system ]]
426 debug-print "${FUNCNAME}: [[ -d /run/systemd/system ]] -> ${ret}"
430 # @FUNCTION: systemd_tmpfiles_create
431 # @USAGE: <tmpfilesd> ...
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.
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} "${@}"
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 "${@}"
451 # @FUNCTION: systemd_reenable
454 # Re-enables units if they are currently enabled. This resets symlinks to the
455 # defaults specified in the [Install] section.
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.
463 type systemctl &>/dev/null || return 0
466 if systemctl --quiet --root="${ROOT}" is-enabled "${x}"; then
467 systemctl --root="${ROOT}" reenable "${x}"