systemd: merge branch systemd into master
This commit is contained in:
@@ -184,10 +184,13 @@ int cg_set_attribute(const char *controller, const char *path, const char *attri
|
||||
int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret);
|
||||
int cg_get_keyed_attribute(const char *controller, const char *path, const char *attribute, char **keys, char **values);
|
||||
|
||||
int cg_get_attribute_as_uint64(const char *controller, const char *path, const char *attribute, uint64_t *ret);
|
||||
|
||||
int cg_set_access(const char *controller, const char *path, uid_t uid, gid_t gid);
|
||||
|
||||
int cg_set_xattr(const char *controller, const char *path, const char *name, const void *value, size_t size, int flags);
|
||||
int cg_get_xattr(const char *controller, const char *path, const char *name, void *value, size_t size);
|
||||
int cg_get_xattr_malloc(const char *controller, const char *path, const char *name, char **ret);
|
||||
int cg_remove_xattr(const char *controller, const char *path, const char *name);
|
||||
|
||||
int cg_install_release_agent(const char *controller, const char *agent);
|
||||
|
@@ -56,6 +56,44 @@ int fdopen_unlocked(int fd, const char *options, FILE **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int take_fdopen_unlocked(int *fd, const char *options, FILE **ret) {
|
||||
int r;
|
||||
|
||||
assert(fd);
|
||||
|
||||
r = fdopen_unlocked(*fd, options, ret);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*fd = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FILE* take_fdopen(int *fd, const char *options) {
|
||||
assert(fd);
|
||||
|
||||
FILE *f = fdopen(*fd, options);
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
*fd = -1;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
DIR* take_fdopendir(int *dfd) {
|
||||
assert(dfd);
|
||||
|
||||
DIR *d = fdopendir(*dfd);
|
||||
if (!d)
|
||||
return NULL;
|
||||
|
||||
*dfd = -1;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
FILE* open_memstream_unlocked(char **ptr, size_t *sizeloc) {
|
||||
FILE *f = open_memstream(ptr, sizeloc);
|
||||
if (!f)
|
||||
|
@@ -39,6 +39,9 @@ typedef enum {
|
||||
|
||||
int fopen_unlocked(const char *path, const char *options, FILE **ret);
|
||||
int fdopen_unlocked(int fd, const char *options, FILE **ret);
|
||||
int take_fdopen_unlocked(int *fd, const char *options, FILE **ret);
|
||||
FILE* take_fdopen(int *fd, const char *options);
|
||||
DIR* take_fdopendir(int *dfd);
|
||||
FILE* open_memstream_unlocked(char **ptr, size_t *sizeloc);
|
||||
FILE* fmemopen_unlocked(void *buf, size_t size, const char *mode);
|
||||
|
||||
|
@@ -59,9 +59,12 @@ void log_show_color(bool b);
|
||||
bool log_get_show_color(void) _pure_;
|
||||
void log_show_location(bool b);
|
||||
bool log_get_show_location(void) _pure_;
|
||||
void log_show_time(bool b);
|
||||
bool log_get_show_time(void) _pure_;
|
||||
|
||||
int log_show_color_from_string(const char *e);
|
||||
int log_show_location_from_string(const char *e);
|
||||
int log_show_time_from_string(const char *e);
|
||||
|
||||
LogTarget log_get_target(void) _pure_;
|
||||
#if 0 /* NM_IGNORED */
|
||||
@@ -77,7 +80,7 @@ int log_get_max_level_realm(LogRealm realm) _pure_;
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
assert_cc(STRLEN(__FILE__) > STRLEN(RELATIVE_SOURCE_PATH) + 1);
|
||||
#define PROJECT_FILE (__FILE__ + STRLEN(RELATIVE_SOURCE_PATH) + 1)
|
||||
#define PROJECT_FILE (&__FILE__[STRLEN(RELATIVE_SOURCE_PATH) + 1])
|
||||
#endif /* NM_IGNORED */
|
||||
#define PROJECT_FILE __FILE__
|
||||
|
||||
|
@@ -1188,6 +1188,11 @@ int must_be_root(void) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Need to be root.");
|
||||
}
|
||||
|
||||
static void restore_sigsetp(sigset_t **ssp) {
|
||||
if (*ssp)
|
||||
(void) sigprocmask(SIG_SETMASK, *ssp, NULL);
|
||||
}
|
||||
|
||||
int safe_fork_full(
|
||||
const char *name,
|
||||
const int except_fds[],
|
||||
@@ -1197,7 +1202,8 @@ int safe_fork_full(
|
||||
|
||||
pid_t original_pid, pid;
|
||||
sigset_t saved_ss, ss;
|
||||
bool block_signals = false;
|
||||
_cleanup_(restore_sigsetp) sigset_t *saved_ssp = NULL;
|
||||
bool block_signals = false, block_all = false;
|
||||
int prio, r;
|
||||
|
||||
/* A wrapper around fork(), that does a couple of important initializations in addition to mere forking. Always
|
||||
@@ -1212,7 +1218,7 @@ int safe_fork_full(
|
||||
* be sure that SIGTERMs are not lost we might send to the child. */
|
||||
|
||||
assert_se(sigfillset(&ss) >= 0);
|
||||
block_signals = true;
|
||||
block_signals = block_all = true;
|
||||
|
||||
} else if (flags & FORK_WAIT) {
|
||||
/* Let's block SIGCHLD at least, so that we can safely watch for the child process */
|
||||
@@ -1222,28 +1228,31 @@ int safe_fork_full(
|
||||
block_signals = true;
|
||||
}
|
||||
|
||||
if (block_signals)
|
||||
if (block_signals) {
|
||||
if (sigprocmask(SIG_SETMASK, &ss, &saved_ss) < 0)
|
||||
return log_full_errno(prio, errno, "Failed to set signal mask: %m");
|
||||
saved_ssp = &saved_ss;
|
||||
}
|
||||
|
||||
if (flags & FORK_NEW_MOUNTNS)
|
||||
pid = raw_clone(SIGCHLD|CLONE_NEWNS);
|
||||
else
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
r = -errno;
|
||||
|
||||
if (block_signals) /* undo what we did above */
|
||||
(void) sigprocmask(SIG_SETMASK, &saved_ss, NULL);
|
||||
|
||||
return log_full_errno(prio, r, "Failed to fork: %m");
|
||||
}
|
||||
if (pid < 0)
|
||||
return log_full_errno(prio, errno, "Failed to fork: %m");
|
||||
if (pid > 0) {
|
||||
/* We are in the parent process */
|
||||
|
||||
log_debug("Successfully forked off '%s' as PID " PID_FMT ".", strna(name), pid);
|
||||
|
||||
if (flags & FORK_WAIT) {
|
||||
if (block_all) {
|
||||
/* undo everything except SIGCHLD */
|
||||
ss = saved_ss;
|
||||
assert_se(sigaddset(&ss, SIGCHLD) >= 0);
|
||||
(void) sigprocmask(SIG_SETMASK, &ss, NULL);
|
||||
}
|
||||
|
||||
r = wait_for_terminate_and_check(name, pid, (flags & FORK_LOG ? WAIT_LOG : 0));
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -1251,9 +1260,6 @@ int safe_fork_full(
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
if (block_signals) /* undo what we did above */
|
||||
(void) sigprocmask(SIG_SETMASK, &saved_ss, NULL);
|
||||
|
||||
if (ret_pid)
|
||||
*ret_pid = pid;
|
||||
|
||||
@@ -1262,6 +1268,9 @@ int safe_fork_full(
|
||||
|
||||
/* We are in the child process */
|
||||
|
||||
/* Restore signal mask manually */
|
||||
saved_ssp = NULL;
|
||||
|
||||
if (flags & FORK_REOPEN_LOG) {
|
||||
/* Close the logs if requested, before we log anything. And make sure we reopen it if needed. */
|
||||
log_close();
|
||||
|
@@ -12,6 +12,7 @@
|
||||
#include "alloc-util.h"
|
||||
#include "dirent-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "macro.h"
|
||||
#include "missing_fs.h"
|
||||
@@ -82,10 +83,9 @@ int dir_is_empty_at(int dir_fd, const char *path) {
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
d = fdopendir(fd);
|
||||
d = take_fdopendir(&fd);
|
||||
if (!d)
|
||||
return -errno;
|
||||
fd = -1;
|
||||
|
||||
FOREACH_DIRENT(de, d, return -errno)
|
||||
return 0;
|
||||
|
@@ -115,7 +115,7 @@ static size_t strcspn_escaped(const char *s, const char *reject) {
|
||||
bool escaped = false;
|
||||
int n;
|
||||
|
||||
for (n=0; s[n]; n++) {
|
||||
for (n = 0; s[n] != '\0'; n++) {
|
||||
if (escaped)
|
||||
escaped = false;
|
||||
else if (s[n] == '\\')
|
||||
@@ -124,50 +124,62 @@ static size_t strcspn_escaped(const char *s, const char *reject) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* if s ends in \, return index of previous char */
|
||||
return n - escaped;
|
||||
return n;
|
||||
}
|
||||
|
||||
/* Split a string into words. */
|
||||
const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags) {
|
||||
const char* split(
|
||||
const char **state,
|
||||
size_t *l,
|
||||
const char *separator,
|
||||
SplitFlags flags) {
|
||||
|
||||
const char *current;
|
||||
|
||||
assert(state);
|
||||
assert(l);
|
||||
|
||||
if (!separator)
|
||||
separator = WHITESPACE;
|
||||
|
||||
current = *state;
|
||||
|
||||
if (!*current) {
|
||||
assert(**state == '\0');
|
||||
if (*current == '\0') /* already at the end? */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
current += strspn(current, separator);
|
||||
if (!*current) {
|
||||
current += strspn(current, separator); /* skip leading separators */
|
||||
if (*current == '\0') { /* at the end now? */
|
||||
*state = current;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (flags & SPLIT_QUOTES && strchr("\'\"", *current)) {
|
||||
char quotechars[2] = {*current, '\0'};
|
||||
if (FLAGS_SET(flags, SPLIT_QUOTES)) {
|
||||
|
||||
*l = strcspn_escaped(current + 1, quotechars);
|
||||
if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] ||
|
||||
(current[*l + 2] && !strchr(separator, current[*l + 2]))) {
|
||||
/* right quote missing or garbage at the end */
|
||||
if (flags & SPLIT_RELAX) {
|
||||
*state = current + *l + 1 + (current[*l + 1] != '\0');
|
||||
return current + 1;
|
||||
if (strchr(QUOTES, *current)) {
|
||||
/* We are looking at a quote */
|
||||
*l = strcspn_escaped(current + 1, CHAR_TO_STR(*current));
|
||||
if (current[*l + 1] != *current ||
|
||||
(current[*l + 2] != 0 && !strchr(separator, current[*l + 2]))) {
|
||||
/* right quote missing or garbage at the end */
|
||||
if (FLAGS_SET(flags, SPLIT_RELAX)) {
|
||||
*state = current + *l + 1 + (current[*l + 1] != '\0');
|
||||
return current + 1;
|
||||
}
|
||||
*state = current;
|
||||
return NULL;
|
||||
}
|
||||
*state = current;
|
||||
return NULL;
|
||||
*state = current++ + *l + 2;
|
||||
|
||||
} else {
|
||||
/* We are looking at a something that is not a quote */
|
||||
*l = strcspn_escaped(current, separator);
|
||||
if (current[*l] && !strchr(separator, current[*l]) && !FLAGS_SET(flags, SPLIT_RELAX)) {
|
||||
/* unfinished escape */
|
||||
*state = current;
|
||||
return NULL;
|
||||
}
|
||||
*state = current + *l;
|
||||
}
|
||||
*state = current++ + *l + 2;
|
||||
} else if (flags & SPLIT_QUOTES) {
|
||||
*l = strcspn_escaped(current, separator);
|
||||
if (current[*l] && !strchr(separator, current[*l]) && !(flags & SPLIT_RELAX)) {
|
||||
/* unfinished escape */
|
||||
*state = current;
|
||||
return NULL;
|
||||
}
|
||||
*state = current + *l;
|
||||
} else {
|
||||
*l = strcspn(current, separator);
|
||||
*state = current + *l;
|
||||
|
@@ -112,8 +112,10 @@ typedef enum SplitFlags {
|
||||
SPLIT_RELAX = 0x01 << 1,
|
||||
} SplitFlags;
|
||||
|
||||
/* Smelly. Do not use this anymore. Use extract_first_word() instead! */
|
||||
const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags);
|
||||
|
||||
/* Similar, don't use this anymore */
|
||||
#define FOREACH_WORD(word, length, s, state) \
|
||||
_FOREACH_WORD(word, length, s, WHITESPACE, 0, state)
|
||||
|
||||
|
@@ -87,6 +87,16 @@ char **strv_parse_nulstr(const char *s, size_t l);
|
||||
char **strv_split_nulstr(const char *s);
|
||||
int strv_make_nulstr(char * const *l, char **p, size_t *n);
|
||||
|
||||
static inline int strv_from_nulstr(char ***a, const char *nulstr) {
|
||||
char **t;
|
||||
|
||||
t = strv_split_nulstr(nulstr);
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
*a = t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool strv_overlap(char * const *a, char * const *b) _pure_;
|
||||
|
||||
#define STRV_FOREACH(s, l) \
|
||||
|
@@ -50,14 +50,12 @@ int fopen_temporary(const char *path, FILE **ret_f, char **ret_temp_path) {
|
||||
/* This assumes that returned FILE object is short-lived and used within the same single-threaded
|
||||
* context and never shared externally, hence locking is not necessary. */
|
||||
|
||||
r = fdopen_unlocked(fd, "w", &f);
|
||||
r = take_fdopen_unlocked(&fd, "w", &f);
|
||||
if (r < 0) {
|
||||
(void) unlink(t);
|
||||
return r;
|
||||
}
|
||||
|
||||
TAKE_FD(fd);
|
||||
|
||||
if (ret_f)
|
||||
*ret_f = TAKE_PTR(f);
|
||||
|
||||
@@ -83,18 +81,16 @@ int mkostemp_safe(char *pattern) {
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
int fmkostemp_safe(char *pattern, const char *mode, FILE **ret_f) {
|
||||
int fd;
|
||||
_cleanup_close_ int fd = -1;
|
||||
FILE *f;
|
||||
|
||||
fd = mkostemp_safe(pattern);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
f = fdopen(fd, mode);
|
||||
if (!f) {
|
||||
safe_close(fd);
|
||||
f = take_fdopen(&fd, mode);
|
||||
if (!f)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
*ret_f = f;
|
||||
return 0;
|
||||
|
59
shared/systemd/src/shared/web-util.c
Normal file
59
shared/systemd/src/shared/web-util.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "nm-sd-adapt-shared.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "utf8.h"
|
||||
#include "web-util.h"
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
bool http_etag_is_valid(const char *etag) {
|
||||
if (isempty(etag))
|
||||
return false;
|
||||
|
||||
if (!endswith(etag, "\""))
|
||||
return false;
|
||||
|
||||
if (!STARTSWITH_SET(etag, "\"", "W/\""))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif /* NM_IGNORED */
|
||||
|
||||
bool http_url_is_valid(const char *url) {
|
||||
const char *p;
|
||||
|
||||
if (isempty(url))
|
||||
return false;
|
||||
|
||||
p = STARTSWITH_SET(url, "http://", "https://");
|
||||
if (!p)
|
||||
return false;
|
||||
|
||||
if (isempty(p))
|
||||
return false;
|
||||
|
||||
return ascii_is_valid(p);
|
||||
}
|
||||
|
||||
#if 0 /* NM_IGNORED */
|
||||
bool documentation_url_is_valid(const char *url) {
|
||||
const char *p;
|
||||
|
||||
if (isempty(url))
|
||||
return false;
|
||||
|
||||
if (http_url_is_valid(url))
|
||||
return true;
|
||||
|
||||
p = STARTSWITH_SET(url, "file:/", "info:", "man:");
|
||||
if (isempty(p))
|
||||
return false;
|
||||
|
||||
return ascii_is_valid(p);
|
||||
}
|
||||
#endif /* NM_IGNORED */
|
12
shared/systemd/src/shared/web-util.h
Normal file
12
shared/systemd/src/shared/web-util.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "macro.h"
|
||||
|
||||
bool http_url_is_valid(const char *url) _pure_;
|
||||
|
||||
bool documentation_url_is_valid(const char *url) _pure_;
|
||||
|
||||
bool http_etag_is_valid(const char *etag);
|
Reference in New Issue
Block a user