os-release: define /usr/lib/os-release as fallback for /etc/os-release

The file should have been in /usr/lib/ in the first place, since it
describes the OS container in /usr (and not the configuration in /etc),
hence, let's support os-release files in /usr/lib as fallback if no
version in /etc exists, following the usual override logic.

A prior commit already enabled tmpfiles to create /etc/os-release as a
symlink to /usr/lib/os-release should it be missing, thus providing nice
compatibility with applications only checking in /etc.

While it's probably a good idea if all apps check both locations via a
fallback logic, it is only necessary in the early boot process, as long
as the /etc/os-release symlink has not been restored, in case we boot
with an empty /etc.
This commit is contained in:
Lennart Poettering 2014-06-13 19:45:52 +02:00
parent b0284aba93
commit 5ae4d543cb
11 changed files with 76 additions and 26 deletions

View File

@ -95,14 +95,20 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<para>The kernel-install plugin <filename>50-depmod.install</filename> runs depmod for the <replaceable>KERNEL-VERSION</replaceable>.</para>
<para>The kernel-install plugin <filename>90-loaderentry.install</filename> copies
<para>The kernel-install plugin
<filename>90-loaderentry.install</filename> copies
<replaceable>KERNEL-IMAGE</replaceable> to
<filename>/boot/<replaceable>MACHINE-ID</replaceable>/<replaceable>KERNEL-VERSION</replaceable>/linux</filename>.
It also creates a boot loader entry according to the boot loader specification in
It also creates a boot loader entry according to the boot
loader specification in
<filename>/boot/loader/entries/<replaceable>MACHINE-ID</replaceable>-<replaceable>KERNEL-VERSION</replaceable>.conf</filename>.
The title of the entry is the <replaceable>PRETTY_NAME</replaceable> parameter specified in <filename>/etc/os-release</filename>,
or "Linux <replaceable>KERNEL-VERSION</replaceable>", if unset.
If the file <filename>initrd</filename> is found next to the
The title of the entry is the
<replaceable>PRETTY_NAME</replaceable> parameter specified
in <filename>/etc/os-release</filename> or
<filename>/usr/lib/os-release</filename> (if the former is
missing), or "Linux
<replaceable>KERNEL-VERSION</replaceable>", if unset. If
the file <filename>initrd</filename> is found next to the
<filename>linux</filename> file, the initrd will be added to
the configuration.</para>
</listitem>
@ -165,6 +171,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
<varlistentry>
<term>
<filename>/etc/os-release</filename>
<filename>/usr/lib/os-release</filename>
</term>
<listitem>
<para>The content of the file specifies the operating system title <replaceable>PRETTY_NAME</replaceable>.</para>

View File

@ -49,13 +49,15 @@
<refsynopsisdiv>
<para><filename>/etc/os-release</filename></para>
<para><filename>/usr/lib/os-release</filename></para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>The <filename>/etc/os-release</filename> file
contains operating system identification data.</para>
<para>The <filename>/etc/os-release</filename> and
<filename>/usr/lib/os-release</filename> files contain
operating system identification data.</para>
<para>The basic file format of
<filename>os-release</filename> is a newline-separated
@ -78,20 +80,38 @@
strings. Lines beginning with "#" shall be ignored as
comments.</para>
<para><filename>/etc/os-release</filename> contains
data that is defined by the operating system vendor
and should not be changed by the administrator.</para>
<para>The file <filename>/etc/os-release</filename>
takes precedence over
<filename>/usr/lib/os-release</filename>. Applications
should check for the former, and exclusively use its
data if it exists, and only fall back to
<filename>/usr/lib/os-release</filename> if it is
missing. Applications should not read data from both
files at the same
time. <filename>/usr/lib/os-release</filename> is the
recommended place to store OS release information as
part of vendor trees. Frequently
<filename>/etc/os-release</filename> is simply a
symlink to <filename>/usr/lib/os-release</filename>,
to provide compatibility with applications only
looking at <filename>/etc</filename>.</para>
<para><filename>os-release</filename> contains data
that is defined by the operating system vendor and
should generally not be changed by the
administrator.</para>
<para>As this file only encodes names and identifiers
it should not be localized.</para>
<para>The file <filename>/etc/os-release</filename> might
be a symlink to another file, but it is important that
<para>The <filename>/etc/os-release</filename> and
<filename>/usr/lib/os-release</filename> files might
be symlinks to other files, but it is important that
the file is available from earliest boot on, and hence
must be located on the root file system.</para>
<para>For a longer rationale for
<filename>/etc/os-release</filename> please refer to
<filename>os-release</filename> please refer to
the <ulink
url="http://0pointer.de/blog/projects/os-release">Announcement of <filename>/etc/os-release</filename></ulink>.</para>
</refsect1>
@ -100,7 +120,7 @@
<title>Options</title>
<para>The following OS identifications parameters may be set using
<filename>/etc/os-release</filename>:</para>
<filename>os-release</filename>:</para>
<variablelist>

View File

@ -136,8 +136,9 @@
<para>As a safety check
<command>systemd-nspawn</command> will verify the
existence of <filename>/etc/os-release</filename> in
the container tree before starting the container (see
existence of <filename>/usr/lib/os-release</filename>
or <filename>/etc/os-release</filename> in the
container tree before starting the container (see
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>). It
might be necessary to add this file to the container
tree manually if the OS of the container is too old to

View File

@ -386,10 +386,10 @@ int main(int argc, char *argv[]) {
if (sysfd < 0)
sysfd = open("/sys", O_RDONLY|O_CLOEXEC);
if (!build)
parse_env_file("/etc/os-release", NEWLINE,
"PRETTY_NAME", &build,
NULL);
if (!build) {
if (parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &build, NULL) == -ENOENT)
parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &build, NULL);
}
/* wait for /proc to become available, discarding samples */
if (graph_start <= 0.0)

View File

@ -1191,7 +1191,7 @@ static int method_switch_root(sd_bus *bus, sd_bus_message *message, void *userda
/* Safety check */
if (isempty(init)) {
if (! path_is_os_tree(root))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified switch root path %s does not seem to be an OS tree. /etc/os-release is missing.", root);
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified switch root path %s does not seem to be an OS tree. os-release file is missing.", root);
} else {
_cleanup_free_ char *p = NULL;

View File

@ -1251,9 +1251,15 @@ static int status_welcome(void) {
"PRETTY_NAME", &pretty_name,
"ANSI_COLOR", &ansi_color,
NULL);
if (r == -ENOENT) {
r = parse_env_file("/usr/lib/os-release", NEWLINE,
"PRETTY_NAME", &pretty_name,
"ANSI_COLOR", &ansi_color,
NULL);
}
if (r < 0 && r != -ENOENT)
log_warning("Failed to read /etc/os-release: %s", strerror(-r));
log_warning("Failed to read os-release file: %s", strerror(-r));
return status_printf(NULL, false, false,
"\nWelcome to \x1B[%sm%s\x1B[0m!\n",

View File

@ -108,6 +108,13 @@ static int context_read_data(Context *c) {
"PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME],
"CPE_NAME", &c->data[PROP_OS_CPE_NAME],
NULL);
if (r == -ENOENT) {
r = parse_env_file("/usr/lib/os-release", NEWLINE,
"PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME],
"CPE_NAME", &c->data[PROP_OS_CPE_NAME],
NULL);
}
if (r < 0 && r != -ENOENT)
return r;

View File

@ -767,7 +767,8 @@ static int request_handler_machine(
if (r < 0)
return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s\n", strerror(-r));
parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL);
if (parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL) == -ENOENT)
parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL);
get_virtualization(&v);

View File

@ -32,6 +32,8 @@ fi
if [[ -f /etc/os-release ]]; then
. /etc/os-release
elif [[ -f /usr/lib/os-release ]]; then
. /usr/lib/os-release
fi
if ! [[ $PRETTY_NAME ]]; then

View File

@ -2799,7 +2799,7 @@ int main(int argc, char *argv[]) {
if (arg_boot) {
if (path_is_os_tree(arg_directory) <= 0) {
log_error("Directory %s doesn't look like an OS root directory (/etc/os-release is missing). Refusing.", arg_directory);
log_error("Directory %s doesn't look like an OS root directory (os-release file is missing). Refusing.", arg_directory);
goto finish;
}
} else {

View File

@ -526,12 +526,18 @@ int path_is_os_tree(const char *path) {
char *p;
int r;
/* We use /etc/os-release as flag file if something is an OS */
/* We use /usr/lib/os-release as flag file if something is an OS */
p = strappenda(path, "/usr/lib/os-release");
r = access(p, F_OK);
if (r >= 0)
return 1;
/* Also check for the old location in /etc, just in case. */
p = strappenda(path, "/etc/os-release");
r = access(p, F_OK);
return r < 0 ? 0 : 1;
return r >= 0;
}
int find_binary(const char *name, char **filename) {