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.
This commit is contained in:
parent
080dfda85a
commit
d58ad743f9
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 "\","
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -242,6 +242,10 @@ tests += [
|
|||
[],
|
||||
[]],
|
||||
|
||||
[['src/test/test-os-util.c'],
|
||||
[],
|
||||
[]],
|
||||
|
||||
[['src/test/test-escape.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;
|
||||
}
|
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in New Issue