imds preparation (#41214)

This commit is contained in:
Daan De Meyer
2026-03-20 15:14:21 +01:00
committed by GitHub
5 changed files with 134 additions and 4 deletions
+8 -4
View File
@@ -2,24 +2,28 @@
ACTION=="remove", GOTO="dmi_end"
SUBSYSTEM!="dmi", GOTO="dmi_end"
KERNEL!="id", GOTO="dmi_end"
ENV{ID_SYS_VENDOR_IS_RUBBISH}!="1", ENV{ID_VENDOR}="$attr{sys_vendor}"
ENV{ID_SYSFS_ATTRIBUTE_MODEL}=="", ENV{ID_PRODUCT_NAME_IS_RUBBISH}!="1", ENV{ID_MODEL}="$attr{product_name}"
ENV{ID_SYSFS_ATTRIBUTE_MODEL}=="product_name", ENV{ID_MODEL}="$attr{product_name}"
ENV{ID_SYSFS_ATTRIBUTE_MODEL}=="product_version", ENV{ID_MODEL}="$attr{product_version}"
# fallback to board information
# Fallback to board information
ENV{ID_VENDOR}=="", ENV{ID_VENDOR}="$attr{board_vendor}"
ENV{ID_MODEL}=="", ENV{ID_MODEL}="$attr{board_name}"
# stock keeping unit
# Stock keeping unit
ENV{ID_PRODUCT_SKU_IS_RUBBISH}!="1", ENV{ID_SKU}="$attr{product_sku}"
# hardware version
# Hardware version
ENV{ID_PRODUCT_VERSION_IS_RUBBISH}!="1", ENV{ID_HARDWARE_VERSION}="$attr{product_version}"
ENV{ID_HARDWARE_VERSION}=="", ENV{ID_BOARD_VERSION_IS_RUBBISH}!="1", ENV{ID_HARDWARE_VERSION}="$attr{board_version}"
# chassis asset tag
# Chassis asset tag
ENV{MODALIAS}!="", ATTR{chassis_asset_tag}!="", IMPORT{builtin}="hwdb '$attr{modalias}cat$attr{chassis_asset_tag}:'"
ENV{ID_CHASSIS_ASSET_TAG_IS_RUBBISH}!="1", ENV{ID_CHASSIS_ASSET_TAG}="$attr{chassis_asset_tag}"
# Allow units to be ordered after the DMI device
TAG+="systemd"
LABEL="dmi_end"
+62
View File
@@ -7,12 +7,15 @@
#include <unistd.h>
#include "alloc-util.h"
#include "chase.h"
#include "errno-util.h"
#include "extract-word.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "hexdecoct.h"
#include "io-util.h"
#include "iovec-util.h"
#include "label.h"
#include "log.h"
#include "mkdir.h"
@@ -1655,3 +1658,62 @@ int warn_file_is_world_accessible(const char *filename, struct stat *st, const c
filename, st->st_mode & 07777);
return 0;
}
int write_data_file_atomic_at(
int dir_fd,
const char *path,
const struct iovec *iovec,
WriteDataFileFlags flags) {
int r;
assert(dir_fd >= 0 || IN_SET(dir_fd, AT_FDCWD, XAT_FDROOT));
/* This is a cousin of write_string_file_atomic(), but operates with arbitrary struct iovec binary
* data (rather than strings), works without FILE* streams, and does direct syscalls instead. */
_cleanup_free_ char *dn = NULL, *fn = NULL;
r = path_split_prefix_filename(path, &dn, &fn);
if (IN_SET(r, -EADDRNOTAVAIL, O_DIRECTORY))
return -EISDIR; /* path refers to "." or "/" (which are dirs, which we cannot write), or is suffixed with "/" */
if (r < 0)
return r;
_cleanup_close_ int mfd = -EBADF;
if (dn) {
/* If there's a directory component, readjust our position */
r = chaseat(dir_fd,
dn,
FLAGS_SET(flags, WRITE_DATA_FILE_MKDIR_0755) ? CHASE_MKDIR_0755 : 0,
/* ret_path= */ NULL,
&mfd);
if (r < 0)
return r;
dir_fd = mfd;
}
_cleanup_free_ char *t = NULL;
_cleanup_close_ int fd = open_tmpfile_linkable_at(dir_fd, fn, O_WRONLY|O_CLOEXEC, &t);
if (fd < 0)
return fd;
CLEANUP_TMPFILE_AT(dir_fd, t);
if (iovec_is_set(iovec)) {
r = loop_write(fd, iovec->iov_base, iovec->iov_len);
if (r < 0)
return r;
}
r = fchmod_umask(fd, 0644);
if (r < 0)
return r;
r = link_tmpfile_at(fd, dir_fd, t, fn, LINK_TMPFILE_REPLACE);
if (r < 0)
return r;
t = mfree(t); /* disarm CLEANUP_TMPFILE_AT */
return 0;
}
+6
View File
@@ -163,3 +163,9 @@ int safe_fgetc(FILE *f, char *ret);
int warn_file_is_world_accessible(const char *filename, struct stat *st, const char *unit, unsigned line);
int fopen_mode_to_flags(const char *mode);
typedef enum WriteDataFileFlags {
WRITE_DATA_FILE_MKDIR_0755 = 1 << 0,
} WriteDataFileFlags;
int write_data_file_atomic_at(int dir_fd, const char *path, const struct iovec *iovec, WriteDataFileFlags flags);
+6
View File
@@ -24,6 +24,12 @@ struct iovec* iovec_make_string(struct iovec *iovec, const char *s);
.iov_len = STRLEN(s), \
}
#define IOVEC_MAKE_BYTE(c) \
(const struct iovec) { \
.iov_base = (char*) ((const char[]) { c }), \
.iov_len = 1, \
}
void iovec_done_erase(struct iovec *iovec);
char* set_iovec_string_field(struct iovec *iovec, size_t *n_iovec, const char *field, const char *value);
+52
View File
@@ -9,6 +9,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "iovec-util.h"
#include "memfd-util.h"
#include "parse-util.h"
#include "path-util.h"
@@ -695,4 +696,55 @@ TEST(fdopen_independent) {
f = safe_fclose(f);
}
TEST(write_data_file_atomic_at) {
struct iovec a = IOVEC_MAKE_STRING("hallo");
ASSERT_OK(write_data_file_atomic_at(AT_FDCWD, "/tmp/wdfa", &a, /* flags= */ 0));
_cleanup_(iovec_done) struct iovec ra = {};
ASSERT_OK(read_full_file("/tmp/wdfa", (char**) &ra.iov_base, &ra.iov_len));
ASSERT_EQ(iovec_memcmp(&a, &ra), 0);
ASSERT_OK_ERRNO(unlink("/tmp/wdfa"));
ASSERT_OK(write_data_file_atomic_at(XAT_FDROOT, "tmp/wdfa", &a, /* flags= */ 0));
iovec_done(&ra);
ASSERT_OK(read_full_file("/tmp/wdfa", (char**) &ra.iov_base, &ra.iov_len));
ASSERT_EQ(iovec_memcmp(&a, &ra), 0);
ASSERT_OK_ERRNO(unlink("/tmp/wdfa"));
ASSERT_ERROR(write_data_file_atomic_at(AT_FDCWD, NULL, &a, /* flags= */ 0), EINVAL);
ASSERT_ERROR(write_data_file_atomic_at(AT_FDCWD, "", &a, /* flags= */ 0), EINVAL);
ASSERT_ERROR(write_data_file_atomic_at(AT_FDCWD, "/", &a, /* flags= */ 0), EISDIR);
ASSERT_ERROR(write_data_file_atomic_at(AT_FDCWD, ".", &a, /* flags= */ 0), EISDIR);
ASSERT_ERROR(write_data_file_atomic_at(AT_FDCWD, "/tmp/", &a, /* flags= */ 0), EISDIR);
_cleanup_free_ char *cwd = NULL;
ASSERT_OK(safe_getcwd(&cwd));
ASSERT_OK_ERRNO(chdir("/tmp"));
ASSERT_OK(write_data_file_atomic_at(AT_FDCWD, "wdfa", &a, /* flags= */ 0));
iovec_done(&ra);
ASSERT_OK(read_full_file("/tmp/wdfa", (char**) &ra.iov_base, &ra.iov_len));
ASSERT_EQ(iovec_memcmp(&a, &ra), 0);
ASSERT_OK_ERRNO(unlink("/tmp/wdfa"));
ASSERT_OK(write_data_file_atomic_at(XAT_FDROOT, "tmp/wdfa", &a, /* flags= */ 0));
iovec_done(&ra);
ASSERT_OK(read_full_file("/tmp/wdfa", (char**) &ra.iov_base, &ra.iov_len));
ASSERT_EQ(iovec_memcmp(&a, &ra), 0);
ASSERT_OK_ERRNO(unlink("/tmp/wdfa"));
ASSERT_OK_ERRNO(chdir(cwd));
ASSERT_ERROR(write_data_file_atomic_at(XAT_FDROOT, "tmp/zzz/wdfa", &a, /* flags= */ 0), ENOENT);
ASSERT_OK(write_data_file_atomic_at(XAT_FDROOT, "tmp/zzz/wdfa", &a, WRITE_DATA_FILE_MKDIR_0755));
iovec_done(&ra);
ASSERT_OK(read_full_file("/tmp/zzz/wdfa", (char**) &ra.iov_base, &ra.iov_len));
ASSERT_EQ(iovec_memcmp(&a, &ra), 0);
ASSERT_OK_ERRNO(unlink("/tmp/zzz/wdfa"));
ASSERT_ERROR(write_data_file_atomic_at(AT_FDCWD, "/tmp/zzz", &a, /* flags= */ 0), EEXIST);
ASSERT_OK_ERRNO(rmdir("/tmp/zzz"));
}
DEFINE_TEST_MAIN(LOG_DEBUG);