mirror of
https://github.com/systemd/systemd
synced 2026-03-16 18:14:46 +01:00
Compare commits
No commits in common. "83a04afc06eb37e765e23a3af4333f681619794e" and "86204ae145e38a4557981a92ce91a8ce4318e181" have entirely different histories.
83a04afc06
...
86204ae145
@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
|
|
||||||
import ast
|
|
||||||
import re
|
|
||||||
|
|
||||||
def read_os_release():
|
|
||||||
try:
|
|
||||||
f = open('/etc/os-release')
|
|
||||||
except FileNotFoundError:
|
|
||||||
f = open('/usr/lib/os-release')
|
|
||||||
|
|
||||||
for line_number, line in enumerate(f):
|
|
||||||
if m := re.match(r'([A-Z][A-Z_0-9]+)=(.*?)\s*$', line):
|
|
||||||
name, val = m.groups()
|
|
||||||
if val and val[0] in '"\'':
|
|
||||||
val = ast.literal_eval(val)
|
|
||||||
yield name, val
|
|
||||||
else:
|
|
||||||
print(f'Warning: bad line {line_number}: {line}', file=sys.stderr)
|
|
||||||
|
|
||||||
os_release = dict(read_os_release())
|
|
||||||
|
|
||||||
pretty_name = os_release.get('PRETTY_NAME', 'Linux')
|
|
||||||
print(f'Running on {pretty_name}')
|
|
||||||
|
|
||||||
if (os_release.get('ID', 'linux') == 'debian' or
|
|
||||||
os_release.get('ID_LIKE', None) == 'debian'):
|
|
||||||
print('Looks like Debian!')
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
#!/bin/sh -eu
|
|
||||||
|
|
||||||
test -e /etc/os-release && os_release='/etc/os-release' || os_release='/usr/lib/os-release'
|
|
||||||
. "${os_release}"
|
|
||||||
|
|
||||||
echo "Running on ${PRETTY_NAME:-Linux}"
|
|
||||||
|
|
||||||
if [ "${ID:-linux}" = "debian" ] || [ "${ID_LIKE:-}" = "debian" ]; then
|
|
||||||
echo "Looks like Debian!"
|
|
||||||
fi
|
|
||||||
@ -3,7 +3,7 @@
|
|||||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||||
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
|
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
|
||||||
|
|
||||||
<refentry id="os-release" xmlns:xi="http://www.w3.org/2001/XInclude">
|
<refentry id="os-release">
|
||||||
<refentryinfo>
|
<refentryinfo>
|
||||||
<title>os-release</title>
|
<title>os-release</title>
|
||||||
<productname>systemd</productname>
|
<productname>systemd</productname>
|
||||||
@ -16,14 +16,12 @@
|
|||||||
|
|
||||||
<refnamediv>
|
<refnamediv>
|
||||||
<refname>os-release</refname>
|
<refname>os-release</refname>
|
||||||
<refname>initrd-release</refname>
|
|
||||||
<refpurpose>Operating system identification</refpurpose>
|
<refpurpose>Operating system identification</refpurpose>
|
||||||
</refnamediv>
|
</refnamediv>
|
||||||
|
|
||||||
<refsynopsisdiv>
|
<refsynopsisdiv>
|
||||||
<para><filename>/etc/os-release</filename></para>
|
<para><filename>/etc/os-release</filename></para>
|
||||||
<para><filename>/usr/lib/os-release</filename></para>
|
<para><filename>/usr/lib/os-release</filename></para>
|
||||||
<para><filename>/etc/initrd-release</filename></para>
|
|
||||||
</refsynopsisdiv>
|
</refsynopsisdiv>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
@ -81,19 +79,6 @@
|
|||||||
<para>For a longer rationale for <filename>os-release</filename>
|
<para>For a longer rationale for <filename>os-release</filename>
|
||||||
please refer to the <ulink
|
please refer to the <ulink
|
||||||
url="http://0pointer.de/blog/projects/os-release">Announcement of <filename>/etc/os-release</filename></ulink>.</para>
|
url="http://0pointer.de/blog/projects/os-release">Announcement of <filename>/etc/os-release</filename></ulink>.</para>
|
||||||
|
|
||||||
<refsect2>
|
|
||||||
<title><filename>/etc/initrd-release</filename></title>
|
|
||||||
|
|
||||||
<para>In the <ulink
|
|
||||||
url="https://www.kernel.org/doc/html/latest/admin-guide/initrd.html">initrd</ulink>,
|
|
||||||
<filename>/etc/initrd-release</filename> plays the same role as <filename>os-release</filename> in the
|
|
||||||
main system. Additionally, the presence of that file means that the system is in the initrd phase.
|
|
||||||
<filename>/etc/os-release</filename> should be symlinked to <filename>/etc/initrd-release</filename>
|
|
||||||
(or vice versa), so programs that only look for <filename>/etc/os-release</filename> (as described
|
|
||||||
above) work correctly. The rest of this document that talks about <filename>os-release</filename>
|
|
||||||
should be understood to apply to <filename>initrd-release</filename> too.</para>
|
|
||||||
</refsect2>
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
@ -102,235 +87,106 @@
|
|||||||
<para>The following OS identifications parameters may be set using
|
<para>The following OS identifications parameters may be set using
|
||||||
<filename>os-release</filename>:</para>
|
<filename>os-release</filename>:</para>
|
||||||
|
|
||||||
<refsect2>
|
|
||||||
<title>General information identifying the operating system</title>
|
|
||||||
|
|
||||||
<variablelist class='environment-variables'>
|
<variablelist class='environment-variables'>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>NAME=</varname></term>
|
<term><varname>NAME=</varname></term>
|
||||||
|
|
||||||
<listitem><para>A string identifying the operating system, without a version component, and
|
<listitem><para>A string identifying the operating system,
|
||||||
suitable for presentation to the user. If not set, a default of <literal>NAME=Linux</literal> may
|
without a version component, and suitable for presentation to
|
||||||
be used.</para>
|
the user. If not set, defaults to
|
||||||
|
<literal>NAME=Linux</literal>. Example:
|
||||||
|
<literal>NAME=Fedora</literal> or <literal>NAME="Debian
|
||||||
|
GNU/Linux"</literal>.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<para>Examples: <literal>NAME=Fedora</literal>, <literal>NAME="Debian GNU/Linux"</literal>.
|
<varlistentry>
|
||||||
</para></listitem>
|
<term><varname>VERSION=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>A string identifying the operating system
|
||||||
|
version, excluding any OS name information, possibly including
|
||||||
|
a release code name, and suitable for presentation to the
|
||||||
|
user. This field is optional. Example:
|
||||||
|
<literal>VERSION=17</literal> or <literal>VERSION="17 (Beefy
|
||||||
|
Miracle)"</literal>.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>ID=</varname></term>
|
<term><varname>ID=</varname></term>
|
||||||
|
|
||||||
<listitem><para>A lower-case string (no spaces or other characters outside of 0–9, a–z, ".", "_"
|
<listitem><para>A lower-case string (no spaces or other
|
||||||
and "-") identifying the operating system, excluding any version information and suitable for
|
characters outside of 0–9, a–z, ".", "_" and "-") identifying
|
||||||
processing by scripts or usage in generated filenames. If not set, a default of
|
the operating system, excluding any version information and
|
||||||
<literal>ID=linux</literal> may be used.</para>
|
suitable for processing by scripts or usage in generated
|
||||||
|
filenames. If not set, defaults to
|
||||||
<para>Examples: <literal>ID=fedora</literal>, <literal>ID=debian</literal>.</para></listitem>
|
<literal>ID=linux</literal>. Example:
|
||||||
|
<literal>ID=fedora</literal> or
|
||||||
|
<literal>ID=debian</literal>.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>ID_LIKE=</varname></term>
|
<term><varname>ID_LIKE=</varname></term>
|
||||||
|
|
||||||
<listitem><para>A space-separated list of operating system identifiers in the same syntax as the
|
<listitem><para>A space-separated list of operating system
|
||||||
<varname>ID=</varname> setting. It should list identifiers of operating systems that are closely
|
identifiers in the same syntax as the <varname>ID=</varname>
|
||||||
related to the local operating system in regards to packaging and programming interfaces, for
|
setting. It should list identifiers of operating systems that
|
||||||
example listing one or more OS identifiers the local OS is a derivative from. An OS should
|
are closely related to the local operating system in regards
|
||||||
generally only list other OS identifiers it itself is a derivative of, and not any OSes that are
|
to packaging and programming interfaces, for example listing
|
||||||
derived from it, though symmetric relationships are possible. Build scripts and similar should
|
one or more OS identifiers the local OS is a derivative from.
|
||||||
check this variable if they need to identify the local operating system and the value of
|
An OS should generally only list other OS identifiers it
|
||||||
<varname>ID=</varname> is not recognized. Operating systems should be listed in order of how
|
itself is a derivative of, and not any OSes that are derived
|
||||||
closely the local operating system relates to the listed ones, starting with the closest. This
|
from it, though symmetric relationships are possible. Build
|
||||||
field is optional.</para>
|
scripts and similar should check this variable if they need to
|
||||||
|
identify the local operating system and the value of
|
||||||
<para>Examples: for an operating system with <literal>ID=centos</literal>, an assignment of
|
<varname>ID=</varname> is not recognized. Operating systems
|
||||||
<literal>ID_LIKE="rhel fedora"</literal> would be appropriate. For an operating system with
|
should be listed in order of how closely the local operating
|
||||||
<literal>ID=ubuntu</literal>, an assignment of <literal>ID_LIKE=debian</literal> is appropriate.
|
system relates to the listed ones, starting with the closest.
|
||||||
</para></listitem>
|
This field is optional. Example: for an operating system with
|
||||||
|
<literal>ID=centos</literal>, an assignment of
|
||||||
|
<literal>ID_LIKE="rhel fedora"</literal> would be appropriate.
|
||||||
|
For an operating system with <literal>ID=ubuntu</literal>, an
|
||||||
|
assignment of <literal>ID_LIKE=debian</literal> is
|
||||||
|
appropriate.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>PRETTY_NAME=</varname></term>
|
<term><varname>VERSION_CODENAME=</varname></term>
|
||||||
|
|
||||||
<listitem><para>A pretty operating system name in a format suitable for presentation to the
|
<listitem><para>
|
||||||
user. May or may not contain a release code name or OS version of some kind, as suitable. If not
|
A lower-case string (no spaces or other characters outside of
|
||||||
set, a default of <literal>PRETTY_NAME="Linux"</literal> may be used</para>
|
0–9, a–z, ".", "_" and "-") identifying the operating system
|
||||||
|
release code name, excluding any OS name information or
|
||||||
<para>Example: <literal>PRETTY_NAME="Fedora 17 (Beefy Miracle)"</literal>.</para></listitem>
|
release version, and suitable for processing by scripts or
|
||||||
</varlistentry>
|
usage in generated filenames. This field is optional and may
|
||||||
|
not be implemented on all systems.
|
||||||
<varlistentry>
|
Examples:
|
||||||
<term><varname>CPE_NAME=</varname></term>
|
<literal>VERSION_CODENAME=buster</literal>,
|
||||||
|
<literal>VERSION_CODENAME=xenial</literal>
|
||||||
<listitem><para>A CPE name for the operating system, in URI binding syntax, following the <ulink
|
|
||||||
url="http://scap.nist.gov/specifications/cpe/">Common Platform Enumeration Specification</ulink> as
|
|
||||||
proposed by the NIST. This field is optional.</para>
|
|
||||||
|
|
||||||
<para>Example: <literal>CPE_NAME="cpe:/o:fedoraproject:fedora:17"</literal></para></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>VARIANT=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>A string identifying a specific variant or edition of the operating system suitable
|
|
||||||
for presentation to the user. This field may be used to inform the user that the configuration of
|
|
||||||
this system is subject to a specific divergent set of rules or default configuration settings. This
|
|
||||||
field is optional and may not be implemented on all systems.</para>
|
|
||||||
|
|
||||||
<para>Examples: <literal>VARIANT="Server Edition"</literal>, <literal>VARIANT="Smart Refrigerator
|
|
||||||
Edition"</literal>.</para>
|
|
||||||
|
|
||||||
<para>Note: this field is for display purposes only. The <varname>VARIANT_ID</varname> field should
|
|
||||||
be used for making programmatic decisions.</para></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>VARIANT_ID=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>A lower-case string (no spaces or other characters outside of 0–9, a–z, ".", "_" and
|
|
||||||
"-"), identifying a specific variant or edition of the operating system. This may be interpreted by
|
|
||||||
other packages in order to determine a divergent default configuration. This field is optional and
|
|
||||||
may not be implemented on all systems.</para>
|
|
||||||
|
|
||||||
<para>Examples: <literal>VARIANT_ID=server</literal>, <literal>VARIANT_ID=embedded</literal>.
|
|
||||||
</para></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</refsect2>
|
|
||||||
|
|
||||||
<refsect2>
|
|
||||||
<title>Information about the version of the operating system</title>
|
|
||||||
|
|
||||||
<variablelist class='environment-variables'>
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>VERSION=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>A string identifying the operating system version, excluding any OS name
|
|
||||||
information, possibly including a release code name, and suitable for presentation to the
|
|
||||||
user. This field is optional.</para>
|
|
||||||
|
|
||||||
<para>Examples: <literal>VERSION=17</literal>, <literal>VERSION="17 (Beefy Miracle)"</literal>.
|
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>VERSION_ID=</varname></term>
|
<term><varname>VERSION_ID=</varname></term>
|
||||||
|
|
||||||
<listitem><para>A lower-case string (mostly numeric, no spaces or other characters outside of 0–9,
|
<listitem><para>A lower-case string (mostly numeric, no spaces
|
||||||
a–z, ".", "_" and "-") identifying the operating system version, excluding any OS name information
|
or other characters outside of 0–9, a–z, ".", "_" and "-")
|
||||||
or release code name, and suitable for processing by scripts or usage in generated filenames. This
|
identifying the operating system version, excluding any OS
|
||||||
field is optional.</para>
|
name information or release code name, and suitable for
|
||||||
|
processing by scripts or usage in generated filenames. This
|
||||||
<para>Examples: <literal>VERSION_ID=17</literal>, <literal>VERSION_ID=11.04</literal>.
|
field is optional. Example: <literal>VERSION_ID=17</literal>
|
||||||
</para></listitem>
|
or <literal>VERSION_ID=11.04</literal>.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>VERSION_CODENAME=</varname></term>
|
<term><varname>PRETTY_NAME=</varname></term>
|
||||||
|
|
||||||
<listitem><para>A lower-case string (no spaces or other characters outside of 0–9, a–z, ".", "_"
|
<listitem><para>A pretty operating system name in a format
|
||||||
and "-") identifying the operating system release code name, excluding any OS name information or
|
suitable for presentation to the user. May or may not contain
|
||||||
release version, and suitable for processing by scripts or usage in generated filenames. This field
|
a release code name or OS version of some kind, as suitable.
|
||||||
is optional and may not be implemented on all systems.</para>
|
If not set, defaults to
|
||||||
|
<literal>PRETTY_NAME="Linux"</literal>. Example:
|
||||||
<para>Examples: <literal>VERSION_CODENAME=buster</literal>,
|
<literal>PRETTY_NAME="Fedora 17 (Beefy
|
||||||
<literal>VERSION_CODENAME=xenial</literal>.</para></listitem>
|
Miracle)"</literal>.</para></listitem>
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>BUILD_ID=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>A string uniquely identifying the system image originally used as the installation
|
|
||||||
base. In most cases, <varname>VERSION_ID</varname> or
|
|
||||||
<varname>IMAGE_ID</varname>+<varname>IMAGE_VERSION</varname> are updated when the entire system
|
|
||||||
image is replaced during an update. <varname>BUILD_ID</varname> may be used in distributions where
|
|
||||||
the original installation image version is important: <varname>VERSION_ID</varname> would change
|
|
||||||
during incremental system updates, but <varname>BUILD_ID</varname> would not. This field is
|
|
||||||
optional.</para>
|
|
||||||
|
|
||||||
<para>Examples: <literal>BUILD_ID="2013-03-20.3"</literal>, <literal>BUILD_ID=201303203</literal>.
|
|
||||||
</para></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>IMAGE_ID=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para> A lower-case string (no spaces or other characters outside of 0–9, a–z, ".", "_"
|
|
||||||
and "-"), identifying a specific image of the operating system. This is supposed to be used for
|
|
||||||
environments where OS images are prepared, built, shipped and updated as comprehensive, consistent
|
|
||||||
OS images. This field is optional and may not be implemented on all systems, in particularly not on
|
|
||||||
those that are not managed via images but put together and updated from individual packages and on
|
|
||||||
the local system.</para>
|
|
||||||
|
|
||||||
<para>Examples: <literal>IMAGE_ID=vendorx-cashier-system</literal>,
|
|
||||||
<literal>IMAGE_ID=netbook-image</literal>.</para></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>IMAGE_VERSION=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>A lower-case string (mostly numeric, no spaces or other characters outside of 0–9,
|
|
||||||
a–z, ".", "_" and "-") identifying the OS image version. This is supposed to be used together with
|
|
||||||
<varname>IMAGE_ID</varname> described above, to discern different versions of the same image.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>Examples: <literal>IMAGE_VERSION=33</literal>, <literal>IMAGE_VERSION=47.1rc1</literal>.
|
|
||||||
</para></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
|
|
||||||
<para>To summarize: if the image updates are built and shipped as comprehensive units,
|
|
||||||
<varname>IMAGE_ID</varname>+<varname>IMAGE_VERSION</varname> is the best fit. Otherwise, if updates
|
|
||||||
eventually completely replace previously installed contents, as in a typical binary distribution,
|
|
||||||
<varname>VERSION_ID</varname> should be used to identify major releases of the operating system.
|
|
||||||
<varname>BUILD_ID</varname> may be used instead or in addition to <varname>VERSION_ID</varname> when
|
|
||||||
the original system image version is important.</para>
|
|
||||||
</refsect2>
|
|
||||||
|
|
||||||
<refsect2>
|
|
||||||
<title>Presentation information and links</title>
|
|
||||||
|
|
||||||
<variablelist class='environment-variables'>
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>HOME_URL=</varname></term>
|
|
||||||
<term><varname>DOCUMENTATION_URL=</varname></term>
|
|
||||||
<term><varname>SUPPORT_URL=</varname></term>
|
|
||||||
<term><varname>BUG_REPORT_URL=</varname></term>
|
|
||||||
<term><varname>PRIVACY_POLICY_URL=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>Links to resources on the Internet related to the operating system.
|
|
||||||
<varname>HOME_URL=</varname> should refer to the homepage of the operating system, or alternatively
|
|
||||||
some homepage of the specific version of the operating system.
|
|
||||||
<varname>DOCUMENTATION_URL=</varname> should refer to the main documentation page for this
|
|
||||||
operating system. <varname>SUPPORT_URL=</varname> should refer to the main support page for the
|
|
||||||
operating system, if there is any. This is primarily intended for operating systems which vendors
|
|
||||||
provide support for. <varname>BUG_REPORT_URL=</varname> should refer to the main bug reporting page
|
|
||||||
for the operating system, if there is any. This is primarily intended for operating systems that
|
|
||||||
rely on community QA. <varname>PRIVACY_POLICY_URL=</varname> should refer to the main privacy
|
|
||||||
policy page for the operating system, if there is any. These settings are optional, and providing
|
|
||||||
only some of these settings is common. These URLs are intended to be exposed in "About this system"
|
|
||||||
UIs behind links with captions such as "About this Operating System", "Obtain Support", "Report a
|
|
||||||
Bug", or "Privacy Policy". The values should be in <ulink
|
|
||||||
url="https://tools.ietf.org/html/rfc3986">RFC3986 format</ulink>, and should be
|
|
||||||
<literal>http:</literal> or <literal>https:</literal> URLs, and possibly <literal>mailto:</literal>
|
|
||||||
or <literal>tel:</literal>. Only one URL shall be listed in each setting. If multiple resources
|
|
||||||
need to be referenced, it is recommended to provide an online landing page linking all available
|
|
||||||
resources.</para>
|
|
||||||
|
|
||||||
<para>Examples: <literal>HOME_URL="https://fedoraproject.org/"</literal>,
|
|
||||||
<literal>BUG_REPORT_URL="https://bugzilla.redhat.com/"</literal>.</para></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>LOGO=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>A string, specifying the name of an icon as defined by <ulink
|
|
||||||
url="http://standards.freedesktop.org/icon-theme-spec/latest">freedesktop.org Icon Theme
|
|
||||||
Specification</ulink>. This can be used by graphical applications to display an operating system's
|
|
||||||
or distributor's logo. This field is optional and may not necessarily be implemented on all
|
|
||||||
systems.</para>
|
|
||||||
|
|
||||||
<para>Examples: <literal>LOGO=fedora-logo</literal>, <literal>LOGO=distributor-logo-opensuse</literal>
|
|
||||||
</para></listitem>
|
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
@ -338,31 +194,142 @@
|
|||||||
|
|
||||||
<listitem><para>A suggested presentation color when showing the OS name on the console. This should
|
<listitem><para>A suggested presentation color when showing the OS name on the console. This should
|
||||||
be specified as string suitable for inclusion in the ESC [ m ANSI/ECMA-48 escape code for setting
|
be specified as string suitable for inclusion in the ESC [ m ANSI/ECMA-48 escape code for setting
|
||||||
graphical rendition. This field is optional.</para>
|
graphical rendition. This field is optional. Example: <literal>ANSI_COLOR="0;31"</literal> for red,
|
||||||
|
<literal>ANSI_COLOR="1;34"</literal> for light blue, or
|
||||||
|
<literal>ANSI_COLOR="0;38;2;60;110;180"</literal> for Fedora blue.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<para>Examples: <literal>ANSI_COLOR="0;31"</literal> for red, <literal>ANSI_COLOR="1;34"</literal>
|
<varlistentry>
|
||||||
for light blue, or <literal>ANSI_COLOR="0;38;2;60;110;180"</literal> for Fedora blue.
|
<term><varname>CPE_NAME=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>A CPE name for the operating system, in URI
|
||||||
|
binding syntax, following the
|
||||||
|
<ulink url="http://scap.nist.gov/specifications/cpe/">Common
|
||||||
|
Platform Enumeration Specification</ulink> as proposed by the
|
||||||
|
NIST. This field is optional. Example:
|
||||||
|
<literal>CPE_NAME="cpe:/o:fedoraproject:fedora:17"</literal>
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
</variablelist>
|
|
||||||
</refsect2>
|
|
||||||
|
|
||||||
<refsect2>
|
<varlistentry>
|
||||||
<title>Distribution-level defaults and metadata</title>
|
<term><varname>HOME_URL=</varname></term>
|
||||||
|
<term><varname>DOCUMENTATION_URL=</varname></term>
|
||||||
|
<term><varname>SUPPORT_URL=</varname></term>
|
||||||
|
<term><varname>BUG_REPORT_URL=</varname></term>
|
||||||
|
<term><varname>PRIVACY_POLICY_URL=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Links to resources on the Internet related to
|
||||||
|
the operating system.
|
||||||
|
<varname>HOME_URL=</varname> should refer to the homepage of
|
||||||
|
the operating system, or alternatively some homepage of the
|
||||||
|
specific version of the operating system.
|
||||||
|
<varname>DOCUMENTATION_URL=</varname> should refer to the main
|
||||||
|
documentation page for this operating system.
|
||||||
|
<varname>SUPPORT_URL=</varname> should refer to the main
|
||||||
|
support page for the operating system, if there is any. This
|
||||||
|
is primarily intended for operating systems which vendors
|
||||||
|
provide support for. <varname>BUG_REPORT_URL=</varname> should
|
||||||
|
refer to the main bug reporting page for the operating system,
|
||||||
|
if there is any. This is primarily intended for operating
|
||||||
|
systems that rely on community QA.
|
||||||
|
<varname>PRIVACY_POLICY_URL=</varname> should refer to the
|
||||||
|
main privacy policy page for the operating system, if there is
|
||||||
|
any. These settings are optional, and providing only some of
|
||||||
|
these settings is common. These URLs are intended to be
|
||||||
|
exposed in "About this system" UIs behind links with captions
|
||||||
|
such as "About this Operating System", "Obtain Support",
|
||||||
|
"Report a Bug", or "Privacy Policy". The values should be in
|
||||||
|
<ulink url="https://tools.ietf.org/html/rfc3986">RFC3986
|
||||||
|
format</ulink>, and should be <literal>http:</literal> or
|
||||||
|
<literal>https:</literal> URLs, and possibly
|
||||||
|
<literal>mailto:</literal> or <literal>tel:</literal>. Only
|
||||||
|
one URL shall be listed in each setting. If multiple resources
|
||||||
|
need to be referenced, it is recommended to provide an online
|
||||||
|
landing page linking all available resources. Examples:
|
||||||
|
<literal>HOME_URL="https://fedoraproject.org/"</literal> and
|
||||||
|
<literal>BUG_REPORT_URL="https://bugzilla.redhat.com/"</literal></para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>BUILD_ID=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>A string uniquely identifying the system image
|
||||||
|
used as the origin for a distribution (it is not updated with
|
||||||
|
system updates). The field can be identical between different
|
||||||
|
VERSION_IDs as BUILD_ID is an only a unique identifier to a
|
||||||
|
specific version. Distributions that release each update as a
|
||||||
|
new version would only need to use VERSION_ID as each build is
|
||||||
|
already distinct based on the VERSION_ID. This field is
|
||||||
|
optional. Example: <literal>BUILD_ID="2013-03-20.3"</literal>
|
||||||
|
or <literal>BUILD_ID=201303203</literal>.
|
||||||
|
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>VARIANT=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>
|
||||||
|
A string identifying a specific variant or edition of the
|
||||||
|
operating system suitable for presentation to the user. This
|
||||||
|
field may be used to inform the user that the configuration of
|
||||||
|
this system is subject to a specific divergent set of rules or
|
||||||
|
default configuration settings. This field is optional and may
|
||||||
|
not be implemented on all systems.
|
||||||
|
Examples:
|
||||||
|
<literal>VARIANT="Server Edition"</literal>,
|
||||||
|
<literal>VARIANT="Smart Refrigerator Edition"</literal>
|
||||||
|
Note: this field is for display purposes only. The
|
||||||
|
<varname>VARIANT_ID</varname> field should be used for making
|
||||||
|
programmatic decisions.
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>VARIANT_ID=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>
|
||||||
|
A lower-case string (no spaces or other characters outside of
|
||||||
|
0–9, a–z, ".", "_" and "-"), identifying a specific variant or
|
||||||
|
edition of the operating system. This may be interpreted by
|
||||||
|
other packages in order to determine a divergent default
|
||||||
|
configuration. This field is optional and may not be
|
||||||
|
implemented on all systems.
|
||||||
|
Examples:
|
||||||
|
<literal>VARIANT_ID=server</literal>,
|
||||||
|
<literal>VARIANT_ID=embedded</literal>
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>LOGO=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>
|
||||||
|
A string, specifying the name of an icon as defined by <ulink
|
||||||
|
url="http://standards.freedesktop.org/icon-theme-spec/latest">
|
||||||
|
freedesktop.org Icon Theme Specification</ulink>. This can be
|
||||||
|
used by graphical applications to display an operating
|
||||||
|
system's or distributor's logo. This field is optional and
|
||||||
|
may not necessarily be implemented on all systems.
|
||||||
|
Examples:
|
||||||
|
<literal>LOGO=fedora-logo</literal>,
|
||||||
|
<literal>LOGO=distributor-logo-opensuse</literal>
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<variablelist class='environment-variables'>
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>DEFAULT_HOSTNAME=</varname></term>
|
<term><varname>DEFAULT_HOSTNAME=</varname></term>
|
||||||
|
|
||||||
<listitem><para>A string specifying the hostname if
|
<listitem><para>A string specifying the hostname if
|
||||||
<citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>5</manvolnum></citerefentry> is not
|
<citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>5</manvolnum></citerefentry> is not
|
||||||
present and no other configuration source specifies the hostname. Must be either a single DNS label
|
present and no other configuration source specifies the hostname. Must be either a single DNS label
|
||||||
(a string composed of 7-bit ASCII lower-case characters and no spaces or dots, limited to the
|
(a string composed of 7-bit ASCII lower-case characters and no spaces or dots, limited to the format
|
||||||
format allowed for DNS domain name labels), or a sequence of such labels separated by single dots
|
allowed for DNS domain name labels), or a sequence of such labels separated by single dots that forms
|
||||||
that forms a valid DNS FQDN. The hostname must be at most 64 characters, which is a Linux
|
a valid DNS FQDN. The hostname must be at most 64 characters, which is a Linux limitation (DNS allows
|
||||||
limitation (DNS allows longer names).</para>
|
longer names).</para>
|
||||||
|
|
||||||
<para>See <citerefentry><refentrytitle>org.freedesktop.hostname1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
<para>See
|
||||||
|
<citerefentry><refentrytitle>org.freedesktop.hostname1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||||
for a description of how
|
for a description of how
|
||||||
<citerefentry><refentrytitle>systemd-hostnamed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
<citerefentry><refentrytitle>systemd-hostnamed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||||
determines the fallback hostname.</para></listitem>
|
determines the fallback hostname.</para></listitem>
|
||||||
@ -373,47 +340,66 @@
|
|||||||
|
|
||||||
<listitem><para>A lower-case string (mostly numeric, no spaces or other characters outside of 0–9,
|
<listitem><para>A lower-case string (mostly numeric, no spaces or other characters outside of 0–9,
|
||||||
a–z, ".", "_" and "-") identifying the operating system extensions support level, to indicate which
|
a–z, ".", "_" and "-") identifying the operating system extensions support level, to indicate which
|
||||||
extension images are supported. See:
|
extension images are supported (See:
|
||||||
<citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry>)
|
<citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry>).
|
||||||
for more information.</para>
|
Example: <literal>SYSEXT_LEVEL=2</literal> or
|
||||||
|
<literal>SYSEXT_LEVEL=15.14</literal>.</para></listitem>
|
||||||
<para>Examples: <literal>SYSEXT_LEVEL=2</literal>, <literal>SYSEXT_LEVEL=15.14</literal>.
|
|
||||||
</para></listitem>
|
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>IMAGE_ID=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para> A lower-case string (no spaces or other characters outside of 0–9, a–z, ".", "_" and
|
||||||
|
"-"), identifying a specific image of the operating system. This is supposed to be used for
|
||||||
|
environments where OS images are prepared, built, shipped and updated as comprehensive, consistent OS
|
||||||
|
images. This field is optional and may not be implemented on all systems, in particularly not on those
|
||||||
|
that are not managed via images but put together and updated from individual packages and on the
|
||||||
|
local system. Examples: <literal>IMAGE_ID=vendorx-cashier-system</literal>,
|
||||||
|
<literal>IMAGE_ID=netbook-image</literal> </para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>IMAGE_VERSION=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>A lower-case string (mostly numeric, no spaces or other characters outside of 0–9,
|
||||||
|
a–z, ".", "_" and "-") identifying the OS image version. This is supposed to be used together with
|
||||||
|
<varname>IMAGE_ID</varname> described above, to discern different versions of the same
|
||||||
|
image. Examples: <literal>IMAGE_VERSION=33</literal>,
|
||||||
|
<literal>IMAGE_VERSION=47.1rc1</literal> </para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect2>
|
|
||||||
|
|
||||||
<refsect2>
|
<para>If you are reading this file from C code or a shell script
|
||||||
<title>Notes</title>
|
to determine the OS or a specific version of it, use the
|
||||||
|
<varname>ID</varname> and <varname>VERSION_ID</varname> fields,
|
||||||
|
possibly with <varname>ID_LIKE</varname> as fallback for
|
||||||
|
<varname>ID</varname>. When looking for an OS identification
|
||||||
|
string for presentation to the user use the
|
||||||
|
<varname>PRETTY_NAME</varname> field.</para>
|
||||||
|
|
||||||
<para>If you are using this file to determine the OS or a specific version of it, use the
|
<para>Note that operating system vendors may choose not to provide
|
||||||
<varname>ID</varname> and <varname>VERSION_ID</varname> fields, possibly with
|
version information, for example to accommodate for rolling
|
||||||
<varname>ID_LIKE</varname> as fallback for <varname>ID</varname>. When looking for an OS identification
|
releases. In this case, <varname>VERSION</varname> and
|
||||||
string for presentation to the user use the <varname>PRETTY_NAME</varname> field.</para>
|
<varname>VERSION_ID</varname> may be unset. Applications should
|
||||||
|
not rely on these fields to be set.</para>
|
||||||
|
|
||||||
<para>Note that operating system vendors may choose not to provide version information, for example to
|
<para>Operating system vendors may extend the file
|
||||||
accommodate for rolling releases. In this case, <varname>VERSION</varname> and
|
format and introduce new fields. It is highly
|
||||||
<varname>VERSION_ID</varname> may be unset. Applications should not rely on these fields to be
|
recommended to prefix new fields with an OS specific
|
||||||
set.</para>
|
name in order to avoid name clashes. Applications
|
||||||
|
reading this file must ignore unknown fields. Example:
|
||||||
|
<literal>DEBIAN_BTS="debbugs://bugs.debian.org/"</literal></para>
|
||||||
|
|
||||||
<para>Operating system vendors may extend the file format and introduce new fields. It is highly
|
<para>Container and sandbox runtime managers may make the host's
|
||||||
recommended to prefix new fields with an OS specific name in order to avoid name clashes. Applications
|
identification data available to applications by providing the host's
|
||||||
reading this file must ignore unknown fields.</para>
|
<filename>/etc/os-release</filename> (if available, otherwise
|
||||||
|
|
||||||
<para>Example: <literal>DEBIAN_BTS="debbugs://bugs.debian.org/"</literal>.</para>
|
|
||||||
|
|
||||||
<para>Container and sandbox runtime managers may make the host's identification data available to
|
|
||||||
applications by providing the host's <filename>/etc/os-release</filename> (if available, otherwise
|
|
||||||
<filename>/usr/lib/os-release</filename> as a fallback) as
|
<filename>/usr/lib/os-release</filename> as a fallback) as
|
||||||
<filename>/run/host/os-release</filename>.</para>
|
<filename>/run/host/os-release</filename>.</para>
|
||||||
</refsect2>
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Examples</title>
|
<title>Example</title>
|
||||||
|
|
||||||
<example>
|
|
||||||
<title><filename>os-release</filename> file for Fedora Workstation</title>
|
|
||||||
|
|
||||||
<programlisting>NAME=Fedora
|
<programlisting>NAME=Fedora
|
||||||
VERSION="32 (Workstation Edition)"
|
VERSION="32 (Workstation Edition)"
|
||||||
@ -434,22 +420,6 @@ REDHAT_SUPPORT_PRODUCT_VERSION=32
|
|||||||
PRIVACY_POLICY_URL="https://fedoraproject.org/wiki/Legal:PrivacyPolicy"
|
PRIVACY_POLICY_URL="https://fedoraproject.org/wiki/Legal:PrivacyPolicy"
|
||||||
VARIANT="Workstation Edition"
|
VARIANT="Workstation Edition"
|
||||||
VARIANT_ID=workstation</programlisting>
|
VARIANT_ID=workstation</programlisting>
|
||||||
</example>
|
|
||||||
|
|
||||||
<example>
|
|
||||||
<title>Reading <filename>os-release</filename> in
|
|
||||||
<citerefentry><refentrytitle>sh</refentrytitle><manvolnum>1</manvolnum></citerefentry></title>
|
|
||||||
|
|
||||||
<programlisting><xi:include href="check-os-release.sh" parse="text" /></programlisting>
|
|
||||||
</example>
|
|
||||||
|
|
||||||
<example>
|
|
||||||
<title>Reading <filename>os-release</filename> in
|
|
||||||
<citerefentry><refentrytitle>python</refentrytitle><manvolnum>1</manvolnum></citerefentry></title>
|
|
||||||
|
|
||||||
<programlisting><xi:include href="check-os-release.py" parse="text" /></programlisting>
|
|
||||||
</example>
|
|
||||||
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
|||||||
@ -61,7 +61,7 @@ manpages = [
|
|||||||
['org.freedesktop.resolve1', '5', [], 'ENABLE_RESOLVE'],
|
['org.freedesktop.resolve1', '5', [], 'ENABLE_RESOLVE'],
|
||||||
['org.freedesktop.systemd1', '5', [], ''],
|
['org.freedesktop.systemd1', '5', [], ''],
|
||||||
['org.freedesktop.timedate1', '5', [], 'ENABLE_TIMEDATED'],
|
['org.freedesktop.timedate1', '5', [], 'ENABLE_TIMEDATED'],
|
||||||
['os-release', '5', ['initrd-release'], ''],
|
['os-release', '5', [], ''],
|
||||||
['pam_systemd', '8', [], 'HAVE_PAM'],
|
['pam_systemd', '8', [], 'HAVE_PAM'],
|
||||||
['pam_systemd_home', '8', [], 'ENABLE_PAM_HOME'],
|
['pam_systemd_home', '8', [], 'ENABLE_PAM_HOME'],
|
||||||
['portablectl', '1', [], 'ENABLE_PORTABLED'],
|
['portablectl', '1', [], 'ENABLE_PORTABLED'],
|
||||||
|
|||||||
@ -102,20 +102,20 @@ int manager_handle_action(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (handle == HANDLE_SUSPEND)
|
if (handle == HANDLE_SUSPEND)
|
||||||
supported = can_sleep(SLEEP_SUSPEND) > 0;
|
supported = can_sleep("suspend") > 0;
|
||||||
else if (handle == HANDLE_HIBERNATE)
|
else if (handle == HANDLE_HIBERNATE)
|
||||||
supported = can_sleep(SLEEP_HIBERNATE) > 0;
|
supported = can_sleep("hibernate") > 0;
|
||||||
else if (handle == HANDLE_HYBRID_SLEEP)
|
else if (handle == HANDLE_HYBRID_SLEEP)
|
||||||
supported = can_sleep(SLEEP_HYBRID_SLEEP) > 0;
|
supported = can_sleep("hybrid-sleep") > 0;
|
||||||
else if (handle == HANDLE_SUSPEND_THEN_HIBERNATE)
|
else if (handle == HANDLE_SUSPEND_THEN_HIBERNATE)
|
||||||
supported = can_sleep(SLEEP_SUSPEND_THEN_HIBERNATE) > 0;
|
supported = can_sleep("suspend-then-hibernate") > 0;
|
||||||
else if (handle == HANDLE_KEXEC)
|
else if (handle == HANDLE_KEXEC)
|
||||||
supported = access(KEXEC, X_OK) >= 0;
|
supported = access(KEXEC, X_OK) >= 0;
|
||||||
else
|
else
|
||||||
supported = true;
|
supported = true;
|
||||||
|
|
||||||
if (!supported && IN_SET(handle, HANDLE_HIBERNATE, HANDLE_HYBRID_SLEEP, HANDLE_SUSPEND_THEN_HIBERNATE)) {
|
if (!supported && IN_SET(handle, HANDLE_HIBERNATE, HANDLE_HYBRID_SLEEP, HANDLE_SUSPEND_THEN_HIBERNATE)) {
|
||||||
supported = can_sleep(SLEEP_SUSPEND) > 0;
|
supported = can_sleep("suspend") > 0;
|
||||||
if (supported) {
|
if (supported) {
|
||||||
log_notice("Requested %s operation is not supported, using regular suspend instead.",
|
log_notice("Requested %s operation is not supported, using regular suspend instead.",
|
||||||
handle_action_to_string(handle));
|
handle_action_to_string(handle));
|
||||||
|
|||||||
@ -1851,7 +1851,7 @@ static int method_do_shutdown_or_sleep(
|
|||||||
const char *action,
|
const char *action,
|
||||||
const char *action_multiple_sessions,
|
const char *action_multiple_sessions,
|
||||||
const char *action_ignore_inhibit,
|
const char *action_ignore_inhibit,
|
||||||
SleepOperation sleep_operation,
|
const char *sleep_verb,
|
||||||
bool with_flags,
|
bool with_flags,
|
||||||
sd_bus_error *error) {
|
sd_bus_error *error) {
|
||||||
|
|
||||||
@ -1894,14 +1894,14 @@ static int method_do_shutdown_or_sleep(
|
|||||||
return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS,
|
return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS,
|
||||||
"There's already a shutdown or sleep operation in progress");
|
"There's already a shutdown or sleep operation in progress");
|
||||||
|
|
||||||
if (sleep_operation >= 0) {
|
if (sleep_verb) {
|
||||||
r = can_sleep(sleep_operation);
|
r = can_sleep(sleep_verb);
|
||||||
if (r == -ENOSPC)
|
if (r == -ENOSPC)
|
||||||
return sd_bus_error_set(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED,
|
return sd_bus_error_set(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED,
|
||||||
"Not enough swap space for hibernation");
|
"Not enough swap space for hibernation");
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED,
|
return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED,
|
||||||
"Sleep verb \"%s\" not supported", sleep_operation_to_string(sleep_operation));
|
"Sleep verb \"%s\" not supported", sleep_verb);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -1928,7 +1928,7 @@ static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error
|
|||||||
"org.freedesktop.login1.power-off",
|
"org.freedesktop.login1.power-off",
|
||||||
"org.freedesktop.login1.power-off-multiple-sessions",
|
"org.freedesktop.login1.power-off-multiple-sessions",
|
||||||
"org.freedesktop.login1.power-off-ignore-inhibit",
|
"org.freedesktop.login1.power-off-ignore-inhibit",
|
||||||
_SLEEP_OPERATION_INVALID,
|
NULL,
|
||||||
sd_bus_message_is_method_call(message, NULL, "PowerOffWithFlags"),
|
sd_bus_message_is_method_call(message, NULL, "PowerOffWithFlags"),
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
@ -1943,7 +1943,7 @@ static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *
|
|||||||
"org.freedesktop.login1.reboot",
|
"org.freedesktop.login1.reboot",
|
||||||
"org.freedesktop.login1.reboot-multiple-sessions",
|
"org.freedesktop.login1.reboot-multiple-sessions",
|
||||||
"org.freedesktop.login1.reboot-ignore-inhibit",
|
"org.freedesktop.login1.reboot-ignore-inhibit",
|
||||||
_SLEEP_OPERATION_INVALID,
|
NULL,
|
||||||
sd_bus_message_is_method_call(message, NULL, "RebootWithFlags"),
|
sd_bus_message_is_method_call(message, NULL, "RebootWithFlags"),
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
@ -1958,7 +1958,7 @@ static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *er
|
|||||||
"org.freedesktop.login1.halt",
|
"org.freedesktop.login1.halt",
|
||||||
"org.freedesktop.login1.halt-multiple-sessions",
|
"org.freedesktop.login1.halt-multiple-sessions",
|
||||||
"org.freedesktop.login1.halt-ignore-inhibit",
|
"org.freedesktop.login1.halt-ignore-inhibit",
|
||||||
_SLEEP_OPERATION_INVALID,
|
NULL,
|
||||||
sd_bus_message_is_method_call(message, NULL, "HaltWithFlags"),
|
sd_bus_message_is_method_call(message, NULL, "HaltWithFlags"),
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
@ -1973,7 +1973,7 @@ static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error
|
|||||||
"org.freedesktop.login1.suspend",
|
"org.freedesktop.login1.suspend",
|
||||||
"org.freedesktop.login1.suspend-multiple-sessions",
|
"org.freedesktop.login1.suspend-multiple-sessions",
|
||||||
"org.freedesktop.login1.suspend-ignore-inhibit",
|
"org.freedesktop.login1.suspend-ignore-inhibit",
|
||||||
SLEEP_SUSPEND,
|
"suspend",
|
||||||
sd_bus_message_is_method_call(message, NULL, "SuspendWithFlags"),
|
sd_bus_message_is_method_call(message, NULL, "SuspendWithFlags"),
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
@ -1988,7 +1988,7 @@ static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_erro
|
|||||||
"org.freedesktop.login1.hibernate",
|
"org.freedesktop.login1.hibernate",
|
||||||
"org.freedesktop.login1.hibernate-multiple-sessions",
|
"org.freedesktop.login1.hibernate-multiple-sessions",
|
||||||
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||||
SLEEP_HIBERNATE,
|
"hibernate",
|
||||||
sd_bus_message_is_method_call(message, NULL, "HibernateWithFlags"),
|
sd_bus_message_is_method_call(message, NULL, "HibernateWithFlags"),
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
@ -2003,7 +2003,7 @@ static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_e
|
|||||||
"org.freedesktop.login1.hibernate",
|
"org.freedesktop.login1.hibernate",
|
||||||
"org.freedesktop.login1.hibernate-multiple-sessions",
|
"org.freedesktop.login1.hibernate-multiple-sessions",
|
||||||
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||||
SLEEP_HYBRID_SLEEP,
|
"hybrid-sleep",
|
||||||
sd_bus_message_is_method_call(message, NULL, "HybridSleepWithFlags"),
|
sd_bus_message_is_method_call(message, NULL, "HybridSleepWithFlags"),
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
@ -2018,7 +2018,7 @@ static int method_suspend_then_hibernate(sd_bus_message *message, void *userdata
|
|||||||
"org.freedesktop.login1.hibernate",
|
"org.freedesktop.login1.hibernate",
|
||||||
"org.freedesktop.login1.hibernate-multiple-sessions",
|
"org.freedesktop.login1.hibernate-multiple-sessions",
|
||||||
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||||
SLEEP_SUSPEND_THEN_HIBERNATE,
|
"hybrid-sleep",
|
||||||
sd_bus_message_is_method_call(message, NULL, "SuspendThenHibernateWithFlags"),
|
sd_bus_message_is_method_call(message, NULL, "SuspendThenHibernateWithFlags"),
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
@ -2317,7 +2317,7 @@ static int method_can_shutdown_or_sleep(
|
|||||||
const char *action,
|
const char *action,
|
||||||
const char *action_multiple_sessions,
|
const char *action_multiple_sessions,
|
||||||
const char *action_ignore_inhibit,
|
const char *action_ignore_inhibit,
|
||||||
SleepOperation sleep_operation,
|
const char *sleep_verb,
|
||||||
sd_bus_error *error) {
|
sd_bus_error *error) {
|
||||||
|
|
||||||
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
|
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
|
||||||
@ -2335,8 +2335,8 @@ static int method_can_shutdown_or_sleep(
|
|||||||
assert(action_multiple_sessions);
|
assert(action_multiple_sessions);
|
||||||
assert(action_ignore_inhibit);
|
assert(action_ignore_inhibit);
|
||||||
|
|
||||||
if (sleep_operation >= 0) {
|
if (sleep_verb) {
|
||||||
r = can_sleep(sleep_operation);
|
r = can_sleep(sleep_verb);
|
||||||
if (IN_SET(r, 0, -ENOSPC))
|
if (IN_SET(r, 0, -ENOSPC))
|
||||||
return sd_bus_reply_method_return(message, "s", "na");
|
return sd_bus_reply_method_return(message, "s", "na");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -2358,7 +2358,7 @@ static int method_can_shutdown_or_sleep(
|
|||||||
multiple_sessions = r > 0;
|
multiple_sessions = r > 0;
|
||||||
blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
|
blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
|
||||||
|
|
||||||
handle = handle_action_from_string(sleep_operation_to_string(sleep_operation));
|
handle = handle_action_from_string(sleep_verb);
|
||||||
if (handle >= 0) {
|
if (handle >= 0) {
|
||||||
const char *target;
|
const char *target;
|
||||||
|
|
||||||
@ -2434,7 +2434,7 @@ static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_e
|
|||||||
"org.freedesktop.login1.power-off",
|
"org.freedesktop.login1.power-off",
|
||||||
"org.freedesktop.login1.power-off-multiple-sessions",
|
"org.freedesktop.login1.power-off-multiple-sessions",
|
||||||
"org.freedesktop.login1.power-off-ignore-inhibit",
|
"org.freedesktop.login1.power-off-ignore-inhibit",
|
||||||
_SLEEP_OPERATION_INVALID,
|
NULL,
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2447,7 +2447,7 @@ static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_err
|
|||||||
"org.freedesktop.login1.reboot",
|
"org.freedesktop.login1.reboot",
|
||||||
"org.freedesktop.login1.reboot-multiple-sessions",
|
"org.freedesktop.login1.reboot-multiple-sessions",
|
||||||
"org.freedesktop.login1.reboot-ignore-inhibit",
|
"org.freedesktop.login1.reboot-ignore-inhibit",
|
||||||
_SLEEP_OPERATION_INVALID,
|
NULL,
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2460,7 +2460,7 @@ static int method_can_halt(sd_bus_message *message, void *userdata, sd_bus_error
|
|||||||
"org.freedesktop.login1.halt",
|
"org.freedesktop.login1.halt",
|
||||||
"org.freedesktop.login1.halt-multiple-sessions",
|
"org.freedesktop.login1.halt-multiple-sessions",
|
||||||
"org.freedesktop.login1.halt-ignore-inhibit",
|
"org.freedesktop.login1.halt-ignore-inhibit",
|
||||||
_SLEEP_OPERATION_INVALID,
|
NULL,
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2473,7 +2473,7 @@ static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_er
|
|||||||
"org.freedesktop.login1.suspend",
|
"org.freedesktop.login1.suspend",
|
||||||
"org.freedesktop.login1.suspend-multiple-sessions",
|
"org.freedesktop.login1.suspend-multiple-sessions",
|
||||||
"org.freedesktop.login1.suspend-ignore-inhibit",
|
"org.freedesktop.login1.suspend-ignore-inhibit",
|
||||||
SLEEP_SUSPEND,
|
"suspend",
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2486,7 +2486,7 @@ static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_
|
|||||||
"org.freedesktop.login1.hibernate",
|
"org.freedesktop.login1.hibernate",
|
||||||
"org.freedesktop.login1.hibernate-multiple-sessions",
|
"org.freedesktop.login1.hibernate-multiple-sessions",
|
||||||
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||||
SLEEP_HIBERNATE,
|
"hibernate",
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2499,7 +2499,7 @@ static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_b
|
|||||||
"org.freedesktop.login1.hibernate",
|
"org.freedesktop.login1.hibernate",
|
||||||
"org.freedesktop.login1.hibernate-multiple-sessions",
|
"org.freedesktop.login1.hibernate-multiple-sessions",
|
||||||
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||||
SLEEP_HYBRID_SLEEP,
|
"hybrid-sleep",
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2512,7 +2512,7 @@ static int method_can_suspend_then_hibernate(sd_bus_message *message, void *user
|
|||||||
"org.freedesktop.login1.hibernate",
|
"org.freedesktop.login1.hibernate",
|
||||||
"org.freedesktop.login1.hibernate-multiple-sessions",
|
"org.freedesktop.login1.hibernate-multiple-sessions",
|
||||||
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||||
SLEEP_SUSPEND_THEN_HIBERNATE,
|
"suspend-then-hibernate",
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -29,7 +29,6 @@
|
|||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "sleep-config.h"
|
#include "sleep-config.h"
|
||||||
#include "stdio-util.h"
|
#include "stdio-util.h"
|
||||||
#include "string-table.h"
|
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "time-util.h"
|
#include "time-util.h"
|
||||||
@ -49,12 +48,12 @@ int parse_sleep_config(SleepConfig **ret_sleep_config) {
|
|||||||
{ "Sleep", "AllowSuspendThenHibernate", config_parse_tristate, 0, &allow_s2h },
|
{ "Sleep", "AllowSuspendThenHibernate", config_parse_tristate, 0, &allow_s2h },
|
||||||
{ "Sleep", "AllowHybridSleep", config_parse_tristate, 0, &allow_hybrid_sleep },
|
{ "Sleep", "AllowHybridSleep", config_parse_tristate, 0, &allow_hybrid_sleep },
|
||||||
|
|
||||||
{ "Sleep", "SuspendMode", config_parse_strv, 0, sc->modes + SLEEP_SUSPEND },
|
{ "Sleep", "SuspendMode", config_parse_strv, 0, &sc->suspend_modes },
|
||||||
{ "Sleep", "SuspendState", config_parse_strv, 0, sc->states + SLEEP_SUSPEND },
|
{ "Sleep", "SuspendState", config_parse_strv, 0, &sc->suspend_states },
|
||||||
{ "Sleep", "HibernateMode", config_parse_strv, 0, sc->modes + SLEEP_HIBERNATE },
|
{ "Sleep", "HibernateMode", config_parse_strv, 0, &sc->hibernate_modes },
|
||||||
{ "Sleep", "HibernateState", config_parse_strv, 0, sc->states + SLEEP_HIBERNATE },
|
{ "Sleep", "HibernateState", config_parse_strv, 0, &sc->hibernate_states },
|
||||||
{ "Sleep", "HybridSleepMode", config_parse_strv, 0, sc->modes + SLEEP_HYBRID_SLEEP },
|
{ "Sleep", "HybridSleepMode", config_parse_strv, 0, &sc->hybrid_modes },
|
||||||
{ "Sleep", "HybridSleepState", config_parse_strv, 0, sc->states + SLEEP_HYBRID_SLEEP },
|
{ "Sleep", "HybridSleepState", config_parse_strv, 0, &sc->hybrid_states },
|
||||||
|
|
||||||
{ "Sleep", "HibernateDelaySec", config_parse_sec, 0, &sc->hibernate_delay_sec},
|
{ "Sleep", "HibernateDelaySec", config_parse_sec, 0, &sc->hibernate_delay_sec},
|
||||||
{}
|
{}
|
||||||
@ -70,29 +69,29 @@ int parse_sleep_config(SleepConfig **ret_sleep_config) {
|
|||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
/* use default values unless set */
|
/* use default values unless set */
|
||||||
sc->allow[SLEEP_SUSPEND] = allow_suspend != 0;
|
sc->allow_suspend = allow_suspend != 0;
|
||||||
sc->allow[SLEEP_HIBERNATE] = allow_hibernate != 0;
|
sc->allow_hibernate = allow_hibernate != 0;
|
||||||
sc->allow[SLEEP_HYBRID_SLEEP] = allow_hybrid_sleep >= 0 ? allow_hybrid_sleep
|
sc->allow_hybrid_sleep = allow_hybrid_sleep >= 0 ? allow_hybrid_sleep
|
||||||
: (allow_suspend != 0 && allow_hibernate != 0);
|
: (allow_suspend != 0 && allow_hibernate != 0);
|
||||||
sc->allow[SLEEP_SUSPEND_THEN_HIBERNATE] = allow_s2h >= 0 ? allow_s2h
|
sc->allow_s2h = allow_s2h >= 0 ? allow_s2h
|
||||||
: (allow_suspend != 0 && allow_hibernate != 0);
|
: (allow_suspend != 0 && allow_hibernate != 0);
|
||||||
|
|
||||||
if (!sc->states[SLEEP_SUSPEND])
|
if (!sc->suspend_states)
|
||||||
sc->states[SLEEP_SUSPEND] = strv_new("mem", "standby", "freeze");
|
sc->suspend_states = strv_new("mem", "standby", "freeze");
|
||||||
if (!sc->modes[SLEEP_HIBERNATE])
|
if (!sc->hibernate_modes)
|
||||||
sc->modes[SLEEP_HIBERNATE] = strv_new("platform", "shutdown");
|
sc->hibernate_modes = strv_new("platform", "shutdown");
|
||||||
if (!sc->states[SLEEP_HIBERNATE])
|
if (!sc->hibernate_states)
|
||||||
sc->states[SLEEP_HIBERNATE] = strv_new("disk");
|
sc->hibernate_states = strv_new("disk");
|
||||||
if (!sc->modes[SLEEP_HYBRID_SLEEP])
|
if (!sc->hybrid_modes)
|
||||||
sc->modes[SLEEP_HYBRID_SLEEP] = strv_new("suspend", "platform", "shutdown");
|
sc->hybrid_modes = strv_new("suspend", "platform", "shutdown");
|
||||||
if (!sc->states[SLEEP_HYBRID_SLEEP])
|
if (!sc->hybrid_states)
|
||||||
sc->states[SLEEP_HYBRID_SLEEP] = strv_new("disk");
|
sc->hybrid_states = strv_new("disk");
|
||||||
if (sc->hibernate_delay_sec == 0)
|
if (sc->hibernate_delay_sec == 0)
|
||||||
sc->hibernate_delay_sec = 2 * USEC_PER_HOUR;
|
sc->hibernate_delay_sec = 2 * USEC_PER_HOUR;
|
||||||
|
|
||||||
/* ensure values set for all required fields */
|
/* ensure values set for all required fields */
|
||||||
if (!sc->states[SLEEP_SUSPEND] || !sc->modes[SLEEP_HIBERNATE]
|
if (!sc->suspend_states || !sc->hibernate_modes
|
||||||
|| !sc->states[SLEEP_HIBERNATE] || !sc->modes[SLEEP_HYBRID_SLEEP] || !sc->states[SLEEP_HYBRID_SLEEP])
|
|| !sc->hibernate_states || !sc->hybrid_modes || !sc->hybrid_states)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
*ret_sleep_config = TAKE_PTR(sc);
|
*ret_sleep_config = TAKE_PTR(sc);
|
||||||
@ -589,15 +588,10 @@ int read_fiemap(int fd, struct fiemap **ret) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int can_sleep_internal(const SleepConfig *sleep_config, SleepOperation operation, bool check_allowed);
|
static int can_sleep_internal(const char *verb, bool check_allowed, const SleepConfig *sleep_config);
|
||||||
|
|
||||||
static bool can_s2h(const SleepConfig *sleep_config) {
|
static bool can_s2h(const SleepConfig *sleep_config) {
|
||||||
|
const char *p;
|
||||||
static const SleepOperation operations[] = {
|
|
||||||
SLEEP_SUSPEND,
|
|
||||||
SLEEP_HIBERNATE,
|
|
||||||
};
|
|
||||||
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!clock_supported(CLOCK_BOOTTIME_ALARM)) {
|
if (!clock_supported(CLOCK_BOOTTIME_ALARM)) {
|
||||||
@ -605,40 +599,42 @@ static bool can_s2h(const SleepConfig *sleep_config) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < ELEMENTSOF(operations); i++) {
|
FOREACH_STRING(p, "suspend", "hibernate") {
|
||||||
r = can_sleep_internal(sleep_config, operations[i], false);
|
r = can_sleep_internal(p, false, sleep_config);
|
||||||
if (IN_SET(r, 0, -ENOSPC)) {
|
if (IN_SET(r, 0, -ENOSPC, -EADV)) {
|
||||||
log_debug("Unable to %s system.", sleep_operation_to_string(operations[i]));
|
log_debug("Unable to %s system.", p);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to check if %s is possible: %m", sleep_operation_to_string(operations[i]));
|
return log_debug_errno(r, "Failed to check if %s is possible: %m", p);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int can_sleep_internal(
|
static int can_sleep_internal(const char *verb, bool check_allowed, const SleepConfig *sleep_config) {
|
||||||
const SleepConfig *sleep_config,
|
bool allow;
|
||||||
SleepOperation operation,
|
char **modes = NULL, **states = NULL;
|
||||||
bool check_allowed) {
|
int r;
|
||||||
|
|
||||||
assert(operation >= 0);
|
assert(STR_IN_SET(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate"));
|
||||||
assert(operation < _SLEEP_OPERATION_MAX);
|
|
||||||
|
|
||||||
if (check_allowed && !sleep_config->allow[operation]) {
|
r = sleep_settings(verb, sleep_config, &allow, &modes, &states);
|
||||||
log_debug("Sleep mode \"%s\" is disabled by configuration.", sleep_operation_to_string(operation));
|
if (r < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (check_allowed && !allow) {
|
||||||
|
log_debug("Sleep mode \"%s\" is disabled by configuration.", verb);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operation == SLEEP_SUSPEND_THEN_HIBERNATE)
|
if (streq(verb, "suspend-then-hibernate"))
|
||||||
return can_s2h(sleep_config);
|
return can_s2h(sleep_config);
|
||||||
|
|
||||||
if (can_sleep_state(sleep_config->states[operation]) <= 0 ||
|
if (!can_sleep_state(states) || !can_sleep_disk(modes))
|
||||||
can_sleep_disk(sleep_config->modes[operation]) <= 0)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (operation == SLEEP_SUSPEND)
|
if (streq(verb, "suspend"))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!enough_swap_for_hibernation())
|
if (!enough_swap_for_hibernation())
|
||||||
@ -647,7 +643,7 @@ static int can_sleep_internal(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int can_sleep(SleepOperation operation) {
|
int can_sleep(const char *verb) {
|
||||||
_cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL;
|
_cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -655,26 +651,51 @@ int can_sleep(SleepOperation operation) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
return can_sleep_internal(sleep_config, operation, true);
|
return can_sleep_internal(verb, true, sleep_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sleep_settings(const char *verb, const SleepConfig *sleep_config, bool *ret_allow, char ***ret_modes, char ***ret_states) {
|
||||||
|
|
||||||
|
assert(verb);
|
||||||
|
assert(sleep_config);
|
||||||
|
assert(STR_IN_SET(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate"));
|
||||||
|
|
||||||
|
if (streq(verb, "suspend")) {
|
||||||
|
*ret_allow = sleep_config->allow_suspend;
|
||||||
|
*ret_modes = sleep_config->suspend_modes;
|
||||||
|
*ret_states = sleep_config->suspend_states;
|
||||||
|
} else if (streq(verb, "hibernate")) {
|
||||||
|
*ret_allow = sleep_config->allow_hibernate;
|
||||||
|
*ret_modes = sleep_config->hibernate_modes;
|
||||||
|
*ret_states = sleep_config->hibernate_states;
|
||||||
|
} else if (streq(verb, "hybrid-sleep")) {
|
||||||
|
*ret_allow = sleep_config->allow_hybrid_sleep;
|
||||||
|
*ret_modes = sleep_config->hybrid_modes;
|
||||||
|
*ret_states = sleep_config->hybrid_states;
|
||||||
|
} else if (streq(verb, "suspend-then-hibernate")) {
|
||||||
|
*ret_allow = sleep_config->allow_s2h;
|
||||||
|
*ret_modes = *ret_states = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* suspend modes empty by default */
|
||||||
|
if ((!ret_modes && !streq(verb, "suspend")) || !ret_states)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No modes or states set for %s; Check sleep.conf", verb);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SleepConfig* free_sleep_config(SleepConfig *sc) {
|
SleepConfig* free_sleep_config(SleepConfig *sc) {
|
||||||
if (!sc)
|
if (!sc)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for (SleepOperation i = 0; i < _SLEEP_OPERATION_MAX; i++) {
|
strv_free(sc->suspend_modes);
|
||||||
strv_free(sc->modes[i]);
|
strv_free(sc->suspend_states);
|
||||||
strv_free(sc->states[i]);
|
|
||||||
}
|
strv_free(sc->hibernate_modes);
|
||||||
|
strv_free(sc->hibernate_states);
|
||||||
|
|
||||||
|
strv_free(sc->hybrid_modes);
|
||||||
|
strv_free(sc->hybrid_states);
|
||||||
|
|
||||||
return mfree(sc);
|
return mfree(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* const sleep_operation_table[_SLEEP_OPERATION_MAX] = {
|
|
||||||
[SLEEP_SUSPEND] = "suspend",
|
|
||||||
[SLEEP_HIBERNATE] = "hibernate",
|
|
||||||
[SLEEP_HYBRID_SLEEP] = "hybrid-sleep",
|
|
||||||
[SLEEP_SUSPEND_THEN_HIBERNATE] = "suspend-then-hibernate",
|
|
||||||
};
|
|
||||||
|
|
||||||
DEFINE_STRING_TABLE_LOOKUP(sleep_operation, SleepOperation);
|
|
||||||
|
|||||||
@ -4,20 +4,20 @@
|
|||||||
#include <linux/fiemap.h>
|
#include <linux/fiemap.h>
|
||||||
#include "time-util.h"
|
#include "time-util.h"
|
||||||
|
|
||||||
typedef enum SleepOperation {
|
|
||||||
SLEEP_SUSPEND,
|
|
||||||
SLEEP_HIBERNATE,
|
|
||||||
SLEEP_HYBRID_SLEEP,
|
|
||||||
SLEEP_SUSPEND_THEN_HIBERNATE,
|
|
||||||
_SLEEP_OPERATION_MAX,
|
|
||||||
_SLEEP_OPERATION_INVALID = -EINVAL,
|
|
||||||
} SleepOperation;
|
|
||||||
|
|
||||||
typedef struct SleepConfig {
|
typedef struct SleepConfig {
|
||||||
bool allow[_SLEEP_OPERATION_MAX];
|
bool allow_suspend; /* AllowSuspend */
|
||||||
char **modes[_SLEEP_OPERATION_MAX];
|
bool allow_hibernate; /* AllowHibernation */
|
||||||
char **states[_SLEEP_OPERATION_MAX];
|
bool allow_s2h; /* AllowSuspendThenHibernate */
|
||||||
usec_t hibernate_delay_sec;
|
bool allow_hybrid_sleep; /* AllowHybridSleep */
|
||||||
|
|
||||||
|
char **suspend_modes; /* SuspendMode */
|
||||||
|
char **suspend_states; /* SuspendState */
|
||||||
|
char **hibernate_modes; /* HibernateMode */
|
||||||
|
char **hibernate_states; /* HibernateState */
|
||||||
|
char **hybrid_modes; /* HybridSleepMode */
|
||||||
|
char **hybrid_states; /* HybridSleepState */
|
||||||
|
|
||||||
|
usec_t hibernate_delay_sec; /* HibernateDelaySec */
|
||||||
} SleepConfig;
|
} SleepConfig;
|
||||||
|
|
||||||
SleepConfig* free_sleep_config(SleepConfig *sc);
|
SleepConfig* free_sleep_config(SleepConfig *sc);
|
||||||
@ -48,13 +48,12 @@ typedef struct HibernateLocation {
|
|||||||
HibernateLocation* hibernate_location_free(HibernateLocation *hl);
|
HibernateLocation* hibernate_location_free(HibernateLocation *hl);
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(HibernateLocation*, hibernate_location_free);
|
DEFINE_TRIVIAL_CLEANUP_FUNC(HibernateLocation*, hibernate_location_free);
|
||||||
|
|
||||||
|
int sleep_settings(const char *verb, const SleepConfig *sleep_config, bool *ret_allow, char ***ret_modes, char ***ret_states);
|
||||||
|
|
||||||
int read_fiemap(int fd, struct fiemap **ret);
|
int read_fiemap(int fd, struct fiemap **ret);
|
||||||
int parse_sleep_config(SleepConfig **sleep_config);
|
int parse_sleep_config(SleepConfig **sleep_config);
|
||||||
int find_hibernate_location(HibernateLocation **ret_hibernate_location);
|
int find_hibernate_location(HibernateLocation **ret_hibernate_location);
|
||||||
|
|
||||||
int can_sleep(SleepOperation operation);
|
int can_sleep(const char *verb);
|
||||||
int can_sleep_disk(char **types);
|
int can_sleep_disk(char **types);
|
||||||
int can_sleep_state(char **types);
|
int can_sleep_state(char **types);
|
||||||
|
|
||||||
const char* sleep_operation_to_string(SleepOperation s) _const_;
|
|
||||||
SleepOperation sleep_operation_from_string(const char *s) _pure_;
|
|
||||||
|
|||||||
@ -35,7 +35,9 @@
|
|||||||
#include "time-util.h"
|
#include "time-util.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
static SleepOperation arg_operation = _SLEEP_OPERATION_INVALID;
|
static char* arg_verb = NULL;
|
||||||
|
|
||||||
|
STATIC_DESTRUCTOR_REGISTER(arg_verb, freep);
|
||||||
|
|
||||||
static int write_hibernate_location_info(const HibernateLocation *hibernate_location) {
|
static int write_hibernate_location_info(const HibernateLocation *hibernate_location) {
|
||||||
char offset_str[DECIMAL_STR_MAX(uint64_t)];
|
char offset_str[DECIMAL_STR_MAX(uint64_t)];
|
||||||
@ -167,17 +169,11 @@ static int lock_all_homes(void) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int execute(
|
static int execute(char **modes, char **states, const char *action) {
|
||||||
const SleepConfig *sleep_config,
|
|
||||||
SleepOperation operation,
|
|
||||||
const char *action) {
|
|
||||||
|
|
||||||
char *arguments[] = {
|
char *arguments[] = {
|
||||||
NULL,
|
NULL,
|
||||||
(char*) "pre",
|
(char*) "pre",
|
||||||
/* NB: we use 'arg_operation' instead of 'operation' here, as we want to communicate the overall
|
arg_verb,
|
||||||
* operation here, not the specific one, in case of s2h. */
|
|
||||||
(char*) sleep_operation_to_string(arg_operation),
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
static const char* const dirs[] = {
|
static const char* const dirs[] = {
|
||||||
@ -185,24 +181,10 @@ static int execute(
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
_cleanup_(hibernate_location_freep) HibernateLocation *hibernate_location = NULL;
|
|
||||||
_cleanup_fclose_ FILE *f = NULL;
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
char **modes, **states;
|
_cleanup_(hibernate_location_freep) HibernateLocation *hibernate_location = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(sleep_config);
|
|
||||||
assert(operation >= 0);
|
|
||||||
assert(operation < _SLEEP_OPERATION_MAX);
|
|
||||||
assert(operation != SLEEP_SUSPEND_THEN_HIBERNATE); /* Handled by execute_s2h() instead */
|
|
||||||
|
|
||||||
states = sleep_config->states[operation];
|
|
||||||
modes = sleep_config->modes[operation];
|
|
||||||
|
|
||||||
if (strv_isempty(states))
|
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
||||||
"No sleep states configured for sleep operation %s, can't sleep.",
|
|
||||||
sleep_operation_to_string(operation));
|
|
||||||
|
|
||||||
/* This file is opened first, so that if we hit an error,
|
/* This file is opened first, so that if we hit an error,
|
||||||
* we can abort before modifying any state. */
|
* we can abort before modifying any state. */
|
||||||
f = fopen("/sys/power/state", "we");
|
f = fopen("/sys/power/state", "we");
|
||||||
@ -229,34 +211,29 @@ static int execute(
|
|||||||
return log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");;
|
return log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pass an action string to the call-outs. This is mostly our operation string, except if the
|
|
||||||
* hibernate step of s-t-h fails, in which case we communicate that with a separate action. */
|
|
||||||
if (!action)
|
|
||||||
action = sleep_operation_to_string(operation);
|
|
||||||
|
|
||||||
r = setenv("SYSTEMD_SLEEP_ACTION", action, 1);
|
r = setenv("SYSTEMD_SLEEP_ACTION", action, 1);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
log_warning_errno(errno, "Error setting SYSTEMD_SLEEP_ACTION=%s, ignoring: %m", action);
|
log_warning_errno(errno, "Error setting SYSTEMD_SLEEP_ACTION=%s: %m", action);
|
||||||
|
|
||||||
(void) execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
|
(void) execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
|
||||||
(void) lock_all_homes();
|
(void) lock_all_homes();
|
||||||
|
|
||||||
log_struct(LOG_INFO,
|
log_struct(LOG_INFO,
|
||||||
"MESSAGE_ID=" SD_MESSAGE_SLEEP_START_STR,
|
"MESSAGE_ID=" SD_MESSAGE_SLEEP_START_STR,
|
||||||
LOG_MESSAGE("Entering sleep state '%s'...", sleep_operation_to_string(operation)),
|
LOG_MESSAGE("Suspending system..."),
|
||||||
"SLEEP=%s", sleep_operation_to_string(arg_operation));
|
"SLEEP=%s", arg_verb);
|
||||||
|
|
||||||
r = write_state(&f, states);
|
r = write_state(&f, states);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_struct_errno(LOG_ERR, r,
|
log_struct_errno(LOG_ERR, r,
|
||||||
"MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR,
|
"MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR,
|
||||||
LOG_MESSAGE("Failed to put system to sleep. System resumed again: %m"),
|
LOG_MESSAGE("Failed to suspend system. System resumed again: %m"),
|
||||||
"SLEEP=%s", sleep_operation_to_string(arg_operation));
|
"SLEEP=%s", arg_verb);
|
||||||
else
|
else
|
||||||
log_struct(LOG_INFO,
|
log_struct(LOG_INFO,
|
||||||
"MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR,
|
"MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR,
|
||||||
LOG_MESSAGE("System returned from sleep state."),
|
LOG_MESSAGE("System resumed."),
|
||||||
"SLEEP=%s", sleep_operation_to_string(arg_operation));
|
"SLEEP=%s", arg_verb);
|
||||||
|
|
||||||
arguments[1] = (char*) "post";
|
arguments[1] = (char*) "post";
|
||||||
(void) execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
|
(void) execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
|
||||||
@ -285,7 +262,7 @@ static int execute_s2h(const SleepConfig *sleep_config) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(errno, "Error setting hibernate timer: %m");
|
return log_error_errno(errno, "Error setting hibernate timer: %m");
|
||||||
|
|
||||||
r = execute(sleep_config, SLEEP_SUSPEND, NULL);
|
r = execute(sleep_config->suspend_modes, sleep_config->suspend_states, "suspend");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -301,13 +278,13 @@ static int execute_s2h(const SleepConfig *sleep_config) {
|
|||||||
log_debug("Attempting to hibernate after waking from %s timer",
|
log_debug("Attempting to hibernate after waking from %s timer",
|
||||||
format_timespan(buf, sizeof(buf), sleep_config->hibernate_delay_sec, USEC_PER_SEC));
|
format_timespan(buf, sizeof(buf), sleep_config->hibernate_delay_sec, USEC_PER_SEC));
|
||||||
|
|
||||||
r = execute(sleep_config, SLEEP_HIBERNATE, NULL);
|
r = execute(sleep_config->hibernate_modes, sleep_config->hibernate_states, "hibernate");
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_notice("Couldn't hibernate, will try to suspend again.");
|
log_notice_errno(r, "Couldn't hibernate, will try to suspend again: %m");
|
||||||
|
|
||||||
r = execute(sleep_config, SLEEP_SUSPEND, "suspend-after-failed-hibernate");
|
r = execute(sleep_config->suspend_modes, sleep_config->suspend_states, "suspend-after-failed-hibernate");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return log_error_errno(r, "Could neither hibernate nor suspend, giving up: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -374,14 +351,20 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
"Usage: %s COMMAND",
|
"Usage: %s COMMAND",
|
||||||
program_invocation_short_name);
|
program_invocation_short_name);
|
||||||
|
|
||||||
arg_operation = sleep_operation_from_string(argv[optind]);
|
arg_verb = strdup(argv[optind]);
|
||||||
if (arg_operation < 0)
|
if (!arg_verb)
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown command '%s'.", argv[optind]);
|
return log_oom();
|
||||||
|
|
||||||
|
if (!STR_IN_SET(arg_verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate"))
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
|
"Unknown command '%s'.", arg_verb);
|
||||||
|
|
||||||
return 1 /* work to do */;
|
return 1 /* work to do */;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int run(int argc, char *argv[]) {
|
static int run(int argc, char *argv[]) {
|
||||||
|
bool allow;
|
||||||
|
char **modes = NULL, **states = NULL;
|
||||||
_cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL;
|
_cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -395,37 +378,19 @@ static int run(int argc, char *argv[]) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (!sleep_config->allow[arg_operation])
|
r = sleep_settings(arg_verb, sleep_config, &allow, &modes, &states);
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EACCES),
|
if (r < 0)
|
||||||
"Sleep operation \"%s\" is disabled by configuration, refusing.",
|
|
||||||
sleep_operation_to_string(arg_operation));
|
|
||||||
|
|
||||||
switch (arg_operation) {
|
|
||||||
|
|
||||||
case SLEEP_SUSPEND_THEN_HIBERNATE:
|
|
||||||
r = execute_s2h(sleep_config);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SLEEP_HYBRID_SLEEP:
|
|
||||||
r = execute(sleep_config, SLEEP_HYBRID_SLEEP, NULL);
|
|
||||||
if (r < 0) {
|
|
||||||
/* If we can't hybrid sleep, then let's try to suspend at least. After all, the user
|
|
||||||
* asked us to do both: suspend + hibernate, and it's almost certainly the
|
|
||||||
* hibernation that failed, hence still do the other thing, the suspend. */
|
|
||||||
|
|
||||||
log_notice("Couldn't hybrid sleep, will try to suspend instead.");
|
|
||||||
|
|
||||||
r = execute(sleep_config, SLEEP_SUSPEND, "suspend-after-failed-hybrid-sleep");
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
r = execute(sleep_config, arg_operation, NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
if (!allow)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EACCES),
|
||||||
|
"Sleep mode \"%s\" is disabled by configuration, refusing.",
|
||||||
|
arg_verb);
|
||||||
|
|
||||||
|
if (streq(arg_verb, "suspend-then-hibernate"))
|
||||||
|
return execute_s2h(sleep_config);
|
||||||
|
else
|
||||||
|
return execute(modes, states, arg_verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_MAIN_FUNCTION(run);
|
DEFINE_MAIN_FUNCTION(run);
|
||||||
|
|||||||
@ -25,16 +25,16 @@ static void test_parse_sleep_config(void) {
|
|||||||
|
|
||||||
_cleanup_free_ char *sum, *sus, *him, *his, *hym, *hys;
|
_cleanup_free_ char *sum, *sus, *him, *his, *hym, *hys;
|
||||||
|
|
||||||
sum = strv_join(sleep_config->modes[SLEEP_SUSPEND], ", ");
|
sum = strv_join(sleep_config->suspend_modes, ", ");
|
||||||
sus = strv_join(sleep_config->states[SLEEP_SUSPEND], ", ");
|
sus = strv_join(sleep_config->suspend_states, ", ");
|
||||||
him = strv_join(sleep_config->modes[SLEEP_HIBERNATE], ", ");
|
him = strv_join(sleep_config->hibernate_modes, ", ");
|
||||||
his = strv_join(sleep_config->states[SLEEP_HIBERNATE], ", ");
|
his = strv_join(sleep_config->hibernate_states, ", ");
|
||||||
hym = strv_join(sleep_config->modes[SLEEP_HYBRID_SLEEP], ", ");
|
hym = strv_join(sleep_config->hybrid_modes, ", ");
|
||||||
hys = strv_join(sleep_config->states[SLEEP_HYBRID_SLEEP], ", ");
|
hys = strv_join(sleep_config->hybrid_states, ", ");
|
||||||
log_debug(" allow_suspend: %u", sleep_config->allow[SLEEP_SUSPEND]);
|
log_debug(" allow_suspend: %u", sleep_config->allow_suspend);
|
||||||
log_debug(" allow_hibernate: %u", sleep_config->allow[SLEEP_HIBERNATE]);
|
log_debug(" allow_hibernate: %u", sleep_config->allow_hibernate);
|
||||||
log_debug(" allow_s2h: %u", sleep_config->allow[SLEEP_SUSPEND_THEN_HIBERNATE]);
|
log_debug(" allow_s2h: %u", sleep_config->allow_s2h);
|
||||||
log_debug(" allow_hybrid_sleep: %u", sleep_config->allow[SLEEP_HYBRID_SLEEP]);
|
log_debug(" allow_hybrid_sleep: %u", sleep_config->allow_hybrid_sleep);
|
||||||
log_debug(" suspend modes: %s", sum);
|
log_debug(" suspend modes: %s", sum);
|
||||||
log_debug(" states: %s", sus);
|
log_debug(" states: %s", sus);
|
||||||
log_debug(" hibernate modes: %s", him);
|
log_debug(" hibernate modes: %s", him);
|
||||||
@ -98,13 +98,13 @@ static void test_sleep(void) {
|
|||||||
log_info("Freeze configured: %s", yes_no(can_sleep_state(freeze) > 0));
|
log_info("Freeze configured: %s", yes_no(can_sleep_state(freeze) > 0));
|
||||||
|
|
||||||
log_info("/= high-level sleep verbs =/");
|
log_info("/= high-level sleep verbs =/");
|
||||||
r = can_sleep(SLEEP_SUSPEND);
|
r = can_sleep("suspend");
|
||||||
log_info("Suspend configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
|
log_info("Suspend configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
|
||||||
r = can_sleep(SLEEP_HIBERNATE);
|
r = can_sleep("hibernate");
|
||||||
log_info("Hibernation configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
|
log_info("Hibernation configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
|
||||||
r = can_sleep(SLEEP_HYBRID_SLEEP);
|
r = can_sleep("hybrid-sleep");
|
||||||
log_info("Hybrid-sleep configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
|
log_info("Hybrid-sleep configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
|
||||||
r = can_sleep(SLEEP_SUSPEND_THEN_HIBERNATE);
|
r = can_sleep("suspend-then-hibernate");
|
||||||
log_info("Suspend-then-Hibernate configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
|
log_info("Suspend-then-Hibernate configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user