core: add OpenFile setting
This commit is contained in:
committed by
Lennart Poettering
parent
81315baa68
commit
cd48e23f6a
@@ -29,6 +29,7 @@
|
||||
#include "mountpoint-util.h"
|
||||
#include "nsflags.h"
|
||||
#include "numa-util.h"
|
||||
#include "open-file.h"
|
||||
#include "parse-helpers.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
@@ -410,6 +411,23 @@ static int bus_append_exec_command(sd_bus_message *m, const char *field, const c
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int bus_append_open_file(sd_bus_message *m, const char *field, const char *eq) {
|
||||
_cleanup_(open_file_freep) OpenFile *of = NULL;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
r = open_file_parse(eq, &of);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse OpenFile= setting: %m");
|
||||
|
||||
r = sd_bus_message_append(m, "(sv)", field, "a(sst)", (size_t) 1, of->path, of->fdname, of->flags);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int bus_append_ip_address_access(sd_bus_message *m, int family, const union in_addr_union *prefix, unsigned char prefixlen) {
|
||||
int r;
|
||||
|
||||
@@ -2300,6 +2318,9 @@ static int bus_append_service_property(sd_bus_message *m, const char *field, con
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (streq(field, "OpenFile"))
|
||||
return bus_append_open_file(m, field, eq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -243,6 +243,8 @@ shared_sources = files(
|
||||
'nsflags.h',
|
||||
'numa-util.c',
|
||||
'numa-util.h',
|
||||
'open-file.c',
|
||||
'open-file.h',
|
||||
'openssl-util.c',
|
||||
'openssl-util.h',
|
||||
'output-mode.c',
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "escape.h"
|
||||
#include "extract-word.h"
|
||||
#include "fd-util.h"
|
||||
#include "open-file.h"
|
||||
#include "path-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
|
||||
int open_file_parse(const char *v, OpenFile **ret) {
|
||||
_cleanup_free_ char *options = NULL;
|
||||
_cleanup_(open_file_freep) OpenFile *of = NULL;
|
||||
int r;
|
||||
|
||||
assert(v);
|
||||
assert(ret);
|
||||
|
||||
of = new0(OpenFile, 1);
|
||||
if (!of)
|
||||
return -ENOMEM;
|
||||
|
||||
r = extract_many_words(&v, ":", EXTRACT_DONT_COALESCE_SEPARATORS|EXTRACT_CUNESCAPE, &of->path, &of->fdname, &options, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Enforce that at most 3 colon-separated words are present */
|
||||
if (!isempty(v))
|
||||
return -EINVAL;
|
||||
|
||||
for (const char *p = options;;) {
|
||||
OpenFileFlag flag;
|
||||
_cleanup_free_ char *word = NULL;
|
||||
|
||||
r = extract_first_word(&p, &word, ",", 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
flag = open_file_flags_from_string(word);
|
||||
if (flag < 0)
|
||||
return flag;
|
||||
|
||||
if ((flag & of->flags) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
of->flags |= flag;
|
||||
}
|
||||
|
||||
if (isempty(of->fdname)) {
|
||||
free(of->fdname);
|
||||
r = path_extract_filename(of->path, &of->fdname);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = open_file_validate(of);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(of);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int open_file_validate(const OpenFile *of) {
|
||||
assert(of);
|
||||
|
||||
if (!path_is_valid(of->path) || !path_is_absolute(of->path))
|
||||
return -EINVAL;
|
||||
|
||||
if (!fdname_is_valid(of->fdname))
|
||||
return -EINVAL;
|
||||
|
||||
if ((FLAGS_SET(of->flags, OPENFILE_READ_ONLY) + FLAGS_SET(of->flags, OPENFILE_APPEND) +
|
||||
FLAGS_SET(of->flags, OPENFILE_TRUNCATE)) > 1)
|
||||
return -EINVAL;
|
||||
|
||||
if ((of->flags & ~_OPENFILE_MASK_PUBLIC) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int open_file_to_string(const OpenFile *of, char **ret) {
|
||||
_cleanup_free_ char *options = NULL, *fname = NULL, *s = NULL;
|
||||
bool has_fdname = false;
|
||||
int r;
|
||||
|
||||
assert(of);
|
||||
assert(ret);
|
||||
|
||||
s = shell_escape(of->path, ":");
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
r = path_extract_filename(of->path, &fname);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
has_fdname = !streq(fname, of->fdname);
|
||||
if (has_fdname)
|
||||
if (!strextend(&s, ":", of->fdname))
|
||||
return -ENOMEM;
|
||||
|
||||
for (OpenFileFlag flag = OPENFILE_READ_ONLY; flag < _OPENFILE_MAX; flag <<= 1)
|
||||
if (FLAGS_SET(of->flags, flag) && !strextend_with_separator(&options, ",", open_file_flags_to_string(flag)))
|
||||
return -ENOMEM;
|
||||
|
||||
if (options)
|
||||
if (!(has_fdname ? strextend(&s, ":", options) : strextend(&s, "::", options)))
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = TAKE_PTR(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
OpenFile *open_file_free(OpenFile *of) {
|
||||
if (!of)
|
||||
return NULL;
|
||||
|
||||
free(of->path);
|
||||
free(of->fdname);
|
||||
return mfree(of);
|
||||
}
|
||||
|
||||
void open_file_free_many(OpenFile **head) {
|
||||
OpenFile *of;
|
||||
|
||||
while ((of = *head)) {
|
||||
LIST_REMOVE(open_files, *head, of);
|
||||
of = open_file_free(of);
|
||||
}
|
||||
}
|
||||
|
||||
static const char * const open_file_flags_table[_OPENFILE_MAX] = {
|
||||
[OPENFILE_READ_ONLY] = "read-only",
|
||||
[OPENFILE_APPEND] = "append",
|
||||
[OPENFILE_TRUNCATE] = "truncate",
|
||||
[OPENFILE_GRACEFUL] = "graceful",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(open_file_flags, OpenFileFlag);
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "list.h"
|
||||
|
||||
typedef enum OpenFileFlag {
|
||||
OPENFILE_READ_ONLY = 1 << 0,
|
||||
OPENFILE_APPEND = 1 << 1,
|
||||
OPENFILE_TRUNCATE = 1 << 2,
|
||||
OPENFILE_GRACEFUL = 1 << 3,
|
||||
_OPENFILE_MAX,
|
||||
_OPENFILE_INVALID = -EINVAL,
|
||||
_OPENFILE_MASK_PUBLIC = OPENFILE_READ_ONLY | OPENFILE_APPEND | OPENFILE_TRUNCATE | OPENFILE_GRACEFUL,
|
||||
} OpenFileFlag;
|
||||
|
||||
typedef struct OpenFile {
|
||||
char *path;
|
||||
char *fdname;
|
||||
OpenFileFlag flags;
|
||||
LIST_FIELDS(struct OpenFile, open_files);
|
||||
} OpenFile;
|
||||
|
||||
int open_file_parse(const char *v, OpenFile **ret);
|
||||
|
||||
int open_file_validate(const OpenFile *of);
|
||||
|
||||
int open_file_to_string(const OpenFile *of, char **ret);
|
||||
|
||||
OpenFile *open_file_free(OpenFile *of);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(OpenFile*, open_file_free);
|
||||
|
||||
void open_file_free_many(OpenFile **head);
|
||||
|
||||
const char *open_file_flags_to_string(OpenFileFlag t) _const_;
|
||||
OpenFileFlag open_file_flags_from_string(const char *t) _pure_;
|
||||
Reference in New Issue
Block a user