summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2018-03-26 16:32:40 +0200
committerLennart Poettering <lennart@poettering.net>2018-05-24 17:01:57 +0200
commitd58ad743f98b3a88de961462fb7adedbf30f727d (patch)
tree0978f88d2e97ef6aacd032b0c6540c70906f5207
parent080dfda85a9fc4bd471bc056a570d9eab411efa2 (diff)
downloadsystemd-d58ad743f98b3a88de961462fb7adedbf30f727d.tar.gz
systemd-d58ad743f98b3a88de961462fb7adedbf30f727d.tar.bz2
systemd-d58ad743f98b3a88de961462fb7adedbf30f727d.zip
os-util: add helpers for finding /etc/os-release
Place this new helpers in a new source file os-util.[ch], and move the existing and related call path_is_os_tree() to it as well.
-rw-r--r--src/basic/meson.build2
-rw-r--r--src/basic/os-util.c117
-rw-r--r--src/basic/os-util.h12
-rw-r--r--src/basic/stat-util.c26
-rw-r--r--src/basic/stat-util.h1
-rw-r--r--src/core/dbus-manager.c1
-rw-r--r--src/core/main.c20
-rw-r--r--src/firstboot/firstboot.c20
-rw-r--r--src/hostname/hostnamed.c18
-rw-r--r--src/journal-remote/journal-gatewayd.c7
-rw-r--r--src/machine/machine-dbus.c14
-rw-r--r--src/nspawn/nspawn.c1
-rw-r--r--src/shared/dissect-image.c1
-rw-r--r--src/shared/machine-image.c17
-rw-r--r--src/test/meson.build4
-rw-r--r--src/test/test-os-util.c22
-rw-r--r--src/test/test-stat-util.c7
17 files changed, 193 insertions, 97 deletions
diff --git a/src/basic/meson.build b/src/basic/meson.build
index 69c525dcdc..0b2106807c 100644
--- a/src/basic/meson.build
+++ b/src/basic/meson.build
@@ -131,6 +131,8 @@ basic_sources = files('''
ordered-set.h
pager.c
pager.h
+ os-util.c
+ os-util.h
parse-util.c
parse-util.h
path-util.c
diff --git a/src/basic/os-util.c b/src/basic/os-util.c
new file mode 100644
index 0000000000..207594cef8
--- /dev/null
+++ b/src/basic/os-util.c
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fs-util.h"
+#include "macro.h"
+#include "os-util.h"
+#include "strv.h"
+#include "fileio.h"
+#include "string-util.h"
+
+int path_is_os_tree(const char *path) {
+ int r;
+
+ assert(path);
+
+ /* Does the path exist at all? If not, generate an error immediately. This is useful so that a missing root dir
+ * always results in -ENOENT, and we can properly distuingish the case where the whole root doesn't exist from
+ * the case where just the os-release file is missing. */
+ if (laccess(path, F_OK) < 0)
+ return -errno;
+
+ /* We use {/etc|/usr/lib}/os-release as flag file if something is an OS */
+ r = open_os_release(path, NULL, NULL);
+ if (r == -ENOENT) /* We got nothing */
+ return 0;
+ if (r < 0)
+ return r;
+
+ return 1;
+}
+
+int open_os_release(const char *root, char **ret_path, int *ret_fd) {
+ _cleanup_free_ char *q = NULL;
+ const char *p;
+ int k;
+
+ FOREACH_STRING(p, "/etc/os-release", "/usr/lib/os-release") {
+ k = chase_symlinks(p, root, CHASE_PREFIX_ROOT|(ret_fd ? CHASE_OPEN : 0), (ret_path ? &q : NULL));
+ if (k != -ENOENT)
+ break;
+ }
+ if (k < 0)
+ return k;
+
+ if (ret_fd) {
+ int real_fd;
+
+ /* Convert the O_PATH fd into a proper, readable one */
+ real_fd = fd_reopen(k, O_RDONLY|O_CLOEXEC|O_NOCTTY);
+ safe_close(k);
+ if (real_fd < 0)
+ return real_fd;
+
+ *ret_fd = real_fd;
+ }
+
+ if (ret_path)
+ *ret_path = TAKE_PTR(q);
+
+ return 0;
+}
+
+int fopen_os_release(const char *root, char **ret_path, FILE **ret_file) {
+ _cleanup_free_ char *p = NULL;
+ _cleanup_close_ int fd = -1;
+ FILE *f;
+ int r;
+
+ if (!ret_file)
+ return open_os_release(root, ret_path, NULL);
+
+ r = open_os_release(root, ret_path ? &p : NULL, &fd);
+ if (r < 0)
+ return r;
+
+ f = fdopen(fd, "re");
+ if (!f)
+ return -errno;
+ fd = -1;
+
+ *ret_file = f;
+
+ if (ret_path)
+ *ret_path = TAKE_PTR(p);
+
+ return 0;
+}
+
+int parse_os_release(const char *root, ...) {
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *p = NULL;
+ va_list ap;
+ int r;
+
+ r = fopen_os_release(root, &p, &f);
+ if (r < 0)
+ return r;
+
+ va_start(ap, root);
+ r = parse_env_filev(f, p, NEWLINE, ap);
+ va_end(ap);
+
+ return r;
+}
+
+int load_os_release_pairs(const char *root, char ***ret) {
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *p = NULL;
+ int r;
+
+ r = fopen_os_release(root, &p, &f);
+ if (r < 0)
+ return r;
+
+ return load_env_file_pairs(f, p, NEWLINE, ret);
+}
diff --git a/src/basic/os-util.h b/src/basic/os-util.h
new file mode 100644
index 0000000000..6b9e033941
--- /dev/null
+++ b/src/basic/os-util.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdio.h>
+
+int path_is_os_tree(const char *path);
+
+int open_os_release(const char *root, char **ret_path, int *ret_fd);
+int fopen_os_release(const char *root, char **ret_path, FILE **ret_file);
+
+int parse_os_release(const char *root, ...);
+int load_os_release_pairs(const char *root, char ***ret);
diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c
index 61cc6f5738..1f0a75a0e8 100644
--- a/src/basic/stat-util.c
+++ b/src/basic/stat-util.c
@@ -132,32 +132,6 @@ int path_is_read_only_fs(const char *path) {
return false;
}
-int path_is_os_tree(const char *path) {
- int r;
-
- assert(path);
-
- /* Does the path exist at all? If not, generate an error immediately. This is useful so that a missing root dir
- * always results in -ENOENT, and we can properly distuingish the case where the whole root doesn't exist from
- * the case where just the os-release file is missing. */
- if (laccess(path, F_OK) < 0)
- return -errno;
-
- /* We use /usr/lib/os-release as flag file if something is an OS */
- r = chase_symlinks("/usr/lib/os-release", path, CHASE_PREFIX_ROOT, NULL);
- if (r == -ENOENT) {
-
- /* Also check for the old location in /etc, just in case. */
- r = chase_symlinks("/etc/os-release", path, CHASE_PREFIX_ROOT, NULL);
- if (r == -ENOENT)
- return 0; /* We got nothing */
- }
- if (r < 0)
- return r;
-
- return 1;
-}
-
int files_same(const char *filea, const char *fileb, int flags) {
struct stat a, b;
diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h
index d1e8d33001..02b1c47123 100644
--- a/src/basic/stat-util.h
+++ b/src/basic/stat-util.h
@@ -35,7 +35,6 @@ int null_or_empty_path(const char *fn);
int null_or_empty_fd(int fd);
int path_is_read_only_fs(const char *path);
-int path_is_os_tree(const char *path);
int files_same(const char *filea, const char *fileb, int flags);
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 13d7bd476f..f7535e38fc 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -26,6 +26,7 @@
#include "fs-util.h"
#include "install.h"
#include "log.h"
+#include "os-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "selinux-access.h"
diff --git a/src/core/main.c b/src/core/main.c
index e7d89be3f4..7e5a7c22b7 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -57,6 +57,7 @@
#include "manager.h"
#include "missing.h"
#include "mount-setup.h"
+#include "os-util.h"
#include "pager.h"
#include "parse-util.h"
#include "path-util.h"
@@ -1215,23 +1216,18 @@ static int enforce_syscall_archs(Set *archs) {
static int status_welcome(void) {
_cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
- const char *fn;
int r;
if (arg_show_status <= 0)
return 0;
- FOREACH_STRING(fn, "/etc/os-release", "/usr/lib/os-release") {
- r = parse_env_file(NULL, fn, NEWLINE,
- "PRETTY_NAME", &pretty_name,
- "ANSI_COLOR", &ansi_color,
- NULL);
-
- if (r != -ENOENT)
- break;
- }
- if (r < 0 && r != -ENOENT)
- log_warning_errno(r, "Failed to read os-release file, ignoring: %m");
+ r = parse_os_release(NULL,
+ "PRETTY_NAME", &pretty_name,
+ "ANSI_COLOR", &ansi_color,
+ NULL);
+ if (r < 0)
+ log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
+ "Failed to read os-release file, ignoring: %m");
if (log_get_show_color())
return status_printf(NULL, false, false,
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index 9b091bf87a..0fc8bb891b 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -33,6 +33,7 @@
#include "hostname-util.h"
#include "locale-util.h"
#include "mkdir.h"
+#include "os-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "proc-cmdline.h"
@@ -79,27 +80,16 @@ static bool press_any_key(void) {
static void print_welcome(void) {
_cleanup_free_ char *pretty_name = NULL;
- const char *os_release = NULL;
static bool done = false;
int r;
if (done)
return;
- os_release = prefix_roota(arg_root, "/etc/os-release");
- r = parse_env_file(NULL, os_release, NEWLINE,
- "PRETTY_NAME", &pretty_name,
- NULL);
- if (r == -ENOENT) {
-
- os_release = prefix_roota(arg_root, "/usr/lib/os-release");
- r = parse_env_file(NULL, os_release, NEWLINE,
- "PRETTY_NAME", &pretty_name,
- NULL);
- }
-
- if (r < 0 && r != -ENOENT)
- log_warning_errno(r, "Failed to read os-release file: %m");
+ r = parse_os_release(arg_root, "PRETTY_NAME", &pretty_name, NULL);
+ if (r < 0)
+ log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
+ "Failed to read os-release file, ignoring: %m");
printf("\nWelcome to your new installation of %s!\nPlease configure a few basic system settings:\n\n",
isempty(pretty_name) ? "Linux" : pretty_name);
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index db54e472c6..28fc628742 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -16,6 +16,7 @@
#include "env-util.h"
#include "fileio-label.h"
#include "hostname-util.h"
+#include "os-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "selinux-util.h"
@@ -98,18 +99,11 @@ static int context_read_data(Context *c) {
if (r < 0 && r != -ENOENT)
return r;
- r = parse_env_file(NULL, "/etc/os-release", NEWLINE,
- "PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME],
- "CPE_NAME", &c->data[PROP_OS_CPE_NAME],
- "HOME_URL", &c->data[PROP_HOME_URL],
- NULL);
- if (r == -ENOENT)
- r = parse_env_file(NULL, "/usr/lib/os-release", NEWLINE,
- "PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME],
- "CPE_NAME", &c->data[PROP_OS_CPE_NAME],
- "HOME_URL", &c->data[PROP_HOME_URL],
- NULL);
-
+ r = parse_os_release(NULL,
+ "PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME],
+ "CPE_NAME", &c->data[PROP_OS_CPE_NAME],
+ "HOME_URL", &c->data[PROP_HOME_URL],
+ NULL);
if (r < 0 && r != -ENOENT)
return r;
diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c
index f80ca7e671..c29b65764a 100644
--- a/src/journal-remote/journal-gatewayd.c
+++ b/src/journal-remote/journal-gatewayd.c
@@ -24,6 +24,7 @@
#include "log.h"
#include "logs-show.h"
#include "microhttpd-util.h"
+#include "os-util.h"
#include "parse-util.h"
#include "sigbus.h"
#include "util.h"
@@ -777,10 +778,8 @@ static int request_handler_machine(
if (r < 0)
return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %m");
- if (parse_env_file(NULL, "/etc/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL) == -ENOENT)
- (void) parse_env_file(NULL, "/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL);
-
- get_virtualization(&v);
+ (void) parse_os_release(NULL, "PRETTY_NAME", &os_name, NULL);
+ (void) get_virtualization(&v);
r = asprintf(&json,
"{ \"machine_id\" : \"" SD_ID128_FORMAT_STR "\","
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index 058543fbb2..d7921cf8cf 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -32,6 +32,7 @@
#include "machine-dbus.h"
#include "machine.h"
#include "mkdir.h"
+#include "os-util.h"
#include "path-util.h"
#include "process-util.h"
#include "signal-util.h"
@@ -330,7 +331,7 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s
switch (m->class) {
case MACHINE_HOST:
- r = load_env_file_pairs(NULL, "/etc/os-release", NULL, &l);
+ r = load_os_release_pairs(NULL, &l);
if (r < 0)
return r;
@@ -361,13 +362,10 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s
if (r < 0)
_exit(EXIT_FAILURE);
- fd = open("/etc/os-release", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0 && errno == ENOENT) {
- fd = open("/usr/lib/os-release", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0 && errno == ENOENT)
- _exit(EXIT_NOT_FOUND);
- }
- if (fd < 0)
+ r = open_os_release(NULL, NULL, &fd);
+ if (r == -ENOENT)
+ _exit(EXIT_NOT_FOUND);
+ if (r < 0)
_exit(EXIT_FAILURE);
r = copy_bytes(fd, pair[1], (uint64_t) -1, 0);
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 56c26aae8e..4c157cf654 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -77,6 +77,7 @@
#include "nspawn-settings.h"
#include "nspawn-setuid.h"
#include "nspawn-stub-pid1.h"
+#include "os-util.h"
#include "pager.h"
#include "parse-util.h"
#include "path-util.h"
diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c
index 608e4b51ac..59ee4fe9e5 100644
--- a/src/shared/dissect-image.c
+++ b/src/shared/dissect-image.c
@@ -30,6 +30,7 @@
#include "linux-3.13/dm-ioctl.h"
#include "missing.h"
#include "mount-util.h"
+#include "os-util.h"
#include "path-util.h"
#include "process-util.h"
#include "raw-clone.h"
diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c
index 440b1f574f..44cb371da6 100644
--- a/src/shared/machine-image.c
+++ b/src/shared/machine-image.c
@@ -35,6 +35,7 @@
#include "machine-image.h"
#include "macro.h"
#include "mkdir.h"
+#include "os-util.h"
#include "path-util.h"
#include "rm-rf.h"
#include "string-table.h"
@@ -923,6 +924,7 @@ int image_read_metadata(Image *i) {
sd_id128_t machine_id = SD_ID128_NULL;
_cleanup_free_ char *hostname = NULL;
_cleanup_free_ char *path = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
r = chase_symlinks("/etc/hostname", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path);
if (r < 0 && r != -ENOENT)
@@ -962,18 +964,9 @@ int image_read_metadata(Image *i) {
log_debug_errno(r, "Failed to parse machine-info data of %s: %m", i->name);
}
- path = mfree(path);
-
- r = chase_symlinks("/etc/os-release", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path);
- if (r == -ENOENT)
- r = chase_symlinks("/usr/lib/os-release", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path);
- if (r < 0 && r != -ENOENT)
- log_debug_errno(r, "Failed to chase os-release in image: %m");
- else if (r >= 0) {
- r = load_env_file_pairs(NULL, path, NULL, &os_release);
- if (r < 0)
- log_debug_errno(r, "Failed to parse os-release data of %s: %m", i->name);
- }
+ r = load_os_release_pairs(i->path, &os_release);
+ if (r < 0)
+ log_debug_errno(r, "Failed to read os-release in image, ignoring: %m");
free_and_replace(i->hostname, hostname);
i->machine_id = machine_id;
diff --git a/src/test/meson.build b/src/test/meson.build
index 4a9982240b..619f0cd823 100644
--- a/src/test/meson.build
+++ b/src/test/meson.build
@@ -242,6 +242,10 @@ tests += [
[],
[]],
+ [['src/test/test-os-util.c'],
+ [],
+ []],
+
[['src/test/test-escape.c'],
[],
[]],
diff --git a/src/test/test-os-util.c b/src/test/test-os-util.c
new file mode 100644
index 0000000000..8d8b52d7f6
--- /dev/null
+++ b/src/test/test-os-util.c
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+
+#include "log.h"
+#include "os-util.h"
+
+static void test_path_is_os_tree(void) {
+ assert_se(path_is_os_tree("/") > 0);
+ assert_se(path_is_os_tree("/etc") == 0);
+ assert_se(path_is_os_tree("/idontexist") == -ENOENT);
+}
+
+int main(int argc, char *argv[]) {
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+ log_open();
+
+ test_path_is_os_tree();
+
+ return 0;
+}
diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c
index 6c9c132612..1697b2d777 100644
--- a/src/test/test-stat-util.c
+++ b/src/test/test-stat-util.c
@@ -52,12 +52,6 @@ static void test_is_symlink(void) {
unlink(name_link);
}
-static void test_path_is_os_tree(void) {
- assert_se(path_is_os_tree("/") > 0);
- assert_se(path_is_os_tree("/etc") == 0);
- assert_se(path_is_os_tree("/idontexist") == -ENOENT);
-}
-
static void test_path_is_fs_type(void) {
/* run might not be a mount point in build chroots */
if (path_is_mount_point("/run", NULL, AT_SYMLINK_FOLLOW) > 0) {
@@ -81,7 +75,6 @@ static void test_path_is_temporary_fs(void) {
int main(int argc, char *argv[]) {
test_files_same();
test_is_symlink();
- test_path_is_os_tree();
test_path_is_fs_type();
test_path_is_temporary_fs();