Merge pull request #18704 from keszybz/fallback-hostame-override
Allow overriding of fallback hostname through envvar and os-release field
This commit is contained in:
@@ -420,11 +420,11 @@ int config_parse(
|
||||
if (ret_mtime)
|
||||
*ret_mtime = mtime;
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int config_parse_many_files(
|
||||
const char *conf_file,
|
||||
const char* const* conf_files,
|
||||
char **files,
|
||||
const char *sections,
|
||||
ConfigItemLookup lookup,
|
||||
@@ -437,20 +437,23 @@ static int config_parse_many_files(
|
||||
char **fn;
|
||||
int r;
|
||||
|
||||
if (conf_file) {
|
||||
r = config_parse(NULL, conf_file, NULL, sections, lookup, table, flags, userdata, &mtime);
|
||||
/* First read the first found main config file. */
|
||||
STRV_FOREACH(fn, (char**) conf_files) {
|
||||
r = config_parse(NULL, *fn, NULL, sections, lookup, table, flags, userdata, &mtime);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Then read all the drop-ins. */
|
||||
STRV_FOREACH(fn, files) {
|
||||
usec_t t;
|
||||
|
||||
r = config_parse(NULL, *fn, NULL, sections, lookup, table, flags, userdata, &t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (t > mtime) /* Find the newest */
|
||||
mtime = t;
|
||||
mtime = MAX(mtime, t); /* Find the newest */
|
||||
}
|
||||
|
||||
if (ret_mtime)
|
||||
@@ -477,12 +480,14 @@ int config_parse_many_nulstr(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata, ret_mtime);
|
||||
return config_parse_many_files(STRV_MAKE_CONST(conf_file),
|
||||
files, sections, lookup, table, flags, userdata,
|
||||
ret_mtime);
|
||||
}
|
||||
|
||||
/* Parse each config file in the directories specified as strv. */
|
||||
int config_parse_many(
|
||||
const char *conf_file,
|
||||
const char* const* conf_files,
|
||||
const char* const* conf_file_dirs,
|
||||
const char *dropin_dirname,
|
||||
const char *sections,
|
||||
@@ -506,7 +511,7 @@ int config_parse_many(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata, ret_mtime);
|
||||
return config_parse_many_files(conf_files, files, sections, lookup, table, flags, userdata, ret_mtime);
|
||||
}
|
||||
|
||||
#define DEFINE_PARSER(type, vartype, conv_func) \
|
||||
|
||||
@@ -102,7 +102,7 @@ int config_parse_many_nulstr(
|
||||
usec_t *ret_mtime); /* possibly NULL */
|
||||
|
||||
int config_parse_many(
|
||||
const char *conf_file, /* possibly NULL */
|
||||
const char* const* conf_files, /* possibly empty */
|
||||
const char* const* conf_file_dirs,
|
||||
const char *dropin_dirname,
|
||||
const char *sections, /* nulstr */
|
||||
|
||||
@@ -1250,23 +1250,6 @@ int image_name_lock(const char *name, int operation, LockFile *ret) {
|
||||
return make_lock_file(p, operation, ret);
|
||||
}
|
||||
|
||||
bool image_name_is_valid(const char *s) {
|
||||
if (!filename_is_valid(s))
|
||||
return false;
|
||||
|
||||
if (string_has_cc(s, NULL))
|
||||
return false;
|
||||
|
||||
if (!utf8_is_valid(s))
|
||||
return false;
|
||||
|
||||
/* Temporary files for atomically creating new files */
|
||||
if (startswith(s, ".#"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool image_in_search_path(
|
||||
ImageClass class,
|
||||
const char *root,
|
||||
|
||||
@@ -76,8 +76,6 @@ int image_read_only(Image *i, bool b);
|
||||
const char* image_type_to_string(ImageType t) _const_;
|
||||
ImageType image_type_from_string(const char *s) _pure_;
|
||||
|
||||
bool image_name_is_valid(const char *s) _pure_;
|
||||
|
||||
int image_path_lock(const char *path, int operation, LockFile *global, LockFile *local);
|
||||
int image_name_lock(const char *name, int operation, LockFile *ret);
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "env-util.h"
|
||||
#include "extension-release.h"
|
||||
#include "log.h"
|
||||
#include "os-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
int extension_release_validate(
|
||||
const char *name,
|
||||
const char *host_os_release_id,
|
||||
const char *host_os_release_version_id,
|
||||
const char *host_os_release_sysext_level,
|
||||
char **extension_release) {
|
||||
|
||||
const char *extension_release_id = NULL, *extension_release_sysext_level = NULL;
|
||||
|
||||
assert(name);
|
||||
assert(!isempty(host_os_release_id));
|
||||
|
||||
/* Now that we can look into the extension image, let's see if the OS version is compatible */
|
||||
if (strv_isempty(extension_release)) {
|
||||
log_debug("Extension '%s' carries no extension-release data, ignoring extension.", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
extension_release_id = strv_env_pairs_get(extension_release, "ID");
|
||||
if (isempty(extension_release_id)) {
|
||||
log_debug("Extension '%s' does not contain ID in extension-release but requested to match '%s'",
|
||||
name, strna(host_os_release_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!streq_ptr(host_os_release_id, extension_release_id)) {
|
||||
log_debug("Extension '%s' is for OS '%s', but deployed on top of '%s'.",
|
||||
name, strna(extension_release_id), strna(host_os_release_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Rolling releases do not typically set VERSION_ID (eg: ArchLinux) */
|
||||
if (isempty(host_os_release_version_id) && isempty(host_os_release_sysext_level)) {
|
||||
log_debug("No version info on the host (rolling release?), but ID in %s matched.", name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If the extension has a sysext API level declared, then it must match the host API
|
||||
* level. Otherwise, compare OS version as a whole */
|
||||
extension_release_sysext_level = strv_env_pairs_get(extension_release, "SYSEXT_LEVEL");
|
||||
if (!isempty(host_os_release_sysext_level) && !isempty(extension_release_sysext_level)) {
|
||||
if (!streq_ptr(host_os_release_sysext_level, extension_release_sysext_level)) {
|
||||
log_debug("Extension '%s' is for sysext API level '%s', but running on sysext API level '%s'",
|
||||
name, strna(extension_release_sysext_level), strna(host_os_release_sysext_level));
|
||||
return 0;
|
||||
}
|
||||
} else if (!isempty(host_os_release_version_id)) {
|
||||
const char *extension_release_version_id;
|
||||
|
||||
extension_release_version_id = strv_env_pairs_get(extension_release, "VERSION_ID");
|
||||
if (isempty(extension_release_version_id)) {
|
||||
log_debug("Extension '%s' does not contain VERSION_ID in extension-release but requested to match '%s'",
|
||||
name, strna(host_os_release_version_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!streq_ptr(host_os_release_version_id, extension_release_version_id)) {
|
||||
log_debug("Extension '%s' is for OS '%s', but deployed on top of '%s'.",
|
||||
name, strna(extension_release_version_id), strna(host_os_release_version_id));
|
||||
return 0;
|
||||
}
|
||||
} else if (isempty(host_os_release_version_id) && isempty(host_os_release_sysext_level)) {
|
||||
/* Rolling releases do not typically set VERSION_ID (eg: ArchLinux) */
|
||||
log_debug("No version info on the host (rolling release?), but ID in %s matched.", name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
log_debug("Version info of extension '%s' matches host.", name);
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
/* Given an image name (for logging purposes), a set of os-release values from the host and a key-value pair
|
||||
* vector of extension-release variables, check that the distro and (system extension level or distro
|
||||
* version) match and return 1, and 0 otherwise. */
|
||||
int extension_release_validate(
|
||||
const char *name,
|
||||
const char *host_os_release_id,
|
||||
const char *host_os_release_version_id,
|
||||
const char *host_os_release_sysext_level,
|
||||
char **extension_release);
|
||||
@@ -152,13 +152,13 @@ void hostname_update_source_hint(const char *hostname, HostnameSource source) {
|
||||
* notice if somebody sets the hostname directly (not going through hostnamed).
|
||||
*/
|
||||
|
||||
if (source == HOSTNAME_FALLBACK) {
|
||||
r = write_string_file("/run/systemd/fallback-hostname", hostname,
|
||||
if (source == HOSTNAME_DEFAULT) {
|
||||
r = write_string_file("/run/systemd/default-hostname", hostname,
|
||||
WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_ATOMIC);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to create \"/run/systemd/fallback-hostname\": %m");
|
||||
log_warning_errno(r, "Failed to create \"/run/systemd/default-hostname\": %m");
|
||||
} else
|
||||
unlink_or_warn("/run/systemd/fallback-hostname");
|
||||
unlink_or_warn("/run/systemd/default-hostname");
|
||||
}
|
||||
|
||||
int hostname_setup(bool really) {
|
||||
@@ -194,7 +194,7 @@ int hostname_setup(bool really) {
|
||||
}
|
||||
}
|
||||
|
||||
if (isempty(hn)) {
|
||||
if (!hn) {
|
||||
/* Don't override the hostname if it is already set and not explicitly configured */
|
||||
|
||||
char buf[HOST_NAME_MAX + 1] = {};
|
||||
@@ -204,10 +204,13 @@ int hostname_setup(bool really) {
|
||||
}
|
||||
|
||||
if (enoent)
|
||||
log_info("No hostname configured, using fallback hostname.");
|
||||
log_info("No hostname configured, using default hostname.");
|
||||
|
||||
hn = FALLBACK_HOSTNAME;
|
||||
source = HOSTNAME_FALLBACK;
|
||||
hn = b = get_default_hostname();
|
||||
if (!hn)
|
||||
return log_oom();
|
||||
|
||||
source = HOSTNAME_DEFAULT;
|
||||
|
||||
}
|
||||
|
||||
@@ -230,7 +233,7 @@ int hostname_setup(bool really) {
|
||||
static const char* const hostname_source_table[] = {
|
||||
[HOSTNAME_STATIC] = "static",
|
||||
[HOSTNAME_TRANSIENT] = "transient",
|
||||
[HOSTNAME_FALLBACK] = "fallback",
|
||||
[HOSTNAME_DEFAULT] = "default",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(hostname_source, HostnameSource);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
typedef enum HostnameSource {
|
||||
HOSTNAME_STATIC, /* from /etc/hostname */
|
||||
HOSTNAME_TRANSIENT, /* a transient hostname set through systemd, hostnamed, the container manager, or otherwise */
|
||||
HOSTNAME_FALLBACK, /* the compiled-in fallback was used */
|
||||
HOSTNAME_DEFAULT, /* the os-release default or the compiled-in fallback were used */
|
||||
_HOSTNAME_INVALID = -EINVAL,
|
||||
} HostnameSource;
|
||||
|
||||
|
||||
@@ -100,6 +100,8 @@ shared_sources = files('''
|
||||
exec-util.h
|
||||
exit-status.c
|
||||
exit-status.h
|
||||
extension-release.c
|
||||
extension-release.h
|
||||
fdset.c
|
||||
fdset.h
|
||||
fileio-label.c
|
||||
@@ -196,8 +198,6 @@ shared_sources = files('''
|
||||
numa-util.h
|
||||
openssl-util.c
|
||||
openssl-util.h
|
||||
os-util.c
|
||||
os-util.h
|
||||
output-mode.c
|
||||
output-mode.h
|
||||
pager.c
|
||||
|
||||
@@ -1,266 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "discover-image.h"
|
||||
#include "env-file.h"
|
||||
#include "env-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "macro.h"
|
||||
#include "os-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
int path_is_extension_tree(const char *path, const char *extension) {
|
||||
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 distinguish 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/extension-release.d/extension-release.NAME as flag file if something is a system extension,
|
||||
* and {/etc|/usr/lib}/os-release as flag file if something is an OS (in case extension == NULL) */
|
||||
r = open_extension_release(path, extension, NULL, NULL);
|
||||
if (r == -ENOENT) /* We got nothing */
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int open_extension_release(const char *root, const char *extension, char **ret_path, int *ret_fd) {
|
||||
_cleanup_free_ char *q = NULL;
|
||||
int r, fd;
|
||||
|
||||
if (extension) {
|
||||
const char *extension_full_path;
|
||||
|
||||
if (!image_name_is_valid(extension))
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"The extension name %s is invalid.", extension);
|
||||
|
||||
extension_full_path = strjoina("/usr/lib/extension-release.d/extension-release.", extension);
|
||||
r = chase_symlinks(extension_full_path, root, CHASE_PREFIX_ROOT,
|
||||
ret_path ? &q : NULL,
|
||||
ret_fd ? &fd : NULL);
|
||||
} else {
|
||||
const char *p;
|
||||
|
||||
FOREACH_STRING(p, "/etc/os-release", "/usr/lib/os-release") {
|
||||
r = chase_symlinks(p, root, CHASE_PREFIX_ROOT,
|
||||
ret_path ? &q : NULL,
|
||||
ret_fd ? &fd : NULL);
|
||||
if (r != -ENOENT)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret_fd) {
|
||||
int real_fd;
|
||||
|
||||
/* Convert the O_PATH fd into a proper, readable one */
|
||||
real_fd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
safe_close(fd);
|
||||
if (real_fd < 0)
|
||||
return real_fd;
|
||||
|
||||
*ret_fd = real_fd;
|
||||
}
|
||||
|
||||
if (ret_path)
|
||||
*ret_path = TAKE_PTR(q);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fopen_extension_release(const char *root, const char *extension, 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_extension_release(root, extension, ret_path, NULL);
|
||||
|
||||
r = open_extension_release(root, extension, ret_path ? &p : NULL, &fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
f = take_fdopen(&fd, "r");
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
*ret_file = f;
|
||||
|
||||
if (ret_path)
|
||||
*ret_path = TAKE_PTR(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_release_internal(const char *root, const char *extension, va_list ap) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
int r;
|
||||
|
||||
r = fopen_extension_release(root, extension, &p, &f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return parse_env_filev(f, p, ap);
|
||||
}
|
||||
|
||||
int parse_extension_release(const char *root, const char *extension, ...) {
|
||||
va_list ap;
|
||||
int r;
|
||||
|
||||
va_start(ap, extension);
|
||||
r = parse_release_internal(root, extension, ap);
|
||||
va_end(ap);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int parse_os_release(const char *root, ...) {
|
||||
va_list ap;
|
||||
int r;
|
||||
|
||||
va_start(ap, root);
|
||||
r = parse_release_internal(root, NULL, 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, ret);
|
||||
}
|
||||
|
||||
int load_os_release_pairs_with_prefix(const char *root, const char *prefix, char ***ret) {
|
||||
_cleanup_strv_free_ char **os_release_pairs = NULL, **os_release_pairs_prefixed = NULL;
|
||||
char **p, **q;
|
||||
int r;
|
||||
|
||||
r = load_os_release_pairs(root, &os_release_pairs);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
STRV_FOREACH_PAIR(p, q, os_release_pairs) {
|
||||
char *line;
|
||||
|
||||
/* We strictly return only the four main ID fields and ignore the rest */
|
||||
if (!STR_IN_SET(*p, "ID", "VERSION_ID", "BUILD_ID", "VARIANT_ID"))
|
||||
continue;
|
||||
|
||||
ascii_strlower(*p);
|
||||
line = strjoin(prefix, *p, "=", *q);
|
||||
if (!line)
|
||||
return -ENOMEM;
|
||||
r = strv_consume(&os_release_pairs_prefixed, line);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(os_release_pairs_prefixed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_extension_release_pairs(const char *root, const char *extension, char ***ret) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
int r;
|
||||
|
||||
r = fopen_extension_release(root, extension, &p, &f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return load_env_file_pairs(f, p, ret);
|
||||
}
|
||||
|
||||
int extension_release_validate(
|
||||
const char *name,
|
||||
const char *host_os_release_id,
|
||||
const char *host_os_release_version_id,
|
||||
const char *host_os_release_sysext_level,
|
||||
char **extension_release) {
|
||||
|
||||
const char *extension_release_id = NULL, *extension_release_sysext_level = NULL;
|
||||
|
||||
assert(name);
|
||||
assert(!isempty(host_os_release_id));
|
||||
|
||||
/* Now that we can look into the extension image, let's see if the OS version is compatible */
|
||||
if (strv_isempty(extension_release)) {
|
||||
log_debug("Extension '%s' carries no extension-release data, ignoring extension.", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
extension_release_id = strv_env_pairs_get(extension_release, "ID");
|
||||
if (isempty(extension_release_id)) {
|
||||
log_debug("Extension '%s' does not contain ID in extension-release but requested to match '%s'",
|
||||
name, strna(host_os_release_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!streq_ptr(host_os_release_id, extension_release_id)) {
|
||||
log_debug("Extension '%s' is for OS '%s', but deployed on top of '%s'.",
|
||||
name, strna(extension_release_id), strna(host_os_release_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Rolling releases do not typically set VERSION_ID (eg: ArchLinux) */
|
||||
if (isempty(host_os_release_version_id) && isempty(host_os_release_sysext_level)) {
|
||||
log_debug("No version info on the host (rolling release?), but ID in %s matched.", name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If the extension has a sysext API level declared, then it must match the host API
|
||||
* level. Otherwise, compare OS version as a whole */
|
||||
extension_release_sysext_level = strv_env_pairs_get(extension_release, "SYSEXT_LEVEL");
|
||||
if (!isempty(host_os_release_sysext_level) && !isempty(extension_release_sysext_level)) {
|
||||
if (!streq_ptr(host_os_release_sysext_level, extension_release_sysext_level)) {
|
||||
log_debug("Extension '%s' is for sysext API level '%s', but running on sysext API level '%s'",
|
||||
name, strna(extension_release_sysext_level), strna(host_os_release_sysext_level));
|
||||
return 0;
|
||||
}
|
||||
} else if (!isempty(host_os_release_version_id)) {
|
||||
const char *extension_release_version_id;
|
||||
|
||||
extension_release_version_id = strv_env_pairs_get(extension_release, "VERSION_ID");
|
||||
if (isempty(extension_release_version_id)) {
|
||||
log_debug("Extension '%s' does not contain VERSION_ID in extension-release but requested to match '%s'",
|
||||
name, strna(host_os_release_version_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!streq_ptr(host_os_release_version_id, extension_release_version_id)) {
|
||||
log_debug("Extension '%s' is for OS '%s', but deployed on top of '%s'.",
|
||||
name, strna(extension_release_version_id), strna(host_os_release_version_id));
|
||||
return 0;
|
||||
}
|
||||
} else if (isempty(host_os_release_version_id) && isempty(host_os_release_sysext_level)) {
|
||||
/* Rolling releases do not typically set VERSION_ID (eg: ArchLinux) */
|
||||
log_debug("No version info on the host (rolling release?), but ID in %s matched.", name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
log_debug("Version info of extension '%s' matches host.", name);
|
||||
return 1;
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* The *_extension_release flavours will look for /usr/lib/extension-release/extension-release.NAME
|
||||
* in accordance with the OS extension specification, rather than for /usr/lib/ or /etc/os-release. */
|
||||
|
||||
int path_is_extension_tree(const char *path, const char *extension);
|
||||
static inline int path_is_os_tree(const char *path) {
|
||||
return path_is_extension_tree(path, NULL);
|
||||
}
|
||||
|
||||
int open_extension_release(const char *root, const char *extension, char **ret_path, int *ret_fd);
|
||||
static inline int open_os_release(const char *root, char **ret_path, int *ret_fd) {
|
||||
return open_extension_release(root, NULL, ret_path, ret_fd);
|
||||
}
|
||||
|
||||
int fopen_extension_release(const char *root, const char *extension, char **ret_path, FILE **ret_file);
|
||||
static inline int fopen_os_release(const char *root, char **ret_path, FILE **ret_file) {
|
||||
return fopen_extension_release(root, NULL, ret_path, ret_file);
|
||||
}
|
||||
|
||||
int parse_extension_release(const char *root, const char *extension, ...) _sentinel_;
|
||||
int parse_os_release(const char *root, ...) _sentinel_;
|
||||
int load_extension_release_pairs(const char *root, const char *extension, char ***ret);
|
||||
int load_os_release_pairs(const char *root, char ***ret);
|
||||
int load_os_release_pairs_with_prefix(const char *root, const char *prefix, char ***ret);
|
||||
|
||||
/* Given an image name (for logging purposes), a set of os-release values from the host
|
||||
* and a key-value pair vector of extension-release variables, check that the distro and
|
||||
* (system extension level or distro version) match and return 1, and 0 otherwise. */
|
||||
int extension_release_validate(const char *name, const char *host_os_release_id, const char *host_os_release_version_id, const char *host_os_release_sysext_level, char **extension_release);
|
||||
@@ -203,7 +203,7 @@ static int specifier_os_release_common(const char *field, char **ret) {
|
||||
char *t = NULL;
|
||||
int r;
|
||||
|
||||
r = parse_os_release(NULL, field, &t, NULL);
|
||||
r = parse_os_release(NULL, field, &t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!t) {
|
||||
|
||||
Reference in New Issue
Block a user