mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-11 05:17:44 +03:00
machinectl: show /etc/os-release information of container in status output
This commit is contained in:
parent
98be1a746a
commit
717603e391
@ -2023,7 +2023,7 @@ int exec_context_load_environment(const ExecContext *c, char ***l) {
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
for (n = 0; n < count; n++) {
|
for (n = 0; n < count; n++) {
|
||||||
k = load_env_file(pglob.gl_pathv[n], NULL, &p);
|
k = load_env_file(NULL, pglob.gl_pathv[n], NULL, &p);
|
||||||
if (k < 0) {
|
if (k < 0) {
|
||||||
if (ignore)
|
if (ignore)
|
||||||
continue;
|
continue;
|
||||||
|
@ -319,7 +319,7 @@ static int context_write_data_machine_info(Context *c) {
|
|||||||
|
|
||||||
assert(c);
|
assert(c);
|
||||||
|
|
||||||
r = load_env_file("/etc/machine-info", NULL, &l);
|
r = load_env_file(NULL, "/etc/machine-info", NULL, &l);
|
||||||
if (r < 0 && r != -ENOENT)
|
if (r < 0 && r != -ENOENT)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -288,7 +288,7 @@ static int locale_write_data(Context *c) {
|
|||||||
int r, p;
|
int r, p;
|
||||||
char **l = NULL;
|
char **l = NULL;
|
||||||
|
|
||||||
r = load_env_file("/etc/locale.conf", NULL, &l);
|
r = load_env_file(NULL, "/etc/locale.conf", NULL, &l);
|
||||||
if (r < 0 && r != -ENOENT)
|
if (r < 0 && r != -ENOENT)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -393,7 +393,7 @@ static int vconsole_write_data(Context *c) {
|
|||||||
int r;
|
int r;
|
||||||
_cleanup_strv_free_ char **l = NULL;
|
_cleanup_strv_free_ char **l = NULL;
|
||||||
|
|
||||||
r = load_env_file("/etc/vconsole.conf", NULL, &l);
|
r = load_env_file(NULL, "/etc/vconsole.conf", NULL, &l);
|
||||||
if (r < 0 && r != -ENOENT)
|
if (r < 0 && r != -ENOENT)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -28,9 +28,11 @@
|
|||||||
#include "bus-util.h"
|
#include "bus-util.h"
|
||||||
#include "bus-label.h"
|
#include "bus-label.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "machine.h"
|
|
||||||
#include "rtnl-util.h"
|
#include "rtnl-util.h"
|
||||||
#include "bus-errors.h"
|
#include "bus-errors.h"
|
||||||
|
#include "copy.h"
|
||||||
|
#include "fileio.h"
|
||||||
|
#include "machine.h"
|
||||||
|
|
||||||
static int property_get_id(
|
static int property_get_id(
|
||||||
sd_bus *bus,
|
sd_bus *bus,
|
||||||
@ -333,6 +335,95 @@ int bus_machine_method_get_addresses(sd_bus *bus, sd_bus_message *message, void
|
|||||||
return sd_bus_send(bus, reply, NULL);
|
return sd_bus_send(bus, reply, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bus_machine_method_get_os_release(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||||
|
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
|
||||||
|
_cleanup_close_ int mntns_fd = -1, root_fd = -1;
|
||||||
|
_cleanup_close_pair_ int pair[2] = { -1, -1 };
|
||||||
|
_cleanup_strv_free_ char **l = NULL;
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
Machine *m = userdata;
|
||||||
|
char **k, **v;
|
||||||
|
siginfo_t si;
|
||||||
|
pid_t child;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(bus);
|
||||||
|
assert(message);
|
||||||
|
assert(m);
|
||||||
|
|
||||||
|
r = namespace_open(m->leader, NULL, &mntns_fd, NULL, &root_fd);
|
||||||
|
if (r < 0)
|
||||||
|
return sd_bus_error_set_errno(error, r);
|
||||||
|
|
||||||
|
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
|
||||||
|
return sd_bus_error_set_errno(error, -errno);
|
||||||
|
|
||||||
|
child = fork();
|
||||||
|
if (child < 0)
|
||||||
|
return sd_bus_error_set_errno(error, -errno);
|
||||||
|
|
||||||
|
if (child == 0) {
|
||||||
|
_cleanup_close_ int fd = -1;
|
||||||
|
|
||||||
|
pair[0] = safe_close(pair[0]);
|
||||||
|
|
||||||
|
r = namespace_enter(-1, mntns_fd, -1, root_fd);
|
||||||
|
if (r < 0)
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
|
|
||||||
|
fd = open("/etc/os-release", O_RDONLY|O_CLOEXEC);
|
||||||
|
if (fd < 0) {
|
||||||
|
fd = open("/usr/lib/os-release", O_RDONLY|O_CLOEXEC);
|
||||||
|
if (fd < 0)
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
r = copy_bytes(fd, pair[1], (off_t) -1);
|
||||||
|
if (r < 0)
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
|
|
||||||
|
_exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
pair[1] = safe_close(pair[1]);
|
||||||
|
|
||||||
|
f = fdopen(pair[0], "re");
|
||||||
|
if (!f)
|
||||||
|
return sd_bus_error_set_errno(error, -errno);
|
||||||
|
|
||||||
|
pair[0] = -1;
|
||||||
|
|
||||||
|
r = load_env_file_pairs(f, "/etc/os-release", NULL, &l);
|
||||||
|
if (r < 0)
|
||||||
|
return sd_bus_error_set_errno(error, r);
|
||||||
|
|
||||||
|
r = wait_for_terminate(child, &si);
|
||||||
|
if (r < 0)
|
||||||
|
return sd_bus_error_set_errno(error, r);
|
||||||
|
if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
|
||||||
|
return sd_bus_error_set_errno(error, EIO);
|
||||||
|
|
||||||
|
r = sd_bus_message_new_method_return(message, &reply);
|
||||||
|
if (r < 0)
|
||||||
|
return sd_bus_error_set_errno(error, r);
|
||||||
|
|
||||||
|
r = sd_bus_message_open_container(reply, 'a', "{ss}");
|
||||||
|
if (r < 0)
|
||||||
|
return sd_bus_error_set_errno(error, r);
|
||||||
|
|
||||||
|
STRV_FOREACH_PAIR(k, v, l) {
|
||||||
|
r = sd_bus_message_append(reply, "{ss}", *k, *v);
|
||||||
|
if (r < 0)
|
||||||
|
return sd_bus_error_set_errno(error, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sd_bus_message_close_container(reply);
|
||||||
|
if (r < 0)
|
||||||
|
return sd_bus_error_set_errno(error, r);
|
||||||
|
|
||||||
|
return sd_bus_send(bus, reply, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
const sd_bus_vtable machine_vtable[] = {
|
const sd_bus_vtable machine_vtable[] = {
|
||||||
SD_BUS_VTABLE_START(0),
|
SD_BUS_VTABLE_START(0),
|
||||||
SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Machine, name), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Machine, name), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
@ -348,6 +439,7 @@ const sd_bus_vtable machine_vtable[] = {
|
|||||||
SD_BUS_METHOD("Terminate", NULL, NULL, bus_machine_method_terminate, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
|
SD_BUS_METHOD("Terminate", NULL, NULL, bus_machine_method_terminate, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
|
||||||
SD_BUS_METHOD("Kill", "si", NULL, bus_machine_method_kill, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
|
SD_BUS_METHOD("Kill", "si", NULL, bus_machine_method_kill, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
|
||||||
SD_BUS_METHOD("GetAddresses", NULL, "a(yay)", bus_machine_method_get_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
|
SD_BUS_METHOD("GetAddresses", NULL, "a(yay)", bus_machine_method_get_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
|
SD_BUS_METHOD("GetOSRelease", NULL, "a{ss}", bus_machine_method_get_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
SD_BUS_VTABLE_END
|
SD_BUS_VTABLE_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -100,6 +100,7 @@ int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char
|
|||||||
int bus_machine_method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error);
|
int bus_machine_method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||||
int bus_machine_method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error);
|
int bus_machine_method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||||
int bus_machine_method_get_addresses(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error);
|
int bus_machine_method_get_addresses(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||||
|
int bus_machine_method_get_os_release(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||||
|
|
||||||
int machine_send_signal(Machine *m, bool new_machine);
|
int machine_send_signal(Machine *m, bool new_machine);
|
||||||
int machine_send_create_reply(Machine *m, sd_bus_error *error);
|
int machine_send_create_reply(Machine *m, sd_bus_error *error);
|
||||||
|
@ -224,6 +224,48 @@ static int print_addresses(sd_bus *bus, const char *name, const char *prefix, co
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int print_os_release(sd_bus *bus, const char *name, const char *prefix) {
|
||||||
|
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
|
||||||
|
const char *k, *v, *pretty = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(bus);
|
||||||
|
assert(name);
|
||||||
|
assert(prefix);
|
||||||
|
|
||||||
|
r = sd_bus_call_method(bus,
|
||||||
|
"org.freedesktop.machine1",
|
||||||
|
"/org/freedesktop/machine1",
|
||||||
|
"org.freedesktop.machine1.Manager",
|
||||||
|
"GetMachineOSRelease",
|
||||||
|
NULL,
|
||||||
|
&reply,
|
||||||
|
"s", name);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = sd_bus_message_enter_container(reply, 'a', "{ss}");
|
||||||
|
if (r < 0)
|
||||||
|
return bus_log_parse_error(r);
|
||||||
|
|
||||||
|
while ((r = sd_bus_message_read(reply, "{ss}", &k, &v)) > 0) {
|
||||||
|
if (streq(k, "PRETTY_NAME"))
|
||||||
|
pretty = v;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (r < 0)
|
||||||
|
return bus_log_parse_error(r);
|
||||||
|
|
||||||
|
r = sd_bus_message_exit_container(reply);
|
||||||
|
if (r < 0)
|
||||||
|
return bus_log_parse_error(r);
|
||||||
|
|
||||||
|
if (pretty)
|
||||||
|
printf("%s%s\n", prefix, pretty);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct MachineStatusInfo {
|
typedef struct MachineStatusInfo {
|
||||||
char *name;
|
char *name;
|
||||||
sd_id128_t id;
|
sd_id128_t id;
|
||||||
@ -284,6 +326,8 @@ static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
|
|||||||
"\t Address: ",
|
"\t Address: ",
|
||||||
"\t ");
|
"\t ");
|
||||||
|
|
||||||
|
print_os_release(bus, i->name, "\t OS: ");
|
||||||
|
|
||||||
if (i->unit) {
|
if (i->unit) {
|
||||||
printf("\t Unit: %s\n", i->unit);
|
printf("\t Unit: %s\n", i->unit);
|
||||||
show_unit_cgroup(bus, i->unit, i->leader);
|
show_unit_cgroup(bus, i->unit, i->leader);
|
||||||
|
@ -371,6 +371,27 @@ static int method_get_machine_addresses(sd_bus *bus, sd_bus_message *message, vo
|
|||||||
return bus_machine_method_get_addresses(bus, message, machine, error);
|
return bus_machine_method_get_addresses(bus, message, machine, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int method_get_machine_os_release(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||||
|
Manager *m = userdata;
|
||||||
|
Machine *machine;
|
||||||
|
const char *name;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(bus);
|
||||||
|
assert(message);
|
||||||
|
assert(m);
|
||||||
|
|
||||||
|
r = sd_bus_message_read(message, "s", &name);
|
||||||
|
if (r < 0)
|
||||||
|
return sd_bus_error_set_errno(error, r);
|
||||||
|
|
||||||
|
machine = hashmap_get(m->machines, name);
|
||||||
|
if (!machine)
|
||||||
|
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
|
||||||
|
|
||||||
|
return bus_machine_method_get_os_release(bus, message, machine, error);
|
||||||
|
}
|
||||||
|
|
||||||
const sd_bus_vtable manager_vtable[] = {
|
const sd_bus_vtable manager_vtable[] = {
|
||||||
SD_BUS_VTABLE_START(0),
|
SD_BUS_VTABLE_START(0),
|
||||||
SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED),
|
SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
@ -381,6 +402,7 @@ const sd_bus_vtable manager_vtable[] = {
|
|||||||
SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
|
SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
|
||||||
SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
|
SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
|
||||||
SD_BUS_METHOD("GetMachineAddresses", "s", "a(yay)", method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
|
SD_BUS_METHOD("GetMachineAddresses", "s", "a(yay)", method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
|
SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
SD_BUS_SIGNAL("MachineNew", "so", 0),
|
SD_BUS_SIGNAL("MachineNew", "so", 0),
|
||||||
SD_BUS_SIGNAL("MachineRemoved", "so", 0),
|
SD_BUS_SIGNAL("MachineRemoved", "so", 0),
|
||||||
SD_BUS_VTABLE_END
|
SD_BUS_VTABLE_END
|
||||||
|
@ -56,6 +56,10 @@
|
|||||||
send_interface="org.freedesktop.machine1.Machine"
|
send_interface="org.freedesktop.machine1.Machine"
|
||||||
send_member="GetAddresses"/>
|
send_member="GetAddresses"/>
|
||||||
|
|
||||||
|
<allow send_destination="org.freedesktop.machine1"
|
||||||
|
send_interface="org.freedesktop.machine1.Machine"
|
||||||
|
send_member="GetMachineOSRelease"/>
|
||||||
|
|
||||||
<allow receive_sender="org.freedesktop.machine1"/>
|
<allow receive_sender="org.freedesktop.machine1"/>
|
||||||
</policy>
|
</policy>
|
||||||
|
|
||||||
|
@ -27,8 +27,12 @@
|
|||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
#include "ctype.h"
|
#include "ctype.h"
|
||||||
|
|
||||||
int write_string_to_file(FILE *f, const char *line) {
|
int write_string_stream(FILE *f, const char *line) {
|
||||||
|
assert(f);
|
||||||
|
assert(line);
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
fputs(line, f);
|
fputs(line, f);
|
||||||
if (!endswith(line, "\n"))
|
if (!endswith(line, "\n"))
|
||||||
fputc('\n', f);
|
fputc('\n', f);
|
||||||
@ -51,7 +55,7 @@ int write_string_file(const char *fn, const char *line) {
|
|||||||
if (!f)
|
if (!f)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
return write_string_to_file(f, line);
|
return write_string_stream(f, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
int write_string_file_atomic(const char *fn, const char *line) {
|
int write_string_file_atomic(const char *fn, const char *line) {
|
||||||
@ -189,29 +193,33 @@ ssize_t sendfile_full(int out_fd, const char *fn) {
|
|||||||
return (ssize_t) l;
|
return (ssize_t) l;
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_full_file(const char *fn, char **contents, size_t *size) {
|
int read_full_stream(FILE *f, char **contents, size_t *size) {
|
||||||
_cleanup_fclose_ FILE *f = NULL;
|
|
||||||
size_t n, l;
|
size_t n, l;
|
||||||
_cleanup_free_ char *buf = NULL;
|
_cleanup_free_ char *buf = NULL;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
assert(fn);
|
assert(f);
|
||||||
assert(contents);
|
assert(contents);
|
||||||
|
|
||||||
f = fopen(fn, "re");
|
|
||||||
if (!f)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
if (fstat(fileno(f), &st) < 0)
|
if (fstat(fileno(f), &st) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
|
n = LINE_MAX;
|
||||||
|
|
||||||
|
if (S_ISREG(st.st_mode)) {
|
||||||
|
|
||||||
/* Safety check */
|
/* Safety check */
|
||||||
if (st.st_size > 4*1024*1024)
|
if (st.st_size > 4*1024*1024)
|
||||||
return -E2BIG;
|
return -E2BIG;
|
||||||
|
|
||||||
n = st.st_size > 0 ? st.st_size : LINE_MAX;
|
/* Start with the right file size, but be prepared for
|
||||||
l = 0;
|
* files from /proc which generally report a file size
|
||||||
|
* of 0 */
|
||||||
|
if (st.st_size > 0)
|
||||||
|
n = st.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
l = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char *t;
|
char *t;
|
||||||
size_t k;
|
size_t k;
|
||||||
@ -248,7 +256,21 @@ int read_full_file(const char *fn, char **contents, size_t *size) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int read_full_file(const char *fn, char **contents, size_t *size) {
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
|
||||||
|
assert(fn);
|
||||||
|
assert(contents);
|
||||||
|
|
||||||
|
f = fopen(fn, "re");
|
||||||
|
if (!f)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return read_full_stream(f, contents, size);
|
||||||
|
}
|
||||||
|
|
||||||
static int parse_env_file_internal(
|
static int parse_env_file_internal(
|
||||||
|
FILE *f,
|
||||||
const char *fname,
|
const char *fname,
|
||||||
const char *newline,
|
const char *newline,
|
||||||
int (*push) (const char *filename, unsigned line,
|
int (*push) (const char *filename, unsigned line,
|
||||||
@ -275,9 +297,11 @@ static int parse_env_file_internal(
|
|||||||
COMMENT_ESCAPE
|
COMMENT_ESCAPE
|
||||||
} state = PRE_KEY;
|
} state = PRE_KEY;
|
||||||
|
|
||||||
assert(fname);
|
|
||||||
assert(newline);
|
assert(newline);
|
||||||
|
|
||||||
|
if (f)
|
||||||
|
r = read_full_stream(f, &contents, NULL);
|
||||||
|
else
|
||||||
r = read_full_file(fname, &contents, NULL);
|
r = read_full_file(fname, &contents, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -532,25 +556,27 @@ fail:
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_env_file_push(const char *filename, unsigned line,
|
static int parse_env_file_push(
|
||||||
const char *key, char *value, void *userdata) {
|
const char *filename, unsigned line,
|
||||||
|
const char *key, char *value,
|
||||||
|
void *userdata) {
|
||||||
|
|
||||||
const char *k;
|
const char *k;
|
||||||
va_list aq, *ap = userdata;
|
va_list aq, *ap = userdata;
|
||||||
|
|
||||||
if (!utf8_is_valid(key)) {
|
if (!utf8_is_valid(key)) {
|
||||||
_cleanup_free_ char *p = utf8_escape_invalid(key);
|
_cleanup_free_ char *p;
|
||||||
|
|
||||||
log_error("%s:%u: invalid UTF-8 in key '%s', ignoring.",
|
p = utf8_escape_invalid(key);
|
||||||
filename, line, p);
|
log_error("%s:%u: invalid UTF-8 in key '%s', ignoring.", strna(filename), line, p);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value && !utf8_is_valid(value)) {
|
if (value && !utf8_is_valid(value)) {
|
||||||
_cleanup_free_ char *p = utf8_escape_invalid(value);
|
_cleanup_free_ char *p;
|
||||||
|
|
||||||
log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.",
|
p = utf8_escape_invalid(value);
|
||||||
filename, line, key, p);
|
log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename), line, key, p);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -571,6 +597,7 @@ static int parse_env_file_push(const char *filename, unsigned line,
|
|||||||
|
|
||||||
va_end(aq);
|
va_end(aq);
|
||||||
free(value);
|
free(value);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,14 +612,16 @@ int parse_env_file(
|
|||||||
newline = NEWLINE;
|
newline = NEWLINE;
|
||||||
|
|
||||||
va_start(ap, newline);
|
va_start(ap, newline);
|
||||||
r = parse_env_file_internal(fname, newline, parse_env_file_push, &ap);
|
r = parse_env_file_internal(NULL, fname, newline, parse_env_file_push, &ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int load_env_file_push(const char *filename, unsigned line,
|
static int load_env_file_push(
|
||||||
const char *key, char *value, void *userdata) {
|
const char *filename, unsigned line,
|
||||||
|
const char *key, char *value,
|
||||||
|
void *userdata) {
|
||||||
char ***m = userdata;
|
char ***m = userdata;
|
||||||
char *p;
|
char *p;
|
||||||
int r;
|
int r;
|
||||||
@ -600,16 +629,14 @@ static int load_env_file_push(const char *filename, unsigned line,
|
|||||||
if (!utf8_is_valid(key)) {
|
if (!utf8_is_valid(key)) {
|
||||||
_cleanup_free_ char *t = utf8_escape_invalid(key);
|
_cleanup_free_ char *t = utf8_escape_invalid(key);
|
||||||
|
|
||||||
log_error("%s:%u: invalid UTF-8 for key '%s', ignoring.",
|
log_error("%s:%u: invalid UTF-8 for key '%s', ignoring.", strna(filename), line, t);
|
||||||
filename, line, t);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value && !utf8_is_valid(value)) {
|
if (value && !utf8_is_valid(value)) {
|
||||||
_cleanup_free_ char *t = utf8_escape_invalid(value);
|
_cleanup_free_ char *t = utf8_escape_invalid(value);
|
||||||
|
|
||||||
log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.",
|
log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename), line, key, t);
|
||||||
filename, line, key, t);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,14 +652,69 @@ static int load_env_file_push(const char *filename, unsigned line,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int load_env_file(const char *fname, const char *newline, char ***rl) {
|
int load_env_file(FILE *f, const char *fname, const char *newline, char ***rl) {
|
||||||
char **m = NULL;
|
char **m = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!newline)
|
if (!newline)
|
||||||
newline = NEWLINE;
|
newline = NEWLINE;
|
||||||
|
|
||||||
r = parse_env_file_internal(fname, newline, load_env_file_push, &m);
|
r = parse_env_file_internal(f, fname, newline, load_env_file_push, &m);
|
||||||
|
if (r < 0) {
|
||||||
|
strv_free(m);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
*rl = m;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int load_env_file_push_pairs(
|
||||||
|
const char *filename, unsigned line,
|
||||||
|
const char *key, char *value,
|
||||||
|
void *userdata) {
|
||||||
|
char ***m = userdata;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!utf8_is_valid(key)) {
|
||||||
|
_cleanup_free_ char *t = utf8_escape_invalid(key);
|
||||||
|
|
||||||
|
log_error("%s:%u: invalid UTF-8 for key '%s', ignoring.", strna(filename), line, t);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value && !utf8_is_valid(value)) {
|
||||||
|
_cleanup_free_ char *t = utf8_escape_invalid(value);
|
||||||
|
|
||||||
|
log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename), line, key, t);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = strv_extend(m, key);
|
||||||
|
if (r < 0)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
r = strv_extend(m, "");
|
||||||
|
if (r < 0)
|
||||||
|
return -ENOMEM;
|
||||||
|
} else {
|
||||||
|
r = strv_push(m, value);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int load_env_file_pairs(FILE *f, const char *fname, const char *newline, char ***rl) {
|
||||||
|
char **m = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!newline)
|
||||||
|
newline = NEWLINE;
|
||||||
|
|
||||||
|
r = parse_env_file_internal(f, fname, newline, load_env_file_push_pairs, &m);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
strv_free(m);
|
strv_free(m);
|
||||||
return r;
|
return r;
|
||||||
|
@ -25,16 +25,19 @@
|
|||||||
|
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
|
|
||||||
int write_string_to_file(FILE *f, const char *line);
|
int write_string_stream(FILE *f, const char *line);
|
||||||
int write_string_file(const char *fn, const char *line);
|
int write_string_file(const char *fn, const char *line);
|
||||||
int write_string_file_atomic(const char *fn, const char *line);
|
int write_string_file_atomic(const char *fn, const char *line);
|
||||||
|
|
||||||
int read_one_line_file(const char *fn, char **line);
|
int read_one_line_file(const char *fn, char **line);
|
||||||
int read_full_file(const char *fn, char **contents, size_t *size);
|
int read_full_file(const char *fn, char **contents, size_t *size);
|
||||||
|
int read_full_stream(FILE *f, char **contents, size_t *size);
|
||||||
ssize_t sendfile_full(int out_fd, const char *fn);
|
ssize_t sendfile_full(int out_fd, const char *fn);
|
||||||
|
|
||||||
int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
|
int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
|
||||||
int load_env_file(const char *fname, const char *separator, char ***l);
|
int load_env_file(FILE *f, const char *fname, const char *separator, char ***l);
|
||||||
|
int load_env_file_pairs(FILE *f, const char *fname, const char *separator, char ***l);
|
||||||
|
|
||||||
int write_env_file(const char *fname, char **l);
|
int write_env_file(const char *fname, char **l);
|
||||||
|
|
||||||
int executable_is_script(const char *path, char **interpreter);
|
int executable_is_script(const char *path, char **interpreter);
|
||||||
|
@ -68,7 +68,7 @@ static int write_state(FILE **f, char **states) {
|
|||||||
STRV_FOREACH(state, states) {
|
STRV_FOREACH(state, states) {
|
||||||
int k;
|
int k;
|
||||||
|
|
||||||
k = write_string_to_file(*f, *state);
|
k = write_string_stream(*f, *state);
|
||||||
if (k == 0)
|
if (k == 0)
|
||||||
return 0;
|
return 0;
|
||||||
log_debug("Failed to write '%s' to /sys/power/state: %s",
|
log_debug("Failed to write '%s' to /sys/power/state: %s",
|
||||||
|
@ -72,7 +72,7 @@ static void test_parse_env_file(void) {
|
|||||||
fflush(f);
|
fflush(f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
r = load_env_file(t, NULL, &a);
|
r = load_env_file(NULL, t, NULL, &a);
|
||||||
assert_se(r >= 0);
|
assert_se(r >= 0);
|
||||||
|
|
||||||
STRV_FOREACH(i, a)
|
STRV_FOREACH(i, a)
|
||||||
@ -139,7 +139,7 @@ static void test_parse_env_file(void) {
|
|||||||
r = write_env_file(p, a);
|
r = write_env_file(p, a);
|
||||||
assert_se(r >= 0);
|
assert_se(r >= 0);
|
||||||
|
|
||||||
r = load_env_file(p, NULL, &b);
|
r = load_env_file(NULL, p, NULL, &b);
|
||||||
assert_se(r >= 0);
|
assert_se(r >= 0);
|
||||||
|
|
||||||
unlink(t);
|
unlink(t);
|
||||||
@ -179,7 +179,7 @@ static void test_parse_multiline_env_file(void) {
|
|||||||
fflush(f);
|
fflush(f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
r = load_env_file(t, NULL, &a);
|
r = load_env_file(NULL, t, NULL, &a);
|
||||||
assert_se(r >= 0);
|
assert_se(r >= 0);
|
||||||
|
|
||||||
STRV_FOREACH(i, a)
|
STRV_FOREACH(i, a)
|
||||||
@ -193,7 +193,7 @@ static void test_parse_multiline_env_file(void) {
|
|||||||
r = write_env_file(p, a);
|
r = write_env_file(p, a);
|
||||||
assert_se(r >= 0);
|
assert_se(r >= 0);
|
||||||
|
|
||||||
r = load_env_file(p, NULL, &b);
|
r = load_env_file(NULL, p, NULL, &b);
|
||||||
assert_se(r >= 0);
|
assert_se(r >= 0);
|
||||||
|
|
||||||
unlink(t);
|
unlink(t);
|
||||||
|
@ -234,7 +234,7 @@ static void test_load_env_file_1(void) {
|
|||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1));
|
assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1));
|
||||||
|
|
||||||
r = load_env_file(name, NULL, &data);
|
r = load_env_file(NULL, name, NULL, &data);
|
||||||
assert(r == 0);
|
assert(r == 0);
|
||||||
assert(streq(data[0], "a=a"));
|
assert(streq(data[0], "a=a"));
|
||||||
assert(streq(data[1], "b=bc"));
|
assert(streq(data[1], "b=bc"));
|
||||||
@ -257,7 +257,7 @@ static void test_load_env_file_2(void) {
|
|||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2));
|
assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2));
|
||||||
|
|
||||||
r = load_env_file(name, NULL, &data);
|
r = load_env_file(NULL, name, NULL, &data);
|
||||||
assert(r == 0);
|
assert(r == 0);
|
||||||
assert(streq(data[0], "a=a"));
|
assert(streq(data[0], "a=a"));
|
||||||
assert(data[1] == NULL);
|
assert(data[1] == NULL);
|
||||||
@ -275,7 +275,7 @@ static void test_load_env_file_3(void) {
|
|||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3));
|
assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3));
|
||||||
|
|
||||||
r = load_env_file(name, NULL, &data);
|
r = load_env_file(NULL, name, NULL, &data);
|
||||||
assert(r == 0);
|
assert(r == 0);
|
||||||
assert(data == NULL);
|
assert(data == NULL);
|
||||||
unlink(name);
|
unlink(name);
|
||||||
@ -291,7 +291,7 @@ static void test_load_env_file_4(void) {
|
|||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4));
|
assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4));
|
||||||
|
|
||||||
r = load_env_file(name, NULL, &data);
|
r = load_env_file(NULL, name, NULL, &data);
|
||||||
assert(r == 0);
|
assert(r == 0);
|
||||||
assert(streq(data[0], "HWMON_MODULES=coretemp f71882fg"));
|
assert(streq(data[0], "HWMON_MODULES=coretemp f71882fg"));
|
||||||
assert(streq(data[1], "MODULE_0=coretemp"));
|
assert(streq(data[1], "MODULE_0=coretemp"));
|
||||||
|
@ -15,7 +15,7 @@ After=machine.slice
|
|||||||
[Service]
|
[Service]
|
||||||
ExecStart=@rootlibexecdir@/systemd-machined
|
ExecStart=@rootlibexecdir@/systemd-machined
|
||||||
BusName=org.freedesktop.machine1
|
BusName=org.freedesktop.machine1
|
||||||
CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID
|
CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_CHROOT
|
||||||
WatchdogSec=1min
|
WatchdogSec=1min
|
||||||
PrivateTmp=yes
|
PrivateTmp=yes
|
||||||
PrivateDevices=yes
|
PrivateDevices=yes
|
||||||
|
Loading…
Reference in New Issue
Block a user