```json
{
- "packageType":"rpm", # this provides a namespace for the package+package-version fields
- "packageDistro":"fedora",
- "packageDistroVersion":"33",
- "package":"coreutils",
- "packageVersion": "4711.0815.fc13.arm32",
- "cpe": # A CPE name for the operating system, `CPE_NAME` from os-release is a good default
+ "type":"rpm", # this provides a namespace for the package+package-version fields
+ "os":"fedora",
+ "osVersion":"33",
+ "name":"coreutils",
+ "version": "4711.0815.fc13.arm32",
+ "osCpe": # A CPE name for the operating system, `CPE_NAME` from os-release is a good default
}
```
{
.note.package : ALIGN(4) {
BYTE(0x04) BYTE(0x00) BYTE(0x00) BYTE(0x00) /* Length of Owner including NUL */
- BYTE(0x73) BYTE(0x00) BYTE(0x00) BYTE(0x00) /* Length of Value including NUL */
+ BYTE(0x64) BYTE(0x00) BYTE(0x00) BYTE(0x00) /* Length of Value including NUL */
BYTE(0x7e) BYTE(0x1a) BYTE(0xfe) BYTE(0xca) /* Note ID */
BYTE(0x46) BYTE(0x44) BYTE(0x4f) BYTE(0x00) /* Owner: 'FDO\x00' */
- BYTE(0x7b) BYTE(0x22) BYTE(0x70) BYTE(0x61) /* Value: '{"packageType":"rpm","package":"systemd","packageVersion":"248~rc2-1.fc34","cpe":"cpe:/o:fedoraproject:fedora:33"}\x00\x00' */
- BYTE(0x63) BYTE(0x6b) BYTE(0x61) BYTE(0x67)
- BYTE(0x65) BYTE(0x54) BYTE(0x79) BYTE(0x70)
- BYTE(0x65) BYTE(0x22) BYTE(0x3a) BYTE(0x22)
- BYTE(0x72) BYTE(0x70) BYTE(0x6d) BYTE(0x22)
- BYTE(0x2c) BYTE(0x22) BYTE(0x70) BYTE(0x61)
- BYTE(0x63) BYTE(0x6b) BYTE(0x61) BYTE(0x67)
- BYTE(0x65) BYTE(0x22) BYTE(0x3a) BYTE(0x22)
- BYTE(0x73) BYTE(0x79) BYTE(0x73) BYTE(0x74)
- BYTE(0x65) BYTE(0x6d) BYTE(0x64) BYTE(0x22)
- BYTE(0x2c) BYTE(0x22) BYTE(0x70) BYTE(0x61)
- BYTE(0x63) BYTE(0x6b) BYTE(0x61) BYTE(0x67)
- BYTE(0x65) BYTE(0x56) BYTE(0x65) BYTE(0x72)
- BYTE(0x73) BYTE(0x69) BYTE(0x6f) BYTE(0x6e)
- BYTE(0x22) BYTE(0x3a) BYTE(0x22) BYTE(0x32)
- BYTE(0x34) BYTE(0x38) BYTE(0x7e) BYTE(0x72)
- BYTE(0x63) BYTE(0x32) BYTE(0x2d) BYTE(0x31)
- BYTE(0x2e) BYTE(0x66) BYTE(0x63) BYTE(0x33)
- BYTE(0x34) BYTE(0x22) BYTE(0x2c) BYTE(0x22)
- BYTE(0x63) BYTE(0x70) BYTE(0x65) BYTE(0x22)
- BYTE(0x3a) BYTE(0x22) BYTE(0x63) BYTE(0x70)
- BYTE(0x65) BYTE(0x3a) BYTE(0x2f) BYTE(0x6f)
- BYTE(0x3a) BYTE(0x66) BYTE(0x65) BYTE(0x64)
- BYTE(0x6f) BYTE(0x72) BYTE(0x61) BYTE(0x70)
- BYTE(0x72) BYTE(0x6f) BYTE(0x6a) BYTE(0x65)
- BYTE(0x63) BYTE(0x74) BYTE(0x3a) BYTE(0x66)
- BYTE(0x65) BYTE(0x64) BYTE(0x6f) BYTE(0x72)
- BYTE(0x61) BYTE(0x3a) BYTE(0x33) BYTE(0x33)
- BYTE(0x22) BYTE(0x7d) BYTE(0x00) BYTE(0x00)
+ BYTE(0x7b) BYTE(0x22) BYTE(0x74) BYTE(0x79) /* Value: '{"type":"rpm","name":"systemd","version":"248~rc2-1.fc34","osCpe":"cpe:/o:fedoraproject:fedora:33"}\x00' */
+ BYTE(0x70) BYTE(0x65) BYTE(0x22) BYTE(0x3a)
+ BYTE(0x22) BYTE(0x72) BYTE(0x70) BYTE(0x6d)
+ BYTE(0x22) BYTE(0x2c) BYTE(0x22) BYTE(0x6e)
+ BYTE(0x61) BYTE(0x6d) BYTE(0x65) BYTE(0x22)
+ BYTE(0x3a) BYTE(0x22) BYTE(0x73) BYTE(0x79)
+ BYTE(0x73) BYTE(0x74) BYTE(0x65) BYTE(0x6d)
+ BYTE(0x64) BYTE(0x22) BYTE(0x2c) BYTE(0x22)
+ BYTE(0x76) BYTE(0x65) BYTE(0x72) BYTE(0x73)
+ BYTE(0x69) BYTE(0x6f) BYTE(0x6e) BYTE(0x22)
+ BYTE(0x3a) BYTE(0x22) BYTE(0x32) BYTE(0x34)
+ BYTE(0x38) BYTE(0x7e) BYTE(0x72) BYTE(0x63)
+ BYTE(0x32) BYTE(0x2d) BYTE(0x31) BYTE(0x2e)
+ BYTE(0x66) BYTE(0x63) BYTE(0x33) BYTE(0x34)
+ BYTE(0x22) BYTE(0x2c) BYTE(0x22) BYTE(0x6f)
+ BYTE(0x73) BYTE(0x43) BYTE(0x70) BYTE(0x65)
+ BYTE(0x22) BYTE(0x3a) BYTE(0x22) BYTE(0x63)
+ BYTE(0x70) BYTE(0x65) BYTE(0x3a) BYTE(0x2f)
+ BYTE(0x6f) BYTE(0x3a) BYTE(0x66) BYTE(0x65)
+ BYTE(0x64) BYTE(0x6f) BYTE(0x72) BYTE(0x61)
+ BYTE(0x70) BYTE(0x72) BYTE(0x6f) BYTE(0x6a)
+ BYTE(0x65) BYTE(0x63) BYTE(0x74) BYTE(0x3a)
+ BYTE(0x66) BYTE(0x65) BYTE(0x64) BYTE(0x6f)
+ BYTE(0x72) BYTE(0x61) BYTE(0x3a) BYTE(0x33)
+ BYTE(0x33) BYTE(0x22) BYTE(0x7d) BYTE(0x00)
}
}
INSERT AFTER .note.gnu.build-id;
zero outside of this state, and positive otherwise. Effectively, this function returns positive while regular
messages can be sent or received on the connection.</para>
+ <para>The <parameter>bus</parameter> argument may be <constant>NULL</constant>, zero is also returned in
+ that case.</para>
+
<para>To be notified when the connection is fully established, use
<citerefentry><refentrytitle>sd_bus_set_connected_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry> and
install a match for the <function>Connected()</function> signal on the
<refsect1>
<title>Return Value</title>
- <para>On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style
- error code.</para>
+ <para>Those functions return 0 if the bus is <emphasis>not</emphasis> in the given state, and a positive
+ integer when it is. On failure, a negative errno-style error code is returned.</para>
<refsect2>
<title>Errors</title>
</varlistentry>
<varlistentry>
- <term><varname>COREDUMP_PKGMETA_PACKAGE=</varname></term>
- <term><varname>COREDUMP_PKGMETA_PACKAGEVERSION=</varname></term>
- <term><varname>COREDUMP_PKGMETA_JSON=</varname></term>
+ <term><varname>COREDUMP_PACKAGE_NAME=</varname></term>
+ <term><varname>COREDUMP_PACKAGE_VERSION=</varname></term>
+ <term><varname>COREDUMP_PACKAGE_JSON=</varname></term>
<listitem><para>If the executable contained .package metadata ELF notes, they will be
parsed and attached. The <varname>package</varname> and <varname>packageVersion</varname>
<row>
<entry>8</entry>
- <entry><citerefentry><refentrytitle>sd-boot</refentrytitle><manvolnum>8</manvolnum></citerefentry> measures the kernel command line in this PCR.</entry>
+ <entry><citerefentry><refentrytitle>sd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry> measures the kernel command line in this PCR.</entry>
</row>
</tbody>
</tgroup>
umask 022
fi
+# On Fedora "ld" is (unfortunately — if you ask me) managed via
+# "alternatives". Since we'd like to support building images in environments
+# with only /usr/ around (e.g. mkosi's UsrOnly=1 option), we have the problem
+# that /usr/bin/ld is a symlink that points to a non-existing file in
+# /etc/alternative/ in this mode. Let's work around this for now by manually
+# redirect "ld" to "ld.bfd", i.e. circumventing the /usr/bin/ld symlink.
+if [ ! -x /usr/bin/ld -a -x /usr/bin/ld.bfd ] ; then
+ mkdir -p "$HOME"/bin
+ ln -s /usr/bin/ld.bfd "$HOME"/bin/ld
+ PATH="$HOME/bin:$PATH"
+fi
+
# If mkosi.builddir/ exists mkosi will set $BUILDDIR to it, let's then use it
# as out-of-tree build dir. Otherwise, let's make up our own builddir.
[ -z "$BUILDDIR" ] && BUILDDIR=build
return path_equal(a, b) || files_same(a, b, flags) > 0;
}
+bool path_equal_filename(const char *a, const char *b) {
+ _cleanup_free_ char *a_basename = NULL, *b_basename = NULL;
+ int r;
+
+ assert(a);
+ assert(b);
+
+ r = path_extract_filename(a, &a_basename);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to parse basename of %s: %m", a);
+ return false;
+ }
+ r = path_extract_filename(b, &b_basename);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to parse basename of %s: %m", b);
+ return false;
+ }
+
+ return path_equal(a_basename, b_basename);
+}
+
char* path_join_internal(const char *first, ...) {
char *joined, *q;
const char *p;
int path_compare(const char *a, const char *b) _pure_;
bool path_equal(const char *a, const char *b) _pure_;
bool path_equal_or_files_same(const char *a, const char *b, int flags);
+/* Compares only the last portion of the input paths, ie: the filenames */
+bool path_equal_filename(const char *a, const char *b);
char* path_join_internal(const char *first, ...);
#define path_join(x, ...) path_join_internal(x, __VA_ARGS__, POINTER_MAX)
_cleanup_free_ char *word = NULL;
const char *c;
- r = extract_first_word(&q, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX);
+ r = extract_first_word(&q, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX|EXTRACT_RETAIN_ESCAPE);
if (r < 0)
return r;
if (r == 0)
c->stdin_data_size = 0;
c->network_namespace_path = mfree(c->network_namespace_path);
+ c->ipc_namespace_path = mfree(c->ipc_namespace_path);
c->log_namespace = mfree(c->log_namespace);
if (r < 0)
return log_error_errno(r, "Failed to format JSON package metadata: %m");
- (void) iovw_put_string_field(iovw, "COREDUMP_PKGMETA_JSON=", formatted_json);
+ (void) iovw_put_string_field(iovw, "COREDUMP_PACKAGE_JSON=", formatted_json);
}
JSON_VARIANT_OBJECT_FOREACH(module_name, module_json, json_metadata) {
- _cleanup_free_ char *module_basename = NULL, *exe_basename = NULL;
- const char *key;
- JsonVariant *w;
-
- /* The module name, most likely parsed from the ELF core file,
- * sometimes contains the full path and sometimes does not. */
- r = path_extract_filename(module_name, &module_basename);
- if (r < 0)
- return log_error_errno(r, "Failed to parse module basename: %m");
- r = path_extract_filename(context->meta[META_EXE], &exe_basename);
- if (r < 0)
- return log_error_errno(r, "Failed to parse executable basename: %m");
+ JsonVariant *package_name, *package_version;
/* We only add structured fields for the 'main' ELF module */
- if (!streq(module_basename, exe_basename))
+ if (!path_equal_filename(module_name, context->meta[META_EXE]))
continue;
- /* Cannot nest two JSON_VARIANT_OBJECT_FOREACH as they define the same
- * iterator variable '_state' */
- for (struct json_variant_foreach_state _state2 = { (module_json), 0 }; \
- json_variant_is_object(_state2.variant) && \
- _state2.idx < json_variant_elements(_state2.variant) && \
- ({ key = json_variant_string(json_variant_by_index(_state2.variant, _state2.idx)); \
- w = json_variant_by_index(_state2.variant, _state2.idx + 1); \
- true; }); \
- _state2.idx += 2) {
- _cleanup_free_ char *metadata_id = NULL, *key_upper = NULL;
-
- if (!json_variant_is_string(w))
- continue;
-
- if (!STR_IN_SET(key, "package", "packageVersion"))
- continue;
+ package_name = json_variant_by_key(module_json, "name");
+ if (package_name)
+ (void) iovw_put_string_field(iovw, "COREDUMP_PACKAGE_NAME=", json_variant_string(package_name));
- /* Journal metadata field names need to be upper case */
- key_upper = strdup(key);
- if (!key_upper)
- return log_oom();
- key_upper = ascii_strupper(key_upper);
-
- metadata_id = strjoin("COREDUMP_PKGMETA_", key_upper, "=");
- if (!metadata_id)
- return log_oom();
-
- (void) iovw_put_string_field(iovw, metadata_id, json_variant_string(w));
- }
+ package_version = json_variant_by_key(module_json, "version");
+ if (package_version)
+ (void) iovw_put_string_field(iovw, "COREDUMP_PACKAGE_VERSION=", json_variant_string(package_version));
}
/* Optionally store the entire coredump in the journal */
RETRIEVE(d, l, "COREDUMP_FILENAME", filename);
RETRIEVE(d, l, "COREDUMP_TRUNCATED", truncated);
RETRIEVE(d, l, "COREDUMP", coredump);
- RETRIEVE(d, l, "COREDUMP_PKGMETA_PACKAGE", pkgmeta_name);
- RETRIEVE(d, l, "COREDUMP_PKGMETA_PACKAGEVERSION", pkgmeta_version);
- RETRIEVE(d, l, "COREDUMP_PKGMETA_JSON", pkgmeta_json);
+ RETRIEVE(d, l, "COREDUMP_PACKAGE_NAME", pkgmeta_name);
+ RETRIEVE(d, l, "COREDUMP_PACKAGE_VERSION", pkgmeta_version);
+ RETRIEVE(d, l, "COREDUMP_PACKAGE_JSON", pkgmeta_json);
RETRIEVE(d, l, "_BOOT_ID", boot_id);
RETRIEVE(d, l, "_MACHINE_ID", machine_id);
RETRIEVE(d, l, "MESSAGE", message);
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
r = json_parse(pkgmeta_json, 0, &v, NULL, NULL);
- if (r < 0) {
+ if (r < 0)
log_warning_errno(r, "json_parse on %s failed, ignoring: %m", pkgmeta_json);
- } else {
+ else {
const char *module_name;
JsonVariant *module_json;
- /* Cannot nest two JSON_VARIANT_OBJECT_FOREACH as they define the same
- * iterator variable '_state' */
- for (struct json_variant_foreach_state _state2 = { (v), 0 }; \
- json_variant_is_object(_state2.variant) && \
- _state2.idx < json_variant_elements(_state2.variant) && \
- ({ module_name = json_variant_string(json_variant_by_index(_state2.variant, _state2.idx)); \
- module_json = json_variant_by_index(_state2.variant, _state2.idx + 1); \
- true; }); \
- _state2.idx += 2) {
- _cleanup_free_ char *module_basename = NULL, *exe_basename = NULL;
- const char *key;
- JsonVariant *w;
-
- /* The module name, most likely parsed from the ELF core file,
- * sometimes contains the full path and sometimes does not. */
- r = path_extract_filename(module_name, &module_basename);
- if (r < 0) {
- log_warning_errno(r, "Failed to parse module basename: %m");
- break;
- }
- r = path_extract_filename(exe, &exe_basename);
- if (r < 0) {
- log_warning_errno(r, "Failed to parse executable basename: %m");
- break;
- }
+ JSON_VARIANT_OBJECT_FOREACH(module_name, module_json, v) {
+ JsonVariant *build_id;
/* We only print the build-id for the 'main' ELF module */
- if (!streq(module_basename, exe_basename))
+ if (!path_equal_filename(module_name, exe))
continue;
- JSON_VARIANT_OBJECT_FOREACH(key, w, module_json) {
- if (!json_variant_is_string(w))
- continue;
-
- if (!streq(key, "buildid"))
- continue;
-
- fprintf(file, " build-id: %s\n", json_variant_string(w));
-
- break;
- }
+ build_id = json_variant_by_key(module_json, "buildId");
+ if (build_id)
+ fprintf(file, " build-id: %s\n", json_variant_string(build_id));
break;
}
* magic ID is always the same. */
if (note_header.n_type == ELF_PACKAGE_METADATA_ID) {
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *w = NULL;
- char *name_key = NULL;
r = json_parse(payload, 0, &v, NULL, NULL);
if (r < 0) {
fputc('\n', c->f);
/* Secondly, if we have a build-id, merge it in the same JSON object
- * so that it apperas all nicely together in the logs/metadata. */
+ * so that it appears all nicely together in the logs/metadata. */
if (id_json) {
r = json_variant_merge(&v, id_json);
if (r < 0) {
}
/* Finally stash the name, so we avoid double visits. */
- name_key = strdup(name);
- if (!name_key) {
- log_oom();
- return DWARF_CB_ABORT;
- }
- r = set_ensure_consume(c->modules, &string_hash_ops, name_key);
+ r = set_put_strdup(c->modules, name);
if (r < 0) {
- log_error_errno(r, "set_ensure_consume failed: %m");
+ log_error_errno(r, "set_put_strdup failed: %m");
return DWARF_CB_ABORT;
}
* The build-id is easy, as libdwfl parses it during the dwfl_core_file_report() call and
* stores it separately in an internal library struct. */
id_len = dwfl_module_build_id(mod, &id, &id_vaddr);
- if (id_len <= 0) {
+ if (id_len <= 0)
/* If we don't find a build-id, note it in the journal message, and try
* anyway to find the package metadata. It's unlikely to have the latter
* without the former, but there's no hard rule. */
- fprintf(c->f, "Found module %s without build-id\n", name);
- } else {
- _cleanup_free_ char *id_hex = NULL, *id_hex_prefixed = NULL;
-
- id_hex = hexmem(id, id_len);
- if (!id_hex) {
- log_oom();
- return DWARF_CB_ABORT;
- }
-
- fprintf(c->f, "Found module %s with build-id: %s\n", name, id_hex);
+ fprintf(c->f, "Found module %s without build-id.\n", name);
+ else {
+ JsonVariant *build_id;
/* We will later parse package metadata json and pass it to our caller. Prepare the
* build-id in json format too, so that it can be appended and parsed cleanly. It
* will then be added as metadata to the journal message with the stack trace. */
- id_hex_prefixed = strjoin("{\"buildid\":\"", id_hex, "\"}");
- if (!id_hex_prefixed) {
- log_oom();
- return DWARF_CB_ABORT;
- }
- r = json_parse(id_hex_prefixed, 0, &id_json, NULL, NULL);
+ r = json_build(&id_json, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("buildId", JSON_BUILD_HEX(id, id_len))));
if (r < 0) {
- log_error_errno(r, "json_parse on %s failed: %m", id_hex_prefixed);
+ log_error_errno(r, "json_build on build-id failed: %m");
return DWARF_CB_ABORT;
}
+
+ build_id = json_variant_by_key(id_json, "buildId");
+ assert_se(build_id);
+ fprintf(c->f, "Found module %s with build-id: %s\n", name, json_variant_string(build_id));
}
/* The .note.package metadata is more difficult. From the module, we need to get a reference
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_bus, sd_bus, bus_free);
_public_ int sd_bus_is_open(sd_bus *bus) {
- assert_return(bus, -EINVAL);
+ if (!bus)
+ return 0;
+
assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
}
_public_ int sd_bus_is_ready(sd_bus *bus) {
- assert_return(bus, -EINVAL);
+ if (!bus)
+ return 0;
+
assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
return log_oom();
}
- if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
+ if (sd_bus_is_ready(m->bus) <= 0) {
log_debug("Not connected to system bus, requesting product UUID later.");
return 0;
}
assert(link->manager);
assert(properties);
- if (!link->manager->bus)
+ if (sd_bus_is_ready(link->manager->bus) <= 0)
return 0;
p = link_bus_path(link);
assert(manager);
assert(properties);
- if (!manager->bus)
+ if (sd_bus_is_ready(manager->bus) <= 0)
return 0;
return sd_bus_emit_properties_changed_strv(
if (r < 0)
return r;
- if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
- log_debug("Not connected to system bus, setting hostname later.");
+ if (sd_bus_is_ready(m->bus) <= 0) {
+ log_debug("Not connected to system bus, setting system hostname later.");
return 0;
}
"sb",
hostname,
false);
-
if (r < 0)
return log_error_errno(r, "Could not set transient hostname: %m");
if (r < 0)
return r;
- if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
- log_debug("Not connected to system bus, setting timezone later.");
+ if (sd_bus_is_ready(m->bus) <= 0) {
+ log_debug("Not connected to system bus, setting system timezone later.");
return 0;
}
log_info("/* %s(backend=%s) */", __func__, firewall_backend_to_string(ctx->backend));
+#if HAVE_LIBIPTC
+ if (ctx->backend == FW_BACKEND_IPTABLES && fw_iptables_init_nat(NULL) < 0) {
+ log_debug("iptables backend is used, but nat table is not enabled, skipping tests");
+ return false;
+ }
+#endif
+
assert_se(fw_add_masquerade(&ctx, true, AF_INET, NULL, 0) == -EINVAL);
assert_se(fw_add_masquerade(&ctx, true, AF_INET, parse_addr("10.1.2.0", &u), 0) == -EINVAL);
if (ctx->backend == FW_BACKEND_NONE)
return EXIT_TEST_SKIP;
-#if HAVE_LIBIPTC
- if (ctx->backend == FW_BACKEND_IPTABLES && fw_iptables_init_nat(NULL) < 0)
- return EXIT_TEST_SKIP;
-#endif
-
if (test_v4(ctx) && ctx->backend == FW_BACKEND_NFTABLES)
test_v6(ctx);
assert_se(!path_equal_ptr("/a", "/b"));
assert_se(!path_equal_ptr("/a", NULL));
assert_se(!path_equal_ptr(NULL, "/a"));
+
+ assert_se(path_equal_filename("/a/c", "/b/c"));
+ assert_se(path_equal_filename("/a", "/a"));
+ assert_se(!path_equal_filename("/a/b", "/a/c"));
+ assert_se(!path_equal_filename("/b", "/c"));
}
static void test_path_equal_root(void) {
#include <linux/pci_regs.h>
#include "alloc-util.h"
+#include "device-util.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
return strneq(p + 2, "04", 2);
}
+static int parse_hotplug_slot_from_function_id(sd_device *dev, const char *slots, uint32_t *ret) {
+ uint64_t function_id;
+ char path[PATH_MAX];
+ const char *attr;
+ int r;
+
+ /* The <sysname>/function_id attribute is unique to the s390 PCI driver. If present, we know
+ * that the slot's directory name for this device is /sys/bus/pci/XXXXXXXX/ where XXXXXXXX is
+ * the fixed length 8 hexadecimal character string representation of function_id. Therefore we
+ * can short cut here and just check for the existence of the slot directory. As this directory
+ * has to exist, we're emitting a debug message for the unlikely case it's not found. Note that
+ * the domain part doesn't belong to the slot name here because there's a 1-to-1 relationship
+ * between PCI function and its hotplug slot. */
+
+ assert(dev);
+ assert(slots);
+ assert(ret);
+
+ if (!naming_scheme_has(NAMING_SLOT_FUNCTION_ID))
+ return 0;
+
+ if (sd_device_get_sysattr_value(dev, "function_id", &attr) < 0)
+ return 0;
+
+ r = safe_atou64(attr, &function_id);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to parse function_id, ignoring: %s", attr);
+
+ if (function_id <= 0 || function_id > UINT32_MAX)
+ return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
+ "Invalid function id (0x%"PRIx64"), ignoring.",
+ function_id);
+
+ if (!snprintf_ok(path, sizeof path, "%s/%08"PRIx64, slots, function_id))
+ return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ENAMETOOLONG),
+ "PCI slot path is too long, ignoring.");
+
+ if (access(path, F_OK) < 0)
+ return log_device_debug_errno(dev, errno, "Cannot access %s, ignoring: %m", path);
+
+ *ret = (uint32_t) function_id;
+ return 1;
+}
+
static int dev_pci_slot(sd_device *dev, struct netnames *names) {
- unsigned long dev_port = 0;
- unsigned domain, bus, slot, func;
- int hotplug_slot = -1;
- size_t l;
- char *s;
const char *sysname, *attr, *port_name = NULL, *syspath;
_cleanup_(sd_device_unrefp) sd_device *pci = NULL;
- sd_device *hotplug_slot_dev;
- char slots[PATH_MAX];
_cleanup_closedir_ DIR *dir = NULL;
- struct dirent *dent;
+ unsigned domain, bus, slot, func;
+ sd_device *hotplug_slot_dev;
+ unsigned long dev_port = 0;
+ uint32_t hotplug_slot = 0;
+ char slots[PATH_MAX], *s;
+ size_t l;
int r;
r = sd_device_get_sysname(names->pcidev, &sysname);
hotplug_slot_dev = names->pcidev;
while (hotplug_slot_dev) {
- if (sd_device_get_sysname(hotplug_slot_dev, &sysname) < 0)
- continue;
+ struct dirent *dent;
- /* The <sysname>/function_id attribute is unique to the s390 PCI driver.
- If present, we know that the slot's directory name for this device is
- /sys/bus/pci/XXXXXXXX/ where XXXXXXXX is the fixed length 8 hexadecimal
- character string representation of function_id.
- Therefore we can short cut here and just check for the existence of
- the slot directory. As this directory has to exist, we're emitting a
- debug message for the unlikely case it's not found.
- Note that the domain part of doesn't belong to the slot name here
- because there's a 1-to-1 relationship between PCI function and its hotplug
- slot.
- */
- if (naming_scheme_has(NAMING_SLOT_FUNCTION_ID) &&
- sd_device_get_sysattr_value(hotplug_slot_dev, "function_id", &attr) >= 0) {
- int function_id;
- _cleanup_free_ char *str;
-
- if (safe_atoi(attr, &function_id) >= 0 &&
- asprintf(&str, "%s/%08x/", slots, function_id) >= 0 &&
- access(str, R_OK) == 0) {
- hotplug_slot = function_id;
- domain = 0;
- } else
- log_debug("No matching slot for function_id (%s).", attr);
+ r = parse_hotplug_slot_from_function_id(hotplug_slot_dev, slots, &hotplug_slot);
+ if (r < 0)
+ return 0;
+ if (r > 0) {
+ domain = 0; /* See comments in parse_hotplug_slot_from_function_id(). */
break;
}
+ r = sd_device_get_sysname(hotplug_slot_dev, &sysname);
+ if (r < 0)
+ return log_device_debug_errno(hotplug_slot_dev, r, "Failed to get sysname: %m");
+
FOREACH_DIRENT_ALL(dent, dir, break) {
- int i;
- char str[PATH_MAX];
_cleanup_free_ char *address = NULL;
+ char str[PATH_MAX];
+ uint32_t i;
if (dot_or_dot_dot(dent->d_name))
continue;
- r = safe_atoi(dent->d_name, &i);
+ r = safe_atou32(dent->d_name, &i);
if (r < 0 || i <= 0)
continue;
* devices that will try to claim the same index and that would create name
* collision. */
if (naming_scheme_has(NAMING_BRIDGE_NO_SLOT) && is_pci_bridge(hotplug_slot_dev))
- hotplug_slot = 0;
+ return 0;
break;
}
}
- if (hotplug_slot >= 0)
+ if (hotplug_slot > 0)
break;
if (sd_device_get_parent_with_subsystem_devtype(hotplug_slot_dev, "pci", NULL, &hotplug_slot_dev) < 0)
break;
l = sizeof(names->pci_slot);
if (domain > 0)
l = strpcpyf(&s, l, "P%d", domain);
- l = strpcpyf(&s, l, "s%d", hotplug_slot);
+ l = strpcpyf(&s, l, "s%"PRIu32, hotplug_slot);
if (func > 0 || is_pci_multifunction(names->pcidev))
l = strpcpyf(&s, l, "f%d", func);
if (port_name)
udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
if (names.pci_slot[0] &&
- snprintf(str, sizeof str, "%s%s%s", prefix, names.pci_slot, names.bcma_core))
+ snprintf_ok(str, sizeof str, "%s%s%s", prefix, names.pci_slot, names.bcma_core))
udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str);
return 0;
}
systemd-dissect --json=short ${image}.raw | grep -q -F '{"rw":"ro","designator":"root","partition_uuid":null,"partition_label":null,"fstype":"squashfs","architecture":null,"verity":"external"'
systemd-dissect ${image}.raw | grep -q -F "MARKER=1"
-systemd-dissect ${image}.raw | grep -q -F -f $os_release
+systemd-dissect ${image}.raw | grep -q -F -f <(sed 's/"//g' $os_release)
mv ${image}.verity ${image}.fooverity
mv ${image}.roothash ${image}.foohash
systemd-dissect --json=short ${image}.raw --root-hash=${roothash} --verity-data=${image}.fooverity | grep -q -F '{"rw":"ro","designator":"root","partition_uuid":null,"partition_label":null,"fstype":"squashfs","architecture":null,"verity":"external"'
systemd-dissect ${image}.raw --root-hash=${roothash} --verity-data=${image}.fooverity | grep -q -F "MARKER=1"
-systemd-dissect ${image}.raw --root-hash=${roothash} --verity-data=${image}.fooverity | grep -q -F -f $os_release
+systemd-dissect ${image}.raw --root-hash=${roothash} --verity-data=${image}.fooverity | grep -q -F -f <(sed 's/"//g' $os_release)
mv ${image}.fooverity ${image}.verity
mv ${image}.foohash ${image}.roothash
systemd-dissect --json=short --root-hash ${roothash} ${image}.gpt | grep -q '{"rw":"ro","designator":"root","partition_uuid":"'$ROOT_UUID'","partition_label":"Root Partition","fstype":"squashfs","architecture":"'$architecture'","verity":"yes","node":'
systemd-dissect --json=short --root-hash ${roothash} ${image}.gpt | grep -q '{"rw":"ro","designator":"root-verity","partition_uuid":"'$VERITY_UUID'","partition_label":"Verity Partition","fstype":"DM_verity_hash","architecture":"'$architecture'","verity":null,"node":'
systemd-dissect --root-hash ${roothash} ${image}.gpt | grep -q -F "MARKER=1"
-systemd-dissect --root-hash ${roothash} ${image}.gpt | grep -q -F -f $os_release
+systemd-dissect --root-hash ${roothash} ${image}.gpt | grep -q -F -f <(sed 's/"//g' $os_release)
systemd-dissect --root-hash ${roothash} --mount ${image}.gpt ${image_dir}/mount
cat ${image_dir}/mount/usr/lib/os-release | grep -q -F -f $os_release