mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
varlinkctl: optionally push fds to server
This commit is contained in:
@@ -338,6 +338,22 @@
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--push-fd=</option></term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>Takes a numeric file descriptor number as parameter. May be used to pass a file
|
||||||
|
descriptor along with the method call, if the underlying transport supports this. May be used
|
||||||
|
multiple times to pass multiple file descriptors, retaining the order in which they are
|
||||||
|
specified. The specified file descriptors must be passed to the <command>varlinkctl</command>
|
||||||
|
invocation. Optionally, in place of a numeric file descriptor number an absolute or relative file
|
||||||
|
system path (the latter must be prefixed with <literal>./</literal>) may be specified, which is
|
||||||
|
opened in read-only mode.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<xi:include href="standard-options.xml" xpointer="no-pager" />
|
<xi:include href="standard-options.xml" xpointer="no-pager" />
|
||||||
<xi:include href="standard-options.xml" xpointer="help" />
|
<xi:include href="standard-options.xml" xpointer="help" />
|
||||||
<xi:include href="standard-options.xml" xpointer="version" />
|
<xi:include href="standard-options.xml" xpointer="version" />
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "memfd-util.h"
|
#include "memfd-util.h"
|
||||||
#include "pager.h"
|
#include "pager.h"
|
||||||
#include "parse-argument.h"
|
#include "parse-argument.h"
|
||||||
|
#include "parse-util.h"
|
||||||
#include "pretty-print.h"
|
#include "pretty-print.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
@@ -29,6 +30,11 @@
|
|||||||
#include "verbs.h"
|
#include "verbs.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
|
typedef struct PushFds {
|
||||||
|
int *fds;
|
||||||
|
size_t n_fds;
|
||||||
|
} PushFds;
|
||||||
|
|
||||||
static sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF;
|
static sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF;
|
||||||
static PagerFlags arg_pager_flags = 0;
|
static PagerFlags arg_pager_flags = 0;
|
||||||
static sd_varlink_method_flags_t arg_method_flags = 0;
|
static sd_varlink_method_flags_t arg_method_flags = 0;
|
||||||
@@ -37,8 +43,17 @@ static bool arg_quiet = false;
|
|||||||
static char **arg_graceful = NULL;
|
static char **arg_graceful = NULL;
|
||||||
static usec_t arg_timeout = 0;
|
static usec_t arg_timeout = 0;
|
||||||
static bool arg_exec = false;
|
static bool arg_exec = false;
|
||||||
|
static PushFds arg_push_fds = {};
|
||||||
|
|
||||||
|
static void push_fds_done(PushFds *p) {
|
||||||
|
assert(p);
|
||||||
|
|
||||||
|
close_many_and_free(p->fds, p->n_fds);
|
||||||
|
*p = (PushFds) {};
|
||||||
|
}
|
||||||
|
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_graceful, strv_freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_graceful, strv_freep);
|
||||||
|
STATIC_DESTRUCTOR_REGISTER(arg_push_fds, push_fds_done);
|
||||||
|
|
||||||
static int help(void) {
|
static int help(void) {
|
||||||
_cleanup_free_ char *link = NULL;
|
_cleanup_free_ char *link = NULL;
|
||||||
@@ -80,6 +95,7 @@ static int help(void) {
|
|||||||
" --graceful=ERROR Treat specified Varlink error as success\n"
|
" --graceful=ERROR Treat specified Varlink error as success\n"
|
||||||
" --timeout=SECS Maximum time to wait for method call completion\n"
|
" --timeout=SECS Maximum time to wait for method call completion\n"
|
||||||
" -E Short for --more --timeout=infinity\n"
|
" -E Short for --more --timeout=infinity\n"
|
||||||
|
" --push-fd=FD Pass the specified fd along with method call\n"
|
||||||
"\nSee the %2$s for details.\n",
|
"\nSee the %2$s for details.\n",
|
||||||
program_invocation_short_name,
|
program_invocation_short_name,
|
||||||
link,
|
link,
|
||||||
@@ -107,6 +123,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
ARG_GRACEFUL,
|
ARG_GRACEFUL,
|
||||||
ARG_TIMEOUT,
|
ARG_TIMEOUT,
|
||||||
ARG_EXEC,
|
ARG_EXEC,
|
||||||
|
ARG_PUSH_FD,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct option options[] = {
|
static const struct option options[] = {
|
||||||
@@ -121,6 +138,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
{ "graceful", required_argument, NULL, ARG_GRACEFUL },
|
{ "graceful", required_argument, NULL, ARG_GRACEFUL },
|
||||||
{ "timeout", required_argument, NULL, ARG_TIMEOUT },
|
{ "timeout", required_argument, NULL, ARG_TIMEOUT },
|
||||||
{ "exec", no_argument, NULL, ARG_EXEC },
|
{ "exec", no_argument, NULL, ARG_EXEC },
|
||||||
|
{ "push-fd", required_argument, NULL, ARG_PUSH_FD },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -205,6 +223,34 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
arg_exec = true;
|
arg_exec = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ARG_PUSH_FD: {
|
||||||
|
if (!GREEDY_REALLOC(arg_push_fds.fds, arg_push_fds.n_fds + 1))
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
_cleanup_close_ int add_fd = -EBADF;
|
||||||
|
if (STARTSWITH_SET(optarg, "/", "./")) {
|
||||||
|
/* We usually expect a numeric fd spec, but as an extension let's treat this
|
||||||
|
* as a path to open in read-only mode in case this is clearly an absolute or
|
||||||
|
* relative path */
|
||||||
|
add_fd = open(optarg, O_CLOEXEC|O_RDONLY|O_NOCTTY);
|
||||||
|
if (add_fd < 0)
|
||||||
|
return log_error_errno(errno, "Failed to open '%s': %m", optarg);
|
||||||
|
} else {
|
||||||
|
int parsed_fd = parse_fd(optarg);
|
||||||
|
if (parsed_fd < 0)
|
||||||
|
return log_error_errno(parsed_fd, "Failed to parse --push-fd= parameter: %s", optarg);
|
||||||
|
|
||||||
|
/* Make a copy, so that the same fd could be used multiple times in a reasonable
|
||||||
|
* way. This also validates the fd early */
|
||||||
|
add_fd = fcntl(parsed_fd, F_DUPFD_CLOEXEC, 3);
|
||||||
|
if (add_fd < 0)
|
||||||
|
return log_error_errno(errno, "Failed to duplicate file descriptor %i: %m", parsed_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
arg_push_fds.fds[arg_push_fds.n_fds++] = TAKE_FD(add_fd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@@ -616,6 +662,20 @@ static int verb_call(int argc, char *argv[], void *userdata) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
if (arg_push_fds.n_fds > 0) {
|
||||||
|
r = sd_varlink_set_allow_fd_passing_output(vl, true);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to enable fd passing: %m");
|
||||||
|
|
||||||
|
FOREACH_ARRAY(f, arg_push_fds.fds, arg_push_fds.n_fds) {
|
||||||
|
r = sd_varlink_push_fd(vl, *f);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to push file descriptor: %m");
|
||||||
|
|
||||||
|
TAKE_FD(*f); /* we passed ownership away */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (arg_collect) {
|
if (arg_collect) {
|
||||||
sd_json_variant *reply = NULL;
|
sd_json_variant *reply = NULL;
|
||||||
const char *error = NULL;
|
const char *error = NULL;
|
||||||
|
|||||||
Reference in New Issue
Block a user