#include "hashmap.h"
#include "id128-util.h"
#include "io-util.h"
+#include "iovec-util.h"
#include "json-util.h"
#include "kernel-image.h"
#include "log.h"
/* The source and the temporary file we copy it into */
int source_fd, temp_fd;
char *filename, *temp_filename;
+ struct iovec data; /* Alternative to 'source_fd': literal data */
} ExtraFile;
#define EXTRA_FILE_NULL \
x->temp_fd = safe_close(x->temp_fd);
x->filename = mfree(x->filename);
x->temp_filename = mfree(x->temp_filename);
+ iovec_done(&x->data);
}
static void profile_done(Profile *p) {
}
static int begin_copy_file(
- int source_fd,
+ int source_fd, /* Either the source fd is specified, or the 'data' below, not both */
+ const struct iovec *data,
const char *filename,
int target_dir_fd,
int *ret_tmpfile_fd,
int r;
- assert(source_fd >= 0);
assert(filename);
assert(target_dir_fd >= 0);
assert(ret_tmpfile_fd);
CLEANUP_TMPFILE_AT(target_dir_fd, t);
- r = copy_bytes(source_fd, write_fd, UINT64_MAX, COPY_REFLINK|COPY_SEEK0_SOURCE);
- if (r < 0)
- return log_error_errno(r, "Failed to copy data into '%s': %m", filename);
+ if (source_fd >= 0) {
+ r = copy_bytes(source_fd, write_fd, UINT64_MAX, COPY_REFLINK|COPY_SEEK0_SOURCE);
+ if (r < 0)
+ return log_error_errno(r, "Failed to copy data into '%s': %m", filename);
+
+ (void) copy_times(source_fd, write_fd, /* flags= */ 0);
+ } else if (iovec_is_set(data)) {
+ r = loop_write(write_fd, data->iov_base, data->iov_len);
+ if (r < 0)
+ return log_error_errno(r, "Failed to write data into '%s': %m", filename);
+ }
- (void) copy_times(source_fd, write_fd, /* flags= */ 0);
(void) fchmod(write_fd, 0644);
*ret_tmpfile_fd = TAKE_FD(write_fd);
r = begin_copy_file(
c->kernel_fd,
+ /* data= */ NULL,
c->kernel_filename,
c->entry_token_dir_fd,
&c->kernel_temp_fd,
FOREACH_ARRAY(x, c->extra, c->n_extra) {
r = begin_copy_file(
x->source_fd,
+ &x->data,
x->filename,
c->entry_token_dir_fd,
&x->temp_fd,
static const sd_json_dispatch_field dispatch_table[] = {
{ "filename", SD_JSON_VARIANT_STRING, json_dispatch_loader_entry_resource_filename, offsetof(ExtraParameters, extra_file.filename), SD_JSON_MANDATORY },
- { "fileDescriptor", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint, offsetof(ExtraParameters, fd_index), SD_JSON_MANDATORY },
+ { "fileDescriptor", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint, offsetof(ExtraParameters, fd_index), 0 },
+ { "data", SD_JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(ExtraParameters, extra_file.data), 0 },
{},
};
if (r < 0)
return r;
- xp.extra_file.source_fd = sd_varlink_peek_dup_fd(c->link, xp.fd_index);
- if (xp.extra_file.source_fd < 0)
- return log_debug_errno(xp.extra_file.source_fd, "Failed to acquire extra fd from Varlink: %m");
-
- r = fd_verify_safe_flags(xp.extra_file.source_fd);
- if (r < 0)
+ if (iovec_is_set(&xp.extra_file.data) == (xp.fd_index != UINT_MAX))
return sd_varlink_error_invalid_parameter_name(c->link, name);
+ if (xp.fd_index != UINT_MAX) {
+ xp.extra_file.source_fd = sd_varlink_peek_dup_fd(c->link, xp.fd_index);
+ if (xp.extra_file.source_fd < 0)
+ return log_debug_errno(xp.extra_file.source_fd, "Failed to acquire extra fd from Varlink: %m");
- r = fd_verify_regular(xp.extra_file.source_fd);
- if (r < 0)
- return log_debug_errno(r, "Failed to validate that the extra file is a regular file descriptor: %m");
+ r = fd_verify_safe_flags(xp.extra_file.source_fd);
+ if (r < 0)
+ return sd_varlink_error_invalid_parameter_name(c->link, name);
+
+ r = fd_verify_regular(xp.extra_file.source_fd);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to validate that the extra file is a regular file descriptor: %m");
+ }
if (!GREEDY_REALLOC(c->context.extra, c->context.n_extra+1))
return log_oom();
BootEntryExtraFile,
SD_VARLINK_FIELD_COMMENT("The name of the extra file"),
SD_VARLINK_DEFINE_FIELD(filename, SD_VARLINK_STRING, 0),
- SD_VARLINK_FIELD_COMMENT("Index into array of file descriptors, pointing to a file descriptor referencing the extra file."),
- SD_VARLINK_DEFINE_FIELD(fileDescriptor, SD_VARLINK_INT, 0));
+ SD_VARLINK_FIELD_COMMENT("Index into array of file descriptors, pointing to a file descriptor referencing the extra file to copy in. Either this or the 'data' field below must be set – not both, not neither."),
+ SD_VARLINK_DEFINE_FIELD(fileDescriptor, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Literal data to place in the extra file."),
+ SD_VARLINK_DEFINE_FIELD(data, SD_VARLINK_STRING, SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_METHOD(
Link,