summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSven Eden <yamakuzure@gmx.net>2017-05-24 13:51:31 +0200
committerSven Eden <yamakuzure@gmx.net>2017-06-16 10:12:58 +0200
commitc733f9b08d9eadc5e671185112567ada81116bdf (patch)
tree5755965b950423eae4b3c8f462acaf940a9ad684
parentc6edc23d5f8a483e93a891bf7eb76b5f4caf2fb4 (diff)
Prep v230: Apply missing upstream fixes and updates (2/8) src/basic.
-rw-r--r--src/basic/alloc-util.c4
-rw-r--r--src/basic/cgroup-util.c98
-rw-r--r--src/basic/cgroup-util.h42
-rw-r--r--src/basic/copy.c70
-rw-r--r--src/basic/copy.h1
-rw-r--r--src/basic/def.h2
-rw-r--r--src/basic/escape.c28
-rw-r--r--src/basic/escape.h3
-rw-r--r--src/basic/fd-util.c14
-rw-r--r--src/basic/fd-util.h2
-rw-r--r--src/basic/fileio-label.h1
-rw-r--r--src/basic/fileio.c134
-rw-r--r--src/basic/fileio.h11
-rw-r--r--src/basic/fs-util.c36
-rw-r--r--src/basic/fs-util.h11
-rw-r--r--src/basic/hash-funcs.c8
-rw-r--r--src/basic/hash-funcs.h8
-rw-r--r--src/basic/hashmap.c10
-rw-r--r--src/basic/hashmap.h2
-rw-r--r--src/basic/hostname-util.c46
-rw-r--r--src/basic/hostname-util.h2
-rw-r--r--src/basic/log.c23
-rw-r--r--src/basic/log.h9
-rw-r--r--src/basic/login-util.h4
-rw-r--r--src/basic/memfd-util.c2
-rw-r--r--src/basic/memfd-util.h1
-rw-r--r--src/basic/missing.h246
-rw-r--r--src/basic/missing_syscall.h12
-rw-r--r--src/basic/parse-util.c4
-rw-r--r--src/basic/parse-util.h1
-rw-r--r--src/basic/path-util.c84
-rw-r--r--src/basic/path-util.h22
-rw-r--r--src/basic/process-util.c22
-rw-r--r--src/basic/process-util.h8
-rw-r--r--src/basic/rm-rf.c4
-rw-r--r--src/basic/selinux-util.c40
-rw-r--r--src/basic/selinux-util.h2
-rw-r--r--src/basic/siphash24.c54
-rw-r--r--src/basic/socket-util.c110
-rw-r--r--src/basic/socket-util.h6
-rw-r--r--src/basic/stdio-util.h4
-rw-r--r--src/basic/strv.c2
-rw-r--r--src/basic/strv.h3
-rw-r--r--src/basic/terminal-util.c19
-rw-r--r--src/basic/time-util.c148
-rw-r--r--src/basic/time-util.h6
-rw-r--r--src/basic/unit-name.c2
-rw-r--r--src/basic/util.c25
-rw-r--r--src/basic/util.h14
-rw-r--r--src/basic/virt.c96
-rw-r--r--src/basic/virt.h2
51 files changed, 896 insertions, 612 deletions
diff --git a/src/basic/alloc-util.c b/src/basic/alloc-util.c
index a16f97c3d..b540dcddf 100644
--- a/src/basic/alloc-util.c
+++ b/src/basic/alloc-util.c
@@ -17,7 +17,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <stdint.h>
+#include <string.h>
+
#include "alloc-util.h"
+#include "macro.h"
#include "util.h"
void* memdup(const void *p, size_t l) {
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
index 65909f9ef..3636f13da 100644
--- a/src/basic/cgroup-util.c
+++ b/src/basic/cgroup-util.c
@@ -348,7 +348,6 @@ int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char
log_debug_elogind("Migrating \"%s\"/\"%s\" to \"%s\"/\"%s\" (%s)",
cfrom, pfrom, cto, pto,
ignore_self ? "ignoring self" : "watching self");
-
do {
_cleanup_fclose_ FILE *f = NULL;
pid_t pid = 0;
@@ -443,7 +442,7 @@ int cg_migrate_recursive(
p = strjoin(pfrom, "/", fn, NULL);
free(fn);
if (!p)
- return -ENOMEM;
+ return -ENOMEM;
r = cg_migrate_recursive(cfrom, p, cto, pto, ignore_self, rem);
if (r != 0 && ret >= 0)
@@ -527,14 +526,14 @@ static int join_path_legacy(const char *controller, const char *path, const char
t = strjoin("/sys/fs/cgroup/", dn, "/", suffix, NULL);
else if (isempty(suffix))
t = strjoin("/sys/fs/cgroup/", dn, "/", path, NULL);
- else
+ else
t = strjoin("/sys/fs/cgroup/", dn, "/", path, "/", suffix, NULL);
if (!t)
return -ENOMEM;
*fs = t;
return 0;
- }
+}
static int join_path_unified(const char *path, const char *suffix, char **fs) {
char *t;
@@ -1068,8 +1067,8 @@ int cg_is_empty_recursive(const char *controller, const char *path) {
return r;
r = cg_enumerate_subgroups(controller, path, &d);
- if (r == -ENOENT)
- return 1;
+ if (r == -ENOENT)
+ return 1;
if (r < 0)
return r;
@@ -1294,7 +1293,7 @@ int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
}
#if 0 /// UNNEEDED by elogind
-int cg_path_decode_unit(const char *cgroup, char **unit){
+int cg_path_decode_unit(const char *cgroup, char **unit) {
char *c, *s;
size_t n;
@@ -1545,9 +1544,7 @@ int cg_pid_get_machine_name(pid_t pid, char **machine) {
#endif // 0
int cg_path_get_session(const char *path, char **session) {
- /* Elogind uses a flat hierarchy, just "/SESSION". The only
- wrinkle is that SESSION might be escaped. */
-#if 0
+#if 0 /// UNNEEDED by elogind
_cleanup_free_ char *unit = NULL;
char *start, *end;
int r;
@@ -1569,6 +1566,8 @@ int cg_path_get_session(const char *path, char **session) {
if (!session_id_valid(start))
return -ENXIO;
#else
+ /* Elogind uses a flat hierarchy, just "/SESSION". The only
+ wrinkle is that SESSION might be escaped. */
const char *e, *n, *start;
assert(path);
@@ -1963,16 +1962,16 @@ int cg_attach_everywhere(CGroupMask supported, const char *path, pid_t pid, cg_m
for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c);
- const char *p = NULL;
+ const char *p = NULL;
if (!(supported & bit))
continue;
- if (path_callback)
- p = path_callback(bit, userdata);
+ if (path_callback)
+ p = path_callback(bit, userdata);
- if (!p)
- p = path;
+ if (!p)
+ p = path;
(void) cg_attach_fallback(cgroup_controller_to_string(c), p, pid);
}
@@ -2015,16 +2014,16 @@ int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to
for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c);
- const char *p = NULL;
+ const char *p = NULL;
if (!(supported & bit))
continue;
- if (to_callback)
- p = to_callback(bit, userdata);
+ if (to_callback)
+ p = to_callback(bit, userdata);
- if (!p)
- p = to;
+ if (!p)
+ p = to;
(void) cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, cgroup_controller_to_string(c), p, false, false);
}
@@ -2106,12 +2105,12 @@ int cg_mask_supported(CGroupMask *ret) {
continue;
mask |= CGROUP_CONTROLLER_TO_MASK(v);
- }
+ }
- /* Currently, we only support the memory and pids
+ /* Currently, we only support the memory, io and pids
* controller in the unified hierarchy, mask
* everything else off. */
- mask &= CGROUP_MASK_MEMORY | CGROUP_MASK_PIDS;
+ mask &= CGROUP_MASK_MEMORY | CGROUP_MASK_IO | CGROUP_MASK_PIDS;
} else {
CGroupController c;
@@ -2206,21 +2205,21 @@ int cg_unified(void) {
if (statfs("/sys/fs/cgroup/", &fs) < 0)
return -errno;
-/// elogind can not support the unified hierarchy as a controller,
-/// so always assume a classical hierarchy.
-/// If, ond only *if*, someone really wants to substitute systemd-login
-/// in an environment managed by systemd with elogin, we might have to
-/// add such a support.
-#if 0
- if (F_TYPE_EQUAL(fs.f_type, CGROUP_SUPER_MAGIC))
+#if 0 /// UNNEEDED by elogind
+ if (F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC))
unified_cache = true;
else if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC))
#else
+ /* elogind can not support the unified hierarchy as a controller,
+ * so always assume a classical hierarchy.
+ * If, ond only *if*, someone really wants to substitute systemd-login
+ * in an environment managed by systemd with elogin, we might have to
+ * add such a support. */
if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC))
#endif // 0
unified_cache = false;
else
- return -ENOEXEC;
+ return -ENOMEDIUM;
return unified_cache;
}
@@ -2315,6 +2314,42 @@ bool cg_is_legacy_wanted(void) {
#endif // 0
#if 0 /// UNNEEDED by elogind
+int cg_weight_parse(const char *s, uint64_t *ret) {
+ uint64_t u;
+ int r;
+
+ if (isempty(s)) {
+ *ret = CGROUP_WEIGHT_INVALID;
+ return 0;
+ }
+
+ r = safe_atou64(s, &u);
+ if (r < 0)
+ return r;
+
+ if (u < CGROUP_WEIGHT_MIN || u > CGROUP_WEIGHT_MAX)
+ return -ERANGE;
+
+ *ret = u;
+ return 0;
+}
+
+const uint64_t cgroup_io_limit_defaults[_CGROUP_IO_LIMIT_TYPE_MAX] = {
+ [CGROUP_IO_RBPS_MAX] = CGROUP_LIMIT_MAX,
+ [CGROUP_IO_WBPS_MAX] = CGROUP_LIMIT_MAX,
+ [CGROUP_IO_RIOPS_MAX] = CGROUP_LIMIT_MAX,
+ [CGROUP_IO_WIOPS_MAX] = CGROUP_LIMIT_MAX,
+};
+
+static const char* const cgroup_io_limit_type_table[_CGROUP_IO_LIMIT_TYPE_MAX] = {
+ [CGROUP_IO_RBPS_MAX] = "IOReadBandwidthMax",
+ [CGROUP_IO_WBPS_MAX] = "IOWriteBandwidthMax",
+ [CGROUP_IO_RIOPS_MAX] = "IOReadIOPSMax",
+ [CGROUP_IO_WIOPS_MAX] = "IOWriteIOPSMax",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(cgroup_io_limit_type, CGroupIOLimitType);
+
int cg_cpu_shares_parse(const char *s, uint64_t *ret) {
uint64_t u;
int r;
@@ -2359,6 +2394,7 @@ int cg_blkio_weight_parse(const char *s, uint64_t *ret) {
static const char *cgroup_controller_table[_CGROUP_CONTROLLER_MAX] = {
[CGROUP_CONTROLLER_CPU] = "cpu",
[CGROUP_CONTROLLER_CPUACCT] = "cpuacct",
+ [CGROUP_CONTROLLER_IO] = "io",
[CGROUP_CONTROLLER_BLKIO] = "blkio",
[CGROUP_CONTROLLER_MEMORY] = "memory",
[CGROUP_CONTROLLER_DEVICES] = "devices",
diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h
index 996fe595c..2ff438437 100644
--- a/src/basic/cgroup-util.h
+++ b/src/basic/cgroup-util.h
@@ -34,6 +34,7 @@
typedef enum CGroupController {
CGROUP_CONTROLLER_CPU,
CGROUP_CONTROLLER_CPUACCT,
+ CGROUP_CONTROLLER_IO,
CGROUP_CONTROLLER_BLKIO,
CGROUP_CONTROLLER_MEMORY,
CGROUP_CONTROLLER_DEVICES,
@@ -48,6 +49,7 @@ typedef enum CGroupController {
typedef enum CGroupMask {
CGROUP_MASK_CPU = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPU),
CGROUP_MASK_CPUACCT = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPUACCT),
+ CGROUP_MASK_IO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_IO),
CGROUP_MASK_BLKIO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BLKIO),
CGROUP_MASK_MEMORY = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_MEMORY),
CGROUP_MASK_DEVICES = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_DEVICES),
@@ -56,6 +58,37 @@ typedef enum CGroupMask {
} CGroupMask;
#if 0 /// UNNEEDED by elogind
+/* Special values for all weight knobs on unified hierarchy */
+#define CGROUP_WEIGHT_INVALID ((uint64_t) -1)
+#define CGROUP_WEIGHT_MIN UINT64_C(1)
+#define CGROUP_WEIGHT_MAX UINT64_C(10000)
+#define CGROUP_WEIGHT_DEFAULT UINT64_C(100)
+
+#define CGROUP_LIMIT_MIN UINT64_C(0)
+#define CGROUP_LIMIT_MAX ((uint64_t) -1)
+
+static inline bool CGROUP_WEIGHT_IS_OK(uint64_t x) {
+ return
+ x == CGROUP_WEIGHT_INVALID ||
+ (x >= CGROUP_WEIGHT_MIN && x <= CGROUP_WEIGHT_MAX);
+}
+
+/* IO limits on unified hierarchy */
+typedef enum CGroupIOLimitType {
+ CGROUP_IO_RBPS_MAX,
+ CGROUP_IO_WBPS_MAX,
+ CGROUP_IO_RIOPS_MAX,
+ CGROUP_IO_WIOPS_MAX,
+
+ _CGROUP_IO_LIMIT_TYPE_MAX,
+ _CGROUP_IO_LIMIT_TYPE_INVALID = -1
+} CGroupIOLimitType;
+
+extern const uint64_t cgroup_io_limit_defaults[_CGROUP_IO_LIMIT_TYPE_MAX];
+
+const char* cgroup_io_limit_type_to_string(CGroupIOLimitType t) _const_;
+CGroupIOLimitType cgroup_io_limit_type_from_string(const char *s) _pure_;
+
/* Special values for the cpu.shares attribute */
#define CGROUP_CPU_SHARES_INVALID ((uint64_t) -1)
#define CGROUP_CPU_SHARES_MIN UINT64_C(2)
@@ -135,6 +168,7 @@ int cg_get_attribute(const char *controller, const char *path, const char *attri
int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid);
int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid);
#endif // 0
+
int cg_install_release_agent(const char *controller, const char *agent);
int cg_uninstall_release_agent(const char *controller);
@@ -152,6 +186,7 @@ int cg_path_get_machine_name(const char *path, char **machine);
int cg_path_get_slice(const char *path, char **slice);
int cg_path_get_user_slice(const char *path, char **slice);
#endif // 0
+
int cg_shift_path(const char *cgroup, const char *cached_root, const char **shifted);
int cg_pid_get_path_shifted(pid_t pid, const char *cached_root, char **cgroup);
@@ -166,10 +201,12 @@ int cg_pid_get_user_slice(pid_t pid, char **slice);
int cg_path_decode_unit(const char *cgroup, char **unit);
#endif // 0
+
char *cg_escape(const char *p);
char *cg_unescape(const char *p) _pure_;
bool cg_controller_is_valid(const char *p);
+
#if 0 /// UNNEEDED by elogind
int cg_slice_to_path(const char *unit, char **ret);
@@ -182,10 +219,13 @@ int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to
int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root);
int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p);
#endif // 0
+
int cg_mask_supported(CGroupMask *ret);
+
#if 0 /// UNNEEDED by elogind
int cg_kernel_controllers(Set *controllers);
#endif // 0
+
int cg_unified(void);
#if 0 /// UNNEEDED by elogind
void cg_unified_flush(void);
@@ -196,7 +236,9 @@ bool cg_is_legacy_wanted(void);
const char* cgroup_controller_to_string(CGroupController c) _const_;
CGroupController cgroup_controller_from_string(const char *s) _pure_;
+
#if 0 /// UNNEEDED by elogind
+int cg_weight_parse(const char *s, uint64_t *ret);
int cg_cpu_shares_parse(const char *s, uint64_t *ret);
int cg_blkio_weight_parse(const char *s, uint64_t *ret);
#endif // 0
diff --git a/src/basic/copy.c b/src/basic/copy.c
index c2c0579c8..66279cf92 100644
--- a/src/basic/copy.c
+++ b/src/basic/copy.c
@@ -46,14 +46,35 @@
//#include "umask-util.h"
//#include "xattr-util.h"
-#define COPY_BUFFER_SIZE (16*1024)
+#define COPY_BUFFER_SIZE (16*1024u)
+
+static ssize_t try_copy_file_range(int fd_in, loff_t *off_in,
+ int fd_out, loff_t *off_out,
+ size_t len,
+ unsigned int flags) {
+ static int have = -1;
+ ssize_t r;
+
+ if (have == false)
+ return -ENOSYS;
+
+ r = copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
+ if (_unlikely_(have < 0))
+ have = r >= 0 || errno != ENOSYS;
+ if (r >= 0)
+ return r;
+ else
+ return -errno;
+}
int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
- bool try_sendfile = true, try_splice = true;
+ bool try_cfr = true, try_sendfile = true, try_splice = true;
int r;
+ size_t m = SSIZE_MAX; /* that is the maximum that sendfile and c_f_r accept */
assert(fdf >= 0);
assert(fdt >= 0);
+
#if 0 /// UNNEEDED by elogind
/* Try btrfs reflinks first. */
if (try_reflink &&
@@ -66,57 +87,71 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
return 0; /* we copied the whole thing, hence hit EOF, return 0 */
}
#endif // 0
+
for (;;) {
- size_t m = COPY_BUFFER_SIZE;
ssize_t n;
if (max_bytes != (uint64_t) -1) {
-
if (max_bytes <= 0)
return 1; /* return > 0 if we hit the max_bytes limit */
- if ((uint64_t) m > max_bytes)
- m = (size_t) max_bytes;
+ if (m > max_bytes)
+ m = max_bytes;
+ }
+
+ /* First try copy_file_range(), unless we already tried */
+ if (try_cfr) {
+ n = try_copy_file_range(fdf, NULL, fdt, NULL, m, 0u);
+ if (n < 0) {
+ if (!IN_SET(n, -EINVAL, -ENOSYS, -EXDEV, -EBADF))
+ return n;
+
+ try_cfr = false;
+ /* use fallback below */
+ } else if (n == 0) /* EOF */
+ break;
+ else
+ /* Success! */
+ goto next;
}
/* First try sendfile(), unless we already tried */
if (try_sendfile) {
-
n = sendfile(fdt, fdf, NULL, m);
if (n < 0) {
- if (errno != EINVAL && errno != ENOSYS)
+ if (!IN_SET(errno, EINVAL, ENOSYS))
return -errno;
try_sendfile = false;
/* use fallback below */
} else if (n == 0) /* EOF */
break;
- else if (n > 0)
+ else
/* Success! */
goto next;
}
- /* The try splice, unless we already tried */
+ /* Then try splice, unless we already tried */
if (try_splice) {
- n = splice(fdf, NULL, fdt, NULL, m, 0);
+ n = splice(fdf, NULL, fdt, NULL, m, 0);
if (n < 0) {
- if (errno != EINVAL && errno != ENOSYS)
+ if (!IN_SET(errno, EINVAL, ENOSYS))
return -errno;
try_splice = false;
/* use fallback below */
} else if (n == 0) /* EOF */
break;
- else if (n > 0)
+ else
/* Success! */
goto next;
}
/* As a fallback just copy bits by hand */
{
- uint8_t buf[m];
+ uint8_t buf[MIN(m, COPY_BUFFER_SIZE)];
- n = read(fdf, buf, m);
+ n = read(fdf, buf, sizeof buf);
if (n < 0)
return -errno;
if (n == 0) /* EOF */
@@ -132,6 +167,11 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
assert(max_bytes >= (uint64_t) n);
max_bytes -= n;
}
+ /* sendfile accepts at most SSIZE_MAX-offset bytes to copy,
+ * so reduce our maximum by the amount we already copied,
+ * but don't go below our copy buffer size, unless we are
+ * close the the limit of bytes we are allowed to copy. */
+ m = MAX(MIN(COPY_BUFFER_SIZE, max_bytes), m - n);
}
return 0; /* return 0 if we hit EOF earlier than the size limit */
diff --git a/src/basic/copy.h b/src/basic/copy.h
index c389724aa..41aad741c 100644
--- a/src/basic/copy.h
+++ b/src/basic/copy.h
@@ -31,6 +31,7 @@ int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace
int copy_tree(const char *from, const char *to, bool merge);
int copy_tree_at(int fdf, const char *from, int fdt, const char *to, bool merge);
int copy_directory_fd(int dirfd, const char *to, bool merge);
+int copy_directory(const char *from, const char *to, bool merge);
#endif // 0
int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink);
#if 0 /// UNNEEDED by elogind
diff --git a/src/basic/def.h b/src/basic/def.h
index 31753e600..bc7826f7b 100644
--- a/src/basic/def.h
+++ b/src/basic/def.h
@@ -40,8 +40,6 @@
#define SIGNALS_CRASH_HANDLER SIGSEGV,SIGILL,SIGFPE,SIGBUS,SIGQUIT,SIGABRT
#define SIGNALS_IGNORE SIGPIPE
-#define REBOOT_PARAM_FILE "/run/systemd/reboot-param"
-
#ifdef HAVE_SPLIT_USR
#define KBD_KEYMAP_DIRS \
"/usr/share/keymaps/\0" \
diff --git a/src/basic/escape.c b/src/basic/escape.c
index 564149306..127ca2ecb 100644
--- a/src/basic/escape.c
+++ b/src/basic/escape.c
@@ -414,6 +414,34 @@ char *xescape(const char *s, const char *bad) {
}
#if 0 /// UNNEEDED by elogind
+char *octescape(const char *s, size_t len) {
+ char *r, *t;
+ const char *f;
+
+ /* Escapes all chars in bad, in addition to \ and " chars,
+ * in \nnn style escaping. */
+
+ r = new(char, len * 4 + 1);
+ if (!r)
+ return NULL;
+
+ for (f = s, t = r; f < s + len; f++) {
+
+ if (*f < ' ' || *f >= 127 || *f == '\\' || *f == '"') {
+ *(t++) = '\\';
+ *(t++) = '0' + (*f >> 6);
+ *(t++) = '0' + ((*f >> 3) & 8);
+ *(t++) = '0' + (*f & 8);
+ } else
+ *(t++) = *f;
+ }
+
+ *t = 0;
+
+ return r;
+
+}
+
static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
assert(bad);
diff --git a/src/basic/escape.h b/src/basic/escape.h
index f57438038..8383c7586 100644
--- a/src/basic/escape.h
+++ b/src/basic/escape.h
@@ -48,8 +48,9 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit);
char *xescape(const char *s, const char *bad);
-
#if 0 /// UNNEEDED by elogind
+char *octescape(const char *s, size_t len);
+
char *shell_escape(const char *s, const char *bad);
char *shell_maybe_quote(const char *s);
#endif // 0
diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c
index 9c15b91c3..8e4cfe3fe 100644
--- a/src/basic/fd-util.c
+++ b/src/basic/fd-util.c
@@ -359,4 +359,18 @@ bool fdname_is_valid(const char *s) {
return p - s < 256;
}
+
+int fd_get_path(int fd, char **ret) {
+ char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ int r;
+
+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+
+ r = readlink_malloc(procfs_path, ret);
+
+ if (r == -ENOENT) /* If the file doesn't exist the fd is invalid */
+ return -EBADF;
+
+ return r;
+}
#endif // 0
diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h
index e2f5bbdaf..522ea6894 100644
--- a/src/basic/fd-util.h
+++ b/src/basic/fd-util.h
@@ -74,6 +74,8 @@ int same_fd(int a, int b);
void cmsg_close_all(struct msghdr *mh);
bool fdname_is_valid(const char *s);
+
+int fd_get_path(int fd, char **ret);
#endif // 0
/* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */
diff --git a/src/basic/fileio-label.h b/src/basic/fileio-label.h
index 25262efb8..4deeef252 100644
--- a/src/basic/fileio-label.h
+++ b/src/basic/fileio-label.h
@@ -25,7 +25,6 @@
#include "fileio.h"
int write_string_file_atomic_label(const char *fn, const char *line);
-
#if 0 /// UNNEEDED by elogind
int write_env_file_label(const char *fname, char **l);
int fopen_temporary_label(const char *target,
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index da53c3e75..d3fb86174 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -880,13 +880,13 @@ int get_proc_field(const char *filename, const char *pattern, const char *termin
do {
t = strstr(t, pattern);
- if (!t)
- return -ENOENT;
+ if (!t)
+ return -ENOENT;
/* Check that pattern occurs in beginning of line. */
pattern_ok = (t == status || t[-1] == '\n');
- t += strlen(pattern);
+ t += strlen(pattern);
} while (!pattern_ok);
@@ -1087,32 +1087,6 @@ int mkostemp_safe(char *pattern, int flags) {
return fd;
}
-#if 0 /// UNNEEDED by elogind
-int open_tmpfile(const char *path, int flags) {
- char *p;
- int fd;
-
- assert(path);
-
-#ifdef O_TMPFILE
- /* Try O_TMPFILE first, if it is supported */
- fd = open(path, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
- if (fd >= 0)
- return fd;
-#endif
-
- /* Fall back to unguessable name + unlinking */
- p = strjoina(path, "/systemd-tmp-XXXXXX");
-
- fd = mkostemp_safe(p, flags);
- if (fd < 0)
- return fd;
-
- unlink(p);
- return fd;
-}
-#endif // 0
-
int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
const char *fn;
char *t;
@@ -1145,7 +1119,6 @@ int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
return 0;
}
-#if 0 /// UNNEEDED by elogind
int tempfn_random(const char *p, const char *extra, char **ret) {
const char *fn;
char *t, *x;
@@ -1188,6 +1161,7 @@ int tempfn_random(const char *p, const char *extra, char **ret) {
return 0;
}
+#if 0 /// UNNEEDED by elogind
int tempfn_random_child(const char *p, const char *extra, char **ret) {
char *t, *x;
uint64_t u;
@@ -1285,4 +1259,104 @@ int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space)
return fputs(s, f);
}
+
+int open_tmpfile_unlinkable(const char *directory, int flags) {
+ char *p;
+ int fd;
+
+ assert(directory);
+
+ /* Returns an unlinked temporary file that cannot be linked into the file system anymore */
+
+#ifdef O_TMPFILE
+ /* Try O_TMPFILE first, if it is supported */
+ fd = open(directory, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
+ if (fd >= 0)
+ return fd;
+#endif
+
+ /* Fall back to unguessable name + unlinking */
+ p = strjoina(directory, "/systemd-tmp-XXXXXX");
+
+ fd = mkostemp_safe(p, flags);
+ if (fd < 0)
+ return fd;
+
+ (void) unlink(p);
+
+ return fd;
+}
+
+int open_tmpfile_linkable(const char *target, int flags, char **ret_path) {
+ _cleanup_free_ char *tmp = NULL;
+ int r, fd;
+
+ assert(target);
+ assert(ret_path);
+
+ /* Don't allow O_EXCL, as that has a special meaning for O_TMPFILE */
+ assert((flags & O_EXCL) == 0);
+
+ /* Creates a temporary file, that shall be renamed to "target" later. If possible, this uses O_TMPFILE – in
+ * which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in
+ * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
+
+#ifdef O_TMPFILE
+ {
+ _cleanup_free_ char *dn = NULL;
+
+ dn = dirname_malloc(target);
+ if (!dn)
+ return -ENOMEM;
+
+ fd = open(dn, O_TMPFILE|flags, 0640);
+ if (fd >= 0) {
+ *ret_path = NULL;
+ return fd;
+ }
+
+ log_debug_errno(errno, "Failed to use O_TMPFILE on %s: %m", dn);
+ }
+#endif
+
+ r = tempfn_random(target, NULL, &tmp);
+ if (r < 0)
+ return r;
+
+ fd = open(tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|flags, 0640);
+ if (fd < 0)
+ return -errno;
+
+ *ret_path = tmp;
+ tmp = NULL;
+
+ return fd;
+}
+
+int link_tmpfile(int fd, const char *path, const char *target) {
+
+ assert(fd >= 0);
+ assert(target);
+
+ /* Moves a temporary file created with open_tmpfile() above into its final place. if "path" is NULL an fd
+ * created with O_TMPFILE is assumed, and linkat() is used. Otherwise it is assumed O_TMPFILE is not supported
+ * on the directory, and renameat2() is used instead.
+ *
+ * Note that in both cases we will not replace existing files. This is because linkat() does not support this
+ * operation currently (renameat2() does), and there is no nice way to emulate this. */
+
+ if (path) {
+ if (rename_noreplace(AT_FDCWD, path, AT_FDCWD, target) < 0)
+ return -errno;
+ } else {
+ char proc_fd_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
+
+ xsprintf(proc_fd_path, "/proc/self/fd/%i", fd);
+
+ if (linkat(AT_FDCWD, proc_fd_path, AT_FDCWD, target, AT_SYMLINK_FOLLOW) < 0)
+ return -errno;
+ }
+
+ return 0;
+}
#endif // 0
diff --git a/src/basic/fileio.h b/src/basic/fileio.h
index 0635147b7..3c7b9c85b 100644
--- a/src/basic/fileio.h
+++ b/src/basic/fileio.h
@@ -62,6 +62,7 @@ DIR *xopendirat(int dirfd, const char *name, int flags);
int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f);
int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f);
#endif // 0
+
#define FOREACH_LINE(line, f, on_error) \
for (;;) \
if (!fgets(line, sizeof(line), f)) { \
@@ -75,17 +76,19 @@ int fflush_and_check(FILE *f);
int fopen_temporary(const char *path, FILE **_f, char **_temp_path);
int mkostemp_safe(char *pattern, int flags);
-#if 0 /// UNNEEDED by elogind
-int open_tmpfile(const char *path, int flags);
-#endif // 0
int tempfn_xxxxxx(const char *p, const char *extra, char **ret);
-#if 0 /// UNNEEDED by elogind
int tempfn_random(const char *p, const char *extra, char **ret);
+#if 0 /// UNNEEDED by elogind
int tempfn_random_child(const char *p, const char *extra, char **ret);
int write_timestamp_file_atomic(const char *fn, usec_t n);
int read_timestamp_file(const char *fn, usec_t *ret);
int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space);
+
+int open_tmpfile_unlinkable(const char *directory, int flags);
+int open_tmpfile_linkable(const char *target, int flags, char **ret_path);
+
+int link_tmpfile(int fd, const char *path, const char *target);
#endif // 0
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
index b37fef8f5..426ad9761 100644
--- a/src/basic/fs-util.c
+++ b/src/basic/fs-util.c
@@ -287,26 +287,6 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
return 0;
}
-#if 0 /// UNNEEDED by elogind
-int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
- assert(fd >= 0);
-
- /* Under the assumption that we are running privileged we
- * first change the access mode and only then hand out
- * ownership to avoid a window where access is too open. */
-
- if (mode != MODE_INVALID)
- if (fchmod(fd, mode) < 0)
- return -errno;
-
- if (uid != UID_INVALID || gid != GID_INVALID)
- if (fchown(fd, uid, gid) < 0)
- return -errno;
-
- return 0;
-}
-#endif // 0
-
int fchmod_umask(int fd, mode_t m) {
mode_t u;
int r;
@@ -519,3 +499,19 @@ int get_files_in_directory(const char *path, char ***list) {
return n;
}
+
+#if 0 /// UNNEEDED by elogind
+int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
+ char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
+ int r;
+
+ /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
+ xsprintf(path, "/proc/self/fd/%i", what);
+
+ r = inotify_add_watch(fd, path, mask);
+ if (r < 0)
+ return -errno;
+
+ return r;
+}
+#endif // 0
diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h
index 2000b38a9..2c5a65026 100644
--- a/src/basic/fs-util.h
+++ b/src/basic/fs-util.h
@@ -30,11 +30,13 @@
#include "time-util.h"
int unlink_noerrno(const char *path);
+
#if 0 /// UNNEEDED by elogind
int rmdir_parents(const char *path, const char *stop);
int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
#endif // 0
+
int readlinkat_malloc(int fd, const char *p, char **ret);
int readlink_malloc(const char *p, char **r);
#if 0 /// UNNEEDED by elogind
@@ -43,10 +45,9 @@ int readlink_and_make_absolute(const char *p, char **r);
int readlink_and_canonicalize(const char *p, char **r);
int readlink_and_make_absolute_root(const char *root, const char *path, char **ret);
#endif // 0
+
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
-#if 0 /// UNNEEDED by elogind
-int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid);
-#endif // 0
+
int fchmod_umask(int fd, mode_t mode);
int fd_warn_permissions(const char *path, int fd);
@@ -60,6 +61,7 @@ int fd_warn_permissions(const char *path, int fd);
int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode);
int touch(const char *path);
+
#if 0 /// UNNEEDED by elogind
int symlink_idempotent(const char *from, const char *to);
@@ -67,6 +69,7 @@ int symlink_atomic(const char *from, const char *to);
int mknod_atomic(const char *path, mode_t mode, dev_t dev);
int mkfifo_atomic(const char *path, mode_t mode);
#endif // 0
+
int get_files_in_directory(const char *path, char ***list);
#if 0 /// UNNEEDED by elogind
@@ -81,4 +84,6 @@ union inotify_event_buffer {
struct inotify_event ev;
uint8_t raw[INOTIFY_EVENT_MAX];
};
+
+int inotify_add_watch_fd(int fd, int what, uint32_t mask);
#endif // 0
diff --git a/src/basic/hash-funcs.c b/src/basic/hash-funcs.c
index d7b61ceae..c3a4a011b 100644
--- a/src/basic/hash-funcs.c
+++ b/src/basic/hash-funcs.c
@@ -1,21 +1,21 @@
/***
- This file is part of elogind.
+ This file is part of systemd.
Copyright 2010 Lennart Poettering
Copyright 2014 Michal Schmidt
- elogind is free software; you can redistribute it and/or modify it
+ systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
- elogind is distributed in the hope that it will be useful, but
+ systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "hash-funcs.h"
diff --git a/src/basic/hash-funcs.h b/src/basic/hash-funcs.h
index 01be3ca70..299189d14 100644
--- a/src/basic/hash-funcs.h
+++ b/src/basic/hash-funcs.h
@@ -1,23 +1,23 @@
#pragma once
/***
- This file is part of elogind.
+ This file is part of systemd.
Copyright 2010 Lennart Poettering
Copyright 2014 Michal Schmidt
- elogind is free software; you can redistribute it and/or modify it
+ systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
- elogind is distributed in the hope that it will be useful, but
+ systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "macro.h"
diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c
index 75ea2e30b..c89630f04 100644
--- a/src/basic/hashmap.c
+++ b/src/basic/hashmap.c
@@ -1777,20 +1777,18 @@ int set_consume(Set *s, void *value) {
int set_put_strdup(Set *s, const char *p) {
char *c;
- int r;
assert(s);
assert(p);
+ if (set_contains(s, (char*) p))
+ return 0;
+
c = strdup(p);
if (!c)
return -ENOMEM;
- r = set_consume(s, c);
- if (r == -EEXIST)
- return 0;
-
- return r;
+ return set_consume(s, c);
}
#if 0 /// UNNEEDED by elogind
diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h
index a51027204..0fda53e11 100644
--- a/src/basic/hashmap.h
+++ b/src/basic/hashmap.h
@@ -327,10 +327,12 @@ static inline void *hashmap_first(Hashmap *h) {
static inline void *ordered_hashmap_first(OrderedHashmap *h) {
return internal_hashmap_first(HASHMAP_BASE(h));
}
+
#if 0 /// UNNEEDED by elogind
/* no hashmap_next */
void *ordered_hashmap_next(OrderedHashmap *h, const void *key);
#endif // 0
+
char **internal_hashmap_get_strv(HashmapBase *h);
static inline char **hashmap_get_strv(Hashmap *h) {
return internal_hashmap_get_strv(HASHMAP_BASE(h));
diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c
index 3bd3a4d7b..d8d05df3c 100644
--- a/src/basic/hostname-util.c
+++ b/src/basic/hostname-util.c
@@ -17,9 +17,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#if defined(__GLIBC__)
-# include <bits/local_lim.h>
-#endif // defined(__GLIBC__)
#include <errno.h>
#include <limits.h>
#include <stdio.h>
@@ -52,6 +49,10 @@ bool hostname_is_set(void) {
char* gethostname_malloc(void) {
struct utsname u;
+ /* This call tries to return something useful, either the actual hostname
+ * or it makes something up. The only reason it might fail is OOM.
+ * It might even return "localhost" if that's set. */
+
assert_se(uname(&u) >= 0);
if (isempty(u.nodename) || streq(u.nodename, "(none)"))
@@ -59,6 +60,31 @@ char* gethostname_malloc(void) {
return strdup(u.nodename);
}
+
+int gethostname_strict(char **ret) {
+ struct utsname u;
+ char *k;
+
+ /* This call will rather fail than make up a name. It will not return "localhost" either. */
+
+ assert_se(uname(&u) >= 0);
+
+ if (isempty(u.nodename))
+ return -ENXIO;
+
+ if (streq(u.nodename, "(none)"))
+ return -ENXIO;
+
+ if (is_localhost(u.nodename))
+ return -ENXIO;
+
+ k = strdup(u.nodename);
+ if (!k)
+ return -ENOMEM;
+
+ *ret = k;
+ return 0;
+}
#endif // 0
static bool hostname_valid_char(char c) {
@@ -127,6 +153,8 @@ char* hostname_cleanup(char *s) {
assert(s);
+ strshorten(s, HOST_NAME_MAX);
+
for (p = s, d = s, dot = true; *p; p++) {
if (*p == '.') {
if (dot)
@@ -146,8 +174,6 @@ char* hostname_cleanup(char *s) {
else
*d = 0;
- strshorten(s, HOST_NAME_MAX);
-
return s;
}
#endif // 0
@@ -156,16 +182,16 @@ bool is_localhost(const char *hostname) {
assert(hostname);
/* This tries to identify local host and domain names
- * described in RFC6761 plus the redhatism of .localdomain */
+ * described in RFC6761 plus the redhatism of localdomain */
return strcaseeq(hostname, "localhost") ||
strcaseeq(hostname, "localhost.") ||
- strcaseeq(hostname, "localdomain.") ||
- strcaseeq(hostname, "localdomain") ||
+ strcaseeq(hostname, "localhost.localdomain") ||
+ strcaseeq(hostname, "localhost.localdomain.") ||
endswith_no_case(hostname, ".localhost") ||
endswith_no_case(hostname, ".localhost.") ||
- endswith_no_case(hostname, ".localdomain") ||
- endswith_no_case(hostname, ".localdomain.");
+ endswith_no_case(hostname, ".localhost.localdomain") ||
+ endswith_no_case(hostname, ".localhost.localdomain.");
}
#if 0 /// UNNEEDED by elogind
diff --git a/src/basic/hostname-util.h b/src/basic/hostname-util.h
index f22716d0e..1c9efabe1 100644
--- a/src/basic/hostname-util.h
+++ b/src/basic/hostname-util.h
@@ -27,7 +27,9 @@
bool hostname_is_set(void);
char* gethostname_malloc(void);
+int gethostname_strict(char **ret);
#endif // 0
+
bool hostname_is_valid(const char *s, bool allow_trailing_dot) _pure_;
#if 0 /// UNNEEDED by elogind
char* hostname_cleanup(char *s);
diff --git a/src/basic/log.c b/src/basic/log.c
index 08aa986a0..1b8374cfd 100644
--- a/src/basic/log.c
+++ b/src/basic/log.c
@@ -71,7 +71,9 @@ static bool syslog_is_stream = false;
static bool show_color = false;
static bool show_location = false;
-/// UNNEEDED by elogind static bool upgrade_syslog_to_journal = false;
+#if 0 /// UNNEEDED by elogind
+static bool upgrade_syslog_to_journal = false;
+#endif // 0
/* Akin to glibc's __abort_msg; which is private and we hence cannot
* use here. */
@@ -193,11 +195,13 @@ fail:
return r;
}
-#if 0 /// UNNEEDED by elogind
void log_close_journal(void) {
+#if 0 /// elogind does not support journald
journal_fd = safe_close(journal_fd);
+#endif // 0
}
+#if 0 /// UNNEEDED by elogind
static int log_open_journal(void) {
static const union sockaddr_union sa = {
@@ -239,7 +243,7 @@ int log_open(void) {
* because there is no reason to close it. */
if (log_target == LOG_TARGET_NULL) {
- /// UNNEEDED by elogind log_close_journal();
+ log_close_journal();
log_close_syslog();
log_close_console();
return 0;
@@ -261,11 +265,12 @@ int log_open(void) {
}
}
#endif // 0
+
if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
log_target == LOG_TARGET_SYSLOG) {
r = log_open_syslog();
if (r >= 0) {
- /// UNNEEDED by elogind log_close_journal();
+ log_close_journal();
log_close_console();
return r;
}
@@ -273,12 +278,12 @@ int log_open(void) {
if (log_target == LOG_TARGET_AUTO ||
log_target == LOG_TARGET_SAFE ||
- /// UNNEEDED by elogind log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
+ log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
log_target == LOG_TARGET_KMSG) {
r = log_open_kmsg();
if (r >= 0) {
- /// UNNEEDED by elogind log_close_journal();
+ log_close_journal();
log_close_syslog();
log_close_console();
return r;
@@ -286,7 +291,7 @@ int log_open(void) {
}
}
- /// UNNEEDED by elogind log_close_journal();
+ log_close_journal();
log_close_syslog();
return log_open_console();
@@ -309,7 +314,7 @@ void log_set_target(LogTarget target) {
}
void log_close(void) {
- /// UNNEDED by elogind log_close_journal();
+ log_close_journal();
log_close_syslog();
log_close_kmsg();
log_close_console();
@@ -623,7 +628,7 @@ static int log_dispatch(
(log_target == LOG_TARGET_AUTO ||
log_target == LOG_TARGET_SAFE ||
log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
- /// UNNEEDED by elogind log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
+ log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
log_target == LOG_TARGET_KMSG)) {
k = write_to_kmsg(level, error, file, line, func, object_field, object, buffer);
diff --git a/src/basic/log.h b/src/basic/log.h
index 899474daa..0b82b768c 100644
--- a/src/basic/log.h
+++ b/src/basic/log.h
@@ -35,10 +35,8 @@ typedef enum LogTarget{
LOG_TARGET_CONSOLE,
LOG_TARGET_CONSOLE_PREFIXED,
LOG_TARGET_KMSG,
-#if 0 /// elogind does not support logging to systemd-journald
LOG_TARGET_JOURNAL,
LOG_TARGET_JOURNAL_OR_KMSG,
-#endif // 0
LOG_TARGET_SYSLOG,
LOG_TARGET_SYSLOG_OR_KMSG,
LOG_TARGET_AUTO, /* console if stderr is tty, JOURNAL_OR_KMSG otherwise */
@@ -71,10 +69,9 @@ void log_close(void);
#if 0 /// UNNEEDED by elogind
void log_forget_fds(void);
#endif // 0
+
void log_close_syslog(void);
-#if 0 /// UNNEEDED by elogind
void log_close_journal(void);
-#endif // 0
void log_close_kmsg(void);
void log_close_console(void);
@@ -198,13 +195,13 @@ void log_assert_failed_return(
#ifdef LOG_TRACE
# define log_trace(...) log_debug(__VA_ARGS__)
#else
-# define log_trace(...) do {} while(0)
+# define log_trace(...) do {} while (0)
#endif
#ifdef ENABLE_DEBUG_ELOGIND
# define log_debug_elogind(...) log_debug(__VA_ARGS__);usleep(25*USEC_PER_MSEC)
#else
-# define log_debug_elogind(...) do {} while(0)
+# define log_debug_elogind(...) do {} while (0)
#endif // ENABLE_DEBUG_ELOGIND
/* Structured logging */
diff --git a/src/basic/login-util.h b/src/basic/login-util.h
index 89a337d7c..b01ee25c8 100644
--- a/src/basic/login-util.h
+++ b/src/basic/login-util.h
@@ -1,3 +1,5 @@
+#pragma once
+
/***
This file is part of systemd.
@@ -17,8 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include <stdbool.h>
#include <unistd.h>
diff --git a/src/basic/memfd-util.c b/src/basic/memfd-util.c
index 66b5e5c7b..e857c040d 100644
--- a/src/basic/memfd-util.c
+++ b/src/basic/memfd-util.c
@@ -22,7 +22,7 @@
#include <sys/stat.h>
#include <unistd.h>
#ifdef HAVE_LINUX_MEMFD_H
-# include <linux/memfd.h>
+#include <linux/memfd.h>
#endif
#include <stdio.h>
#include <sys/mman.h>
diff --git a/src/basic/memfd-util.h b/src/basic/memfd-util.h
index 419d89979..6b828520e 100644
--- a/src/basic/memfd-util.h
+++ b/src/basic/memfd-util.h
@@ -30,6 +30,7 @@ int memfd_new_and_map(const char *name, size_t sz, void **p);
int memfd_map(int fd, uint64_t offset, size_t size, void **p);
#endif // 0
+
int memfd_set_sealed(int fd);
#if 0 /// UNNEEDED by elogind
int memfd_get_sealed(int fd);
diff --git a/src/basic/missing.h b/src/basic/missing.h
index 7948fc176..984a4c0ed 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -137,84 +137,6 @@
#define SOL_SCTP 132
#endif
-#if !HAVE_DECL_PIVOT_ROOT
-static inline int pivot_root(const char *new_root, const char *put_old) {
- return syscall(SYS_pivot_root, new_root, put_old);
-}
-#endif
-
-#ifndef __NR_memfd_create
-# if defined __x86_64__
-# define __NR_memfd_create 319
-# elif defined __arm__
-# define __NR_memfd_create 385
-# elif defined __aarch64__
-# define __NR_memfd_create 279
-# elif defined __s390__
-# define __NR_memfd_create 350
-# elif defined _MIPS_SIM
-# if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __NR_memfd_create 4354
-# endif
-# if _MIPS_SIM == _MIPS_SIM_NABI32
-# define __NR_memfd_create 6318
-# endif
-# if _MIPS_SIM == _MIPS_SIM_ABI64
-# define __NR_memfd_create 5314
-# endif
-# elif defined __i386__
-# define __NR_memfd_create 356
-# else
-# warning "__NR_memfd_create unknown for your architecture"
-# define __NR_memfd_create 0xffffffff
-# endif
-#endif
-
-#if !HAVE_DECL_MEMFD_CREATE
-static inline int memfd_create(const char *name, unsigned int flags) {
- return syscall(__NR_memfd_create, name, flags);
-}
-#endif
-
-#ifndef __NR_getrandom
-# if defined __x86_64__
-# define __NR_getrandom 318
-# elif defined(__i386__)
-# define __NR_getrandom 355
-# elif defined(__arm__)
-# define __NR_getrandom 384
-# elif defined(__aarch64__)
-# define __NR_getrandom 278
-# elif defined(__ia64__)
-# define __NR_getrandom 1339
-# elif defined(__m68k__)
-# define __NR_getrandom 352
-# elif defined(__s390x__)
-# define __NR_getrandom 349
-# elif defined(__powerpc__)
-# define __NR_getrandom 359
-# elif defined _MIPS_SIM
-# if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __NR_getrandom 4353
-# endif
-# if _MIPS_SIM == _MIPS_SIM_NABI32
-# define __NR_getrandom 6317
-# endif
-# if _MIPS_SIM == _MIPS_SIM_ABI64
-# define __NR_getrandom 5313
-# endif
-# else
-# warning "__NR_getrandom unknown for your architecture"
-# define __NR_getrandom 0xffffffff
-# endif
-#endif
-
-#if !HAVE_DECL_GETRANDOM
-static inline int getrandom(void *buffer, size_t count, unsigned flags) {
- return syscall(__NR_getrandom, buffer, count, flags);
-}
-#endif
-
#ifndef GRND_NONBLOCK
#define GRND_NONBLOCK 0x0001
#endif
@@ -544,12 +466,6 @@ struct btrfs_ioctl_quota_ctl_args {
#define MS_PRIVATE (1 << 18)
#endif
-#if !HAVE_DECL_GETTID
-static inline pid_t gettid(void) {
- return (pid_t) syscall(SYS_gettid);
-}
-#endif
-
#ifndef SCM_SECURITY
#define SCM_SECURITY 0x03
#endif
@@ -578,32 +494,6 @@ static inline pid_t gettid(void) {
#define MAX_HANDLE_SZ 128
#endif
-#ifndef __NR_name_to_handle_at
-# if defined(__x86_64__)
-# define __NR_name_to_handle_at 303
-# elif defined(__i386__)
-# define __NR_name_to_handle_at 341
-# elif defined(__arm__)
-# define __NR_name_to_handle_at 370
-# elif defined(__powerpc__)
-# define __NR_name_to_handle_at 345
-# else
-# error "__NR_name_to_handle_at is not defined"
-# endif
-#endif
-
-#if !HAVE_DECL_NAME_TO_HANDLE_AT
-struct file_handle {
- unsigned int handle_bytes;
- int handle_type;
- unsigned char f_handle[0];
-};
-
-static inline int name_to_handle_at(int fd, const char *name, struct file_handle *handle, int *mnt_id, int flags) {
- return syscall(__NR_name_to_handle_at, fd, name, handle, mnt_id, flags);
-}
-#endif
-
#ifndef HAVE_SECURE_GETENV
# ifdef HAVE___SECURE_GETENV
# define secure_getenv __secure_getenv
@@ -652,22 +542,6 @@ static inline int name_to_handle_at(int fd, const char *name, struct file_handle
#endif
-#ifndef __NR_setns
-# if defined(__x86_64__)
-# define __NR_setns 308
-# elif defined(__i386__)
-# define __NR_setns 346
-# else
-# error "__NR_setns is not defined"
-# endif
-#endif
-
-#if !HAVE_DECL_SETNS
-static inline int setns(int fd, int nstype) {
- return syscall(__NR_setns, fd, nstype);
-}
-#endif
-
#if !HAVE_DECL_LO_FLAGS_PARTSCAN
#define LO_FLAGS_PARTSCAN 8
#endif
@@ -1072,72 +946,11 @@ static inline int setns(int fd, int nstype) {
#define CAP_AUDIT_READ 37
#endif
-static inline int raw_clone(unsigned long flags, void *child_stack) {
-#if defined(__s390__) || defined(__CRIS__)
- /* On s390 and cris the order of the first and second arguments
- * of the raw clone() system call is reversed. */
- return (int) syscall(__NR_clone, child_stack, flags);
-#else
- return (int) syscall(__NR_clone, flags, child_stack);
-#endif
-}
-
-static inline pid_t raw_getpid(void) {
-#if defined(__alpha__)
- return (pid_t) syscall(__NR_getxpid);
-#else
- return (pid_t) syscall(__NR_getpid);
-#endif
-}
-
#if 0 /// UNNEEDED by elogind
-
-#if !HAVE_DECL_RENAMEAT2
-
-
-#ifndef __NR_renameat2
-# if defined __x86_64__
-# define __NR_renameat2 316
-# elif defined __arm__
-# define __NR_renameat2 382
-# elif defined _MIPS_SIM
-# if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __NR_renameat2 4351
-# endif
-# if _MIPS_SIM == _MIPS_SIM_NABI32
-# define __NR_renameat2 6315
-# endif
-# if _MIPS_SIM == _MIPS_SIM_ABI64
-# define __NR_renameat2 5311
-# endif
-# elif defined __i386__
-# define __NR_renameat2 353
-# else
-# warning "__NR_renameat2 unknown for your architecture"
-# define __NR_renameat2 0xffffffff
-# endif
-#endif
-
-static inline int renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) {
- return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags);
-}
-#endif
-
#ifndef RENAME_NOREPLACE
#define RENAME_NOREPLACE (1 << 0)
#endif
-#if !HAVE_DECL_KCMP
-static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) {
-#if defined(__NR_kcmp)
- return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-#endif
-
#ifndef KCMP_FILE
#define KCMP_FILE 0
#endif
@@ -1154,35 +967,6 @@ static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, uns
typedef int32_t key_serial_t;
#endif
-#if !HAVE_DECL_KEYCTL
-static inline long keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4,unsigned long arg5) {
-#if defined(__NR_keyctl)
- return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-static inline key_serial_t add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) {
-#if defined (__NR_add_key)
- return syscall(__NR_add_key, type, description, payload, plen, ringid);
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-static inline key_serial_t request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) {
-#if defined (__NR_request_key)
- return syscall(__NR_request_key, type, description, callout_info, destringid);
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-#endif
-
#ifndef KEYCTL_READ
#define KEYCTL_READ 11
#endif
@@ -1236,32 +1020,4 @@ static inline key_serial_t request_key(const char *type, const char *description
#endif
-#ifndef __NR_copy_file_range
-# if defined(__x86_64__)
-# define __NR_copy_file_range 326
-# elif defined(__i386__)
-# define __NR_copy_file_range 377
-# elif defined __s390__
-# define __NR_copy_file_range 375
-# elif defined __arm__
-# define __NR_copy_file_range 391
-# elif defined __aarch64__
-# define __NR_copy_file_range 285
-# else
-# warning "__NR_copy_file_range not defined for your architecture"
-# endif
-#endif
-
-#if !HAVE_DECL_COPY_FILE_RANGE
-static inline ssize_t copy_file_range(int fd_in, loff_t *off_in,
- int fd_out, loff_t *off_out,
- size_t len,
- unsigned int flags) {
-#ifdef __NR_copy_file_range
- return syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags);
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-#endif
+#include "missing_syscall.h"
diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h
index 42c39ee8d..abfe62a5e 100644
--- a/src/basic/missing_syscall.h
+++ b/src/basic/missing_syscall.h
@@ -1,32 +1,34 @@
#pragma once
/***
- This file is part of elogind.
+ This file is part of systemd.
Copyright 2010 Lennart Poettering
Copyright 2016 Zbigniew Jędrzejewski-Szmek
- elogind is free software; you can redistribute it and/or modify it
+ systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
- elogind is distributed in the hope that it will be useful, but
+ systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
- along with elogind; If not, see <http://www.gnu.org/licenses/>.
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
/* Missing glibc definitions to access certain kernel APIs */
+#if 0 /// UNNEEDED by elogind
#if !HAVE_DECL_PIVOT_ROOT
static inline int pivot_root(const char *new_root, const char *put_old) {
return syscall(SYS_pivot_root, new_root, put_old);
}
#endif
+#endif // 0
/* ======================================================================= */
@@ -178,6 +180,7 @@ static inline int setns(int fd, int nstype) {
/* ======================================================================= */
+#if 0 /// UNNEEDED by elogind
static inline int raw_clone(unsigned long flags, void *child_stack) {
#if defined(__s390__) || defined(__CRIS__)
/* On s390 and cris the order of the first and second arguments
@@ -276,6 +279,7 @@ static inline key_serial_t request_key(const char *type, const char *description
# endif
}
#endif
+#endif // 0
/* ======================================================================= */
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
index 63732634a..d0208e93f 100644
--- a/src/basic/parse-util.c
+++ b/src/basic/parse-util.c
@@ -23,7 +23,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-//#include <xlocale.h>
+#if defined(__GLIBC__)
+# include <xlocale.h>
+#endif // defined(__GLIBC__)
#include "alloc-util.h"
//#include "extract-word.h"
diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h
index ea70c5e1e..250f887f4 100644
--- a/src/basic/parse-util.h
+++ b/src/basic/parse-util.h
@@ -35,7 +35,6 @@ int parse_mode(const char *s, mode_t *ret);
int parse_ifindex(const char *s, int *ret);
int parse_size(const char *t, uint64_t base, uint64_t *size);
-
#if 0 /// UNNEEDED by elogind
int parse_range(const char *t, unsigned *lower, unsigned *upper);
diff --git a/src/basic/path-util.c b/src/basic/path-util.c
index 5f4252f48..123b4ce8c 100644
--- a/src/basic/path-util.c
+++ b/src/basic/path-util.c
@@ -100,9 +100,9 @@ int path_make_absolute_cwd(const char *p, char **ret) {
else {
_cleanup_free_ char *cwd = NULL;
- cwd = get_current_dir_name();
- if (!cwd)
- return -errno;
+ cwd = get_current_dir_name();
+ if (!cwd)
+ return negative_errno();
c = strjoin(cwd, "/", p, NULL);
}
@@ -477,10 +477,10 @@ int find_binary(const char *name, char **ret) {
return 0;
}
- /**
- * Plain getenv, not secure_getenv, because we want
- * to actually allow the user to pick the binary.
- */
+ /**
+ * Plain getenv, not secure_getenv, because we want
+ * to actually allow the user to pick the binary.
+ */
p = getenv("PATH");
if (!p)
p = DEFAULT_PATH;
@@ -497,7 +497,7 @@ int find_binary(const char *name, char **ret) {
break;
if (!path_is_absolute(element))
- continue;
+ continue;
j = strjoin(element, "/", name, NULL);
if (!j)
@@ -762,37 +762,53 @@ char *file_in_same_dir(const char *path, const char *filename) {
return ret;
}
-bool hidden_file_allow_backup(const char *filename) {
- assert(filename);
-
- return
- filename[0] == '.' ||
- streq(filename, "lost+found") ||
- streq(filename, "aquota.user") ||
- streq(filename, "aquota.group") ||
- endswith(filename, ".rpmnew") ||
- endswith(filename, ".rpmsave") ||
- endswith(filename, ".rpmorig") ||
- endswith(filename, ".dpkg-old") ||
- endswith(filename, ".dpkg-new") ||
- endswith(filename, ".dpkg-tmp") ||
- endswith(filename, ".dpkg-dist") ||
- endswith(filename, ".dpkg-bak") ||
- endswith(filename, ".dpkg-backup") ||
- endswith(filename, ".dpkg-remove") ||
- endswith(filename, ".ucf-new") ||
- endswith(filename, ".ucf-old") ||
- endswith(filename, ".ucf-dist") ||
- endswith(filename, ".swp");
-}
+bool hidden_or_backup_file(const char *filename) {
+ const char *p;
-bool hidden_file(const char *filename) {
assert(filename);
- if (endswith(filename, "~"))
+ if (filename[0] == '.' ||
+ streq(filename, "lost+found") ||
+ streq(filename, "aquota.user") ||
+ streq(filename, "aquota.group") ||
+ endswith(filename, "~"))
return true;
- return hidden_file_allow_backup(filename);
+ p = strrchr(filename, '.');
+ if (!p)
+ return false;
+
+ /* Please, let's not add more entries to the list below. If external projects think it's a good idea to come up
+ * with always new suffixes and that everybody else should just adjust to that, then it really should be on
+ * them. Hence, in future, let's not add any more entries. Instead, let's ask those packages to instead adopt
+ * one of the generic suffixes/prefixes for hidden files or backups, possibly augmented with an additional
+ * string. Specifically: there's now:
+ *
+ * The generic suffixes "~" and ".bak" for backup files
+ * The generic prefix "." for hidden files
+ *
+ * Thus, if a new package manager "foopkg" wants its own set of ".foopkg-new", ".foopkg-old", ".foopkg-dist"
+ * or so registered, let's refuse that and ask them to use ".foopkg.new", ".foopkg.old" or ".foopkg~" instead.
+ */
+
+ return STR_IN_SET(p + 1,
+ "rpmnew",
+ "rpmsave",
+ "rpmorig",
+ "dpkg-old",
+ "dpkg-new",
+ "dpkg-tmp",
+ "dpkg-dist",
+ "dpkg-bak",
+ "dpkg-backup",
+ "dpkg-remove",
+ "ucf-new",
+ "ucf-old",
+ "ucf-dist",
+ "swp",
+ "bak",
+ "old",
+ "new");
}
#if 0 /// UNNEEDED by elogind
diff --git a/src/basic/path-util.h b/src/basic/path-util.h
index 99035aae9..540a69c62 100644
--- a/src/basic/path-util.h
+++ b/src/basic/path-util.h
@@ -55,6 +55,25 @@ bool path_equal_or_files_same(const char *a, const char *b);
#if 0 /// UNNEEDED by elogind
char* path_join(const char *root, const char *path, const char *rest);
+static inline bool path_equal_ptr(const char *a, const char *b) {
+ return !!a == !!b && (!a || path_equal(a, b));
+}
+#endif // 0
+
+/* Note: the search terminates on the first NULL item. */
+#define PATH_IN_SET(p, ...) \
+ ({ \
+ char **s; \
+ bool _found = false; \
+ STRV_FOREACH(s, STRV_MAKE(__VA_ARGS__)) \
+ if (path_equal(p, *s)) { \
+ _found = true; \
+ break; \
+ } \
+ _found; \
+ })
+
+#if 0 /// UNNEEDED by elogind
int path_strv_make_absolute_cwd(char **l);
#endif // 0
char** path_strv_resolve(char **l, const char *prefix);
@@ -117,8 +136,7 @@ bool path_is_safe(const char *p) _pure_;
char *file_in_same_dir(const char *path, const char *filename);
-bool hidden_file_allow_backup(const char *filename);
-bool hidden_file(const char *filename) _pure_;
+bool hidden_or_backup_file(const char *filename) _pure_;
#if 0 /// UNNEEDED by elogind
bool is_device_path(const char *path);
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index d146638b8..f418b85b9 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -38,7 +38,7 @@
#endif
#include "alloc-util.h"
-#include "architecture.h"
+//#include "architecture.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
@@ -207,7 +207,7 @@ void rename_process(const char name[8]) {
* "systemd"). If you pass a longer string it will be
* truncated */
- prctl(PR_SET_NAME, name);
+ (void) prctl(PR_SET_NAME, name);
if (program_invocation_name)
strncpy(program_invocation_name, name, strlen(program_invocation_name));
@@ -413,7 +413,7 @@ int get_process_environ(pid_t pid, char **env) {
if (!outcome)
return -ENOMEM;
} else
- outcome[sz] = '\0';
+ outcome[sz] = '\0';
*env = outcome;
outcome = NULL;
@@ -534,17 +534,23 @@ int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_cod
return -EPROTO;
}
-void sigkill_wait(pid_t *pid) {
+#if 0 /// UNNEEDED by elogind
+void sigkill_wait(pid_t pid) {
+ assert(pid > 1);
+
+ if (kill(pid, SIGKILL) > 0)
+ (void) wait_for_terminate(pid, NULL);
+}
+
+void sigkill_waitp(pid_t *pid) {
if (!pid)
return;
if (*pid <= 1)
return;
- if (kill(*pid, SIGKILL) > 0)
- (void) wait_for_terminate(*pid, NULL);
+ sigkill_wait(*pid);
}
-#if 0 /// UNNEEDED by elogind
int kill_and_sigcont(pid_t pid, int sig) {
int r;
@@ -672,6 +678,8 @@ bool is_main_thread(void) {
#if 0 /// UNNEEDED by elogind
noreturn void freeze(void) {
+ log_close();
+
/* Make sure nobody waits for us on a socket anymore */
close_all_fds(NULL, 0);
diff --git a/src/basic/process-util.h b/src/basic/process-util.h
index 66b6cd13a..6cf3a40b1 100644
--- a/src/basic/process-util.h
+++ b/src/basic/process-util.h
@@ -47,7 +47,6 @@ int get_process_state(pid_t pid);
int get_process_comm(pid_t pid, char **name);
int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line);
int get_process_exe(pid_t pid, char **name);
-
#if 0 /// UNNEEDED by elogind
int get_process_uid(pid_t pid, uid_t *uid);
int get_process_gid(pid_t pid, gid_t *gid);
@@ -61,15 +60,14 @@ int get_process_ppid(pid_t pid, pid_t *ppid);
int wait_for_terminate(pid_t pid, siginfo_t *status);
int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code);
-void sigkill_wait(pid_t *pid);
-#define _cleanup_sigkill_wait_ _cleanup_(sigkill_wait)
-
#if 0 /// UNNEEDED by elogind
+void sigkill_wait(pid_t pid);
+void sigkill_waitp(pid_t *pid);
+
int kill_and_sigcont(pid_t pid, int sig);
void rename_process(const char name[8]);
#endif // 0
-
int is_kernel_thread(pid_t pid);
int getenv_for_pid(pid_t pid, const char *field, char **_value);
diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c
index 6912b23f5..474bfbf43 100644
--- a/src/basic/rm-rf.c
+++ b/src/basic/rm-rf.c
@@ -128,7 +128,7 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
continue;
}
-#if 0
+#if 0 /// elogind does not support BTRFS this directly
if ((flags & REMOVE_SUBVOLUME) && st.st_ino == 256) {
/* This could be a subvolume, try to remove it */
@@ -190,7 +190,7 @@ int rm_rf(const char *path, RemoveFlags flags) {
return -EPERM;
}
-#if 0
+#if 0 /// elogind does not support BTRFS this directly
if ((flags & (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) == (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) {
/* Try to remove as subvolume first */
r = btrfs_subvol_remove(path, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA);
diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c
index 700b2e829..835d3fd43 100644
--- a/src/basic/selinux-util.c
+++ b/src/basic/selinux-util.c
@@ -82,31 +82,23 @@ void mac_selinux_retest(void) {
}
#endif // 0
-int mac_selinux_init(const char *prefix) {
+int mac_selinux_init(void) {
int r = 0;
#ifdef HAVE_SELINUX
usec_t before_timestamp, after_timestamp;
struct mallinfo before_mallinfo, after_mallinfo;
- if (!mac_selinux_use())
+ if (label_hnd)
return 0;
- if (label_hnd)
+ if (!mac_selinux_use())
return 0;
before_mallinfo = mallinfo();
before_timestamp = now(CLOCK_MONOTONIC);
- if (prefix) {
- struct selinux_opt options[] = {
- { .type = SELABEL_OPT_SUBSET, .value = prefix },
- };
-
- label_hnd = selabel_open(SELABEL_CTX_FILE, options, ELEMENTSOF(options));
- } else
- label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
-
+ label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
if (!label_hnd) {
log_enforcing("Failed to initialize SELinux context: %m");
r = security_getenforce() == 1 ? -errno : 0;
@@ -164,7 +156,7 @@ int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
return 0;
if (r >= 0) {
- r = lsetfilecon(path, fcon);
+ r = lsetfilecon_raw(path, fcon);
/* If the FS doesn't support labels, then exit without warning */
if (r < 0 && errno == EOPNOTSUPP)
@@ -230,7 +222,7 @@ int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
return -errno;
sclass = string_to_security_class("process");
- r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label);
+ r = security_compute_create_raw(mycon, fcon, sclass, (security_context_t *) label);
if (r < 0)
return -errno;
#endif
@@ -275,7 +267,7 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
if (r < 0)
return -errno;
- r = getpeercon(socket_fd, &peercon);
+ r = getpeercon_raw(socket_fd, &peercon);
if (r < 0)
return -errno;
@@ -309,7 +301,7 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
return -ENOMEM;
sclass = string_to_security_class("process");
- r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label);
+ r = security_compute_create_raw(mycon, fcon, sclass, (security_context_t *) label);
if (r < 0)
return -errno;
#endif
@@ -358,16 +350,16 @@ int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
}
if (r < 0) {
- /* No context specified by the policy? Proceed without setting it. */
+ /* No context specified by the policy? Proceed without setting it. */
if (errno == ENOENT)
- return 0;
+ return 0;
log_enforcing("Failed to determine SELinux security context for %s: %m", path);
} else {
- if (setfscreatecon(filecon) >= 0)
+ if (setfscreatecon_raw(filecon) >= 0)
return 0; /* Success! */
- log_enforcing("Failed to set SELinux security context %s for %s: %m", filecon, path);
+ log_enforcing("Failed to set SELinux security context %s for %s: %m", filecon, path);
}
if (security_getenforce() > 0)
@@ -385,7 +377,7 @@ void mac_selinux_create_file_clear(void) {
if (!mac_selinux_use())
return;
- setfscreatecon(NULL);
+ setfscreatecon_raw(NULL);
#endif
}
@@ -417,7 +409,7 @@ void mac_selinux_create_socket_clear(void) {
if (!mac_selinux_use())
return;
- setsockcreatecon(NULL);
+ setsockcreatecon_raw(NULL);
#endif
}
@@ -476,7 +468,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
return -errno;
} else {
- if (setfscreatecon(fcon) < 0) {
+ if (setfscreatecon_raw(fcon) < 0) {
log_enforcing("Failed to set SELinux security context %s for %s: %m", fcon, path);
if (security_getenforce() > 0)
return -errno;
@@ -487,7 +479,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
r = bind(fd, addr, addrlen) < 0 ? -errno : 0;
if (context_changed)
- setfscreatecon(NULL);
+ setfscreatecon_raw(NULL);
return r;
diff --git a/src/basic/selinux-util.h b/src/basic/selinux-util.h
index e2d21a486..0528b7759 100644
--- a/src/basic/selinux-util.h
+++ b/src/basic/selinux-util.h
@@ -31,7 +31,7 @@ bool mac_selinux_have(void);
void mac_selinux_retest(void);
#endif // 0
-int mac_selinux_init(const char *prefix);
+int mac_selinux_init(void);
#if 0 /// UNNEEDED by elogind
void mac_selinux_finish(void);
#endif // 0
diff --git a/src/basic/siphash24.c b/src/basic/siphash24.c
index 8edaae511..060e8ba38 100644
--- a/src/basic/siphash24.c
+++ b/src/basic/siphash24.c
@@ -56,7 +56,7 @@ void siphash24_init(struct siphash *state, const uint8_t k[16]) {
k1 = unaligned_read_le64(k + 8);
*state = (struct siphash) {
- /* "somepseudorandomlygeneratedbytes" */
+ /* "somepseudorandomlygeneratedbytes" */
.v0 = 0x736f6d6570736575ULL ^ k0,
.v1 = 0x646f72616e646f6dULL ^ k1,
.v2 = 0x6c7967656e657261ULL ^ k0,
@@ -77,16 +77,16 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
assert(state);
/* Update total length */
- state->inlen += inlen;
+ state->inlen += inlen;
/* If padding exists, fill it out */
- if (left > 0) {
- for ( ; in < end && left < 8; in ++, left ++ )
- state->padding |= ( ( uint64_t )*in ) << (left * 8);
+ if (left > 0) {
+ for ( ; in < end && left < 8; in ++, left ++)
+ state->padding |= ((uint64_t) *in) << (left * 8);
- if (in == end && left < 8)
+ if (in == end && left < 8)
/* We did not have enough input to fill out the padding completely */
- return;
+ return;
#ifdef DEBUG
printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
@@ -96,17 +96,17 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
printf("(%3zu) compress padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t)state->padding);
#endif
- state->v3 ^= state->padding;
+ state->v3 ^= state->padding;
sipround(state);
sipround(state);
- state->v0 ^= state->padding;
+ state->v0 ^= state->padding;
- state->padding = 0;
- }
+ state->padding = 0;
+ }
- end -= ( state->inlen % sizeof (uint64_t) );
+ end -= (state->inlen % sizeof(uint64_t));
- for ( ; in < end; in += 8 ) {
+ for ( ; in < end; in += 8) {
m = unaligned_read_le64(in);
#ifdef DEBUG
printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
@@ -115,13 +115,13 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
printf("(%3zu) compress %08x %08x\n", state->inlen, (uint32_t) (m >> 32), (uint32_t) m);
#endif
- state->v3 ^= m;
+ state->v3 ^= m;
sipround(state);
sipround(state);
- state->v0 ^= m;
- }
+ state->v0 ^= m;
+ }
- left = state->inlen & 7;
+ left = state->inlen & 7;
switch (left) {
case 7:
state->padding |= ((uint64_t) in[6]) << 48;
@@ -139,7 +139,7 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
state->padding |= ((uint64_t) in[0]);
case 0:
break;
- }
+ }
}
uint64_t siphash24_finalize(struct siphash *state) {
@@ -147,20 +147,20 @@ uint64_t siphash24_finalize(struct siphash *state) {
assert(state);
- b = state->padding | (( ( uint64_t )state->inlen ) << 56);
+ b = state->padding | (((uint64_t) state->inlen) << 56);
#ifdef DEBUG
- printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t)state->v0);
- printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t)state->v1);
- printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t)state->v2);
- printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t)state->v3);
+ printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
+ printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
+ printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
+ printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
printf("(%3zu) padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t) state->padding);
#endif
- state->v3 ^= b;
+ state->v3 ^= b;
sipround(state);
sipround(state);
- state->v0 ^= b;
+ state->v0 ^= b;
#ifdef DEBUG
printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
@@ -168,7 +168,7 @@ uint64_t siphash24_finalize(struct siphash *state) {
printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
#endif
- state->v2 ^= 0xff;
+ state->v2 ^= 0xff;
sipround(state);
sipround(state);
@@ -179,7 +179,7 @@ uint64_t siphash24_finalize(struct siphash *state) {
}
uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]) {
- struct siphash state;
+ struct siphash state;
assert(in);
assert(k);
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index 73e19310e..5efd09fb8 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -42,6 +42,7 @@
#include "socket-util.h"
#include "string-table.h"
#include "string-util.h"
+#include "strv.h"
#include "user-util.h"
#include "util.h"
@@ -800,6 +801,42 @@ static const char* const ip_tos_table[] = {
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
#endif // 0
+bool ifname_valid(const char *p) {
+ bool numeric = true;
+
+ /* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources
+ * but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We
+ * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */
+
+ if (isempty(p))
+ return false;
+
+ if (strlen(p) >= IFNAMSIZ)
+ return false;
+
+ if (STR_IN_SET(p, ".", ".."))
+ return false;
+
+ while (*p) {
+ if ((unsigned char) *p >= 127U)
+ return false;
+
+ if ((unsigned char) *p <= 32U)
+ return false;
+
+ if (*p == ':' || *p == '/')
+ return false;
+
+ numeric = numeric && (*p >= '0' && *p <= '9');
+ p++;
+ }
+
+ if (numeric)
+ return false;
+
+ return true;
+}
+
int getpeercred(int fd, struct ucred *ucred) {
socklen_t n = sizeof(struct ucred);
struct ucred u;
@@ -943,4 +980,77 @@ int receive_one_fd(int transport_fd, int flags) {
return *(int*) CMSG_DATA(found);
}
+
+ssize_t next_datagram_size_fd(int fd) {
+ ssize_t l;
+ int k;
+
+ /* This is a bit like FIONREAD/SIOCINQ, however a bit more powerful. The difference being: recv(MSG_PEEK) will
+ * actually cause the next datagram in the queue to be validated regarding checksums, which FIONREAD doesn't
+ * do. This difference is actually of major importance as we need to be sure that the size returned here
+ * actually matches what we will read with recvmsg() next, as otherwise we might end up allocating a buffer of
+ * the wrong size. */
+
+ l = recv(fd, NULL, 0, MSG_PEEK|MSG_TRUNC);
+ if (l < 0) {
+ if (errno == EOPNOTSUPP)
+ goto fallback;
+
+ return -errno;
+ }
+ if (l == 0)
+ goto fallback;
+
+ return l;
+
+fallback:
+ k = 0;
+
+ /* Some sockets (AF_PACKET) do not support null-sized recv() with MSG_TRUNC set, let's fall back to FIONREAD
+ * for them. Checksums don't matter for raw sockets anyway, hence this should be fine. */
+
+ if (ioctl(fd, FIONREAD, &k) < 0)
+ return -errno;
+
+ return (ssize_t) k;
+}
+
+int flush_accept(int fd) {
+
+ struct pollfd pollfd = {
+ .fd = fd,
+ .events = POLLIN,
+ };
+ int r;
+
+
+ /* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
+
+ for (;;) {
+ int cfd;
+
+ r = poll(&pollfd, 1, 0);
+ if (r < 0) {
+ if (errno == EINTR)
+ continue;
+
+ return -errno;
+
+ } else if (r == 0)
+ return 0;
+
+ cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
+ if (cfd < 0) {
+ if (errno == EINTR)
+ continue;
+
+ if (errno == EAGAIN)
+ return 0;
+
+ return -errno;
+ }
+
+ close(cfd);
+ }
+}
#endif // 0
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
index 8850d9f16..b5d1dc3ed 100644
--- a/src/basic/socket-util.h
+++ b/src/basic/socket-util.h
@@ -129,6 +129,8 @@ int ip_tos_to_string_alloc(int i, char **s);
int ip_tos_from_string(const char *s);
#endif // 0
+bool ifname_valid(const char *p);
+
int getpeercred(int fd, struct ucred *ucred);
int getpeersec(int fd, char **ret);
@@ -139,6 +141,10 @@ int send_one_fd_sa(int transport_fd,
#define send_one_fd(transport_fd, fd, flags) send_one_fd_sa(transport_fd, fd, NULL, 0, flags)
#if 0 /// UNNEEDED by elogind
int receive_one_fd(int transport_fd, int flags);
+
+ssize_t next_datagram_size_fd(int fd);
+
+int flush_accept(int fd);
#endif // 0
#define CMSG_FOREACH(cmsg, mh) \
diff --git a/src/basic/stdio-util.h b/src/basic/stdio-util.h
index 757c10591..bd1144b4c 100644
--- a/src/basic/stdio-util.h
+++ b/src/basic/stdio-util.h
@@ -19,11 +19,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#if defined(__GLIBC__) && defined(HAVE_PRINTF_H)
#include <printf.h>
-#else
-#include "parse-printf-format.h"
-#endif
#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>
diff --git a/src/basic/strv.c b/src/basic/strv.c
index 7757a4443..93bb130ea 100644
--- a/src/basic/strv.c
+++ b/src/basic/strv.c
@@ -319,7 +319,7 @@ char **strv_split_newlines(const char *s) {
return l;
if (isempty(l[n - 1]))
- l[n-1] = mfree(l[n-1]);
+ l[n - 1] = mfree(l[n - 1]);
return l;
}
diff --git a/src/basic/strv.h b/src/basic/strv.h
index 8e83ffde7..591a452e9 100644
--- a/src/basic/strv.h
+++ b/src/basic/strv.h
@@ -54,6 +54,7 @@ int strv_extend(char ***l, const char *value);
#if 0 /// UNNEEDED by elogind
int strv_extendf(char ***l, const char *format, ...) _printf_(2,0);
#endif // 0
+int strv_extend_front(char ***l, const char *value);
int strv_push(char ***l, char *value);
int strv_push_pair(char ***l, char *a, char *b);
int strv_push_prepend(char ***l, char *value);
@@ -90,6 +91,7 @@ char **strv_split_newlines(const char *s);
int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags);
#endif // 0
+
char *strv_join(char **l, const char *separator);
#if 0 /// UNNEEDED by elogind
char *strv_join_quoted(char **l);
@@ -102,6 +104,7 @@ int strv_make_nulstr(char **l, char **p, size_t *n);
bool strv_overlap(char **a, char **b) _pure_;
#endif // 0
+
#define STRV_FOREACH(s, l) \
for ((s) = (l); (s) && *(s); (s)++)
diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c
index 75a0d6fd8..cb1e6a019 100644
--- a/src/basic/terminal-util.c
+++ b/src/basic/terminal-util.c
@@ -1149,14 +1149,19 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
#endif // 0
bool colors_enabled(void) {
- const char *colors;
+ static int enabled = -1;
- colors = getenv("SYSTEMD_COLORS");
- if (!colors) {
- if (streq_ptr(getenv("TERM"), "dumb"))
- return false;
- return on_tty();
+ if (_unlikely_(enabled < 0)) {
+ const char *colors;
+
+ colors = getenv("SYSTEMD_COLORS");
+ if (colors)
+ enabled = parse_boolean(colors) != 0;
+ else if (streq_ptr(getenv("TERM"), "dumb"))
+ enabled = false;
+ else
+ enabled = on_tty();
}
- return parse_boolean(colors) != 0;
+ return enabled;
}
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
index 2a3957d97..97db1e2cc 100644
--- a/src/basic/time-util.c
+++ b/src/basic/time-util.c
@@ -44,10 +44,30 @@
static nsec_t timespec_load_nsec(const struct timespec *ts);
#endif // 0
+static clockid_t map_clock_id(clockid_t c) {
+
+ /* Some more exotic archs (s390, ppc, …) lack the "ALARM" flavour of the clocks. Thus, clock_gettime() will
+ * fail for them. Since they are essentially the same as their non-ALARM pendants (their only difference is
+ * when timers are set on them), let's just map them accordingly. This way, we can get the correct time even on
+ * those archs. */
+
+ switch (c) {
+
+ case CLOCK_BOOTTIME_ALARM:
+ return CLOCK_BOOTTIME;
+
+ case CLOCK_REALTIME_ALARM:
+ return CLOCK_REALTIME;
+
+ default:
+ return c;
+ }
+}
+
usec_t now(clockid_t clock_id) {
struct timespec ts;
- assert_se(clock_gettime(clock_id, &ts) == 0);
+ assert_se(clock_gettime(map_clock_id(clock_id), &ts) == 0);
return timespec_load(&ts);
}
@@ -56,7 +76,7 @@ usec_t now(clockid_t clock_id) {
nsec_t now_nsec(clockid_t clock_id) {
struct timespec ts;
- assert_se(clock_gettime(clock_id, &ts) == 0);
+ assert_se(clock_gettime(map_clock_id(clock_id), &ts) == 0);
return timespec_load_nsec(&ts);
}
@@ -125,8 +145,7 @@ dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, us
usec_t timespec_load(const struct timespec *ts) {
assert(ts);
- if (ts->tv_sec == (time_t) -1 &&
- ts->tv_nsec == (long) -1)
+ if (ts->tv_sec == (time_t) -1 && ts->tv_nsec == (long) -1)
return USEC_INFINITY;
if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC)
@@ -141,13 +160,13 @@ usec_t timespec_load(const struct timespec *ts) {
static nsec_t timespec_load_nsec(const struct timespec *ts) {
assert(ts);
- if (ts->tv_sec == (time_t) -1 &&
- ts->tv_nsec == (long) -1)
+ if (ts->tv_sec == (time_t) -1 && ts->tv_nsec == (long) -1)
return NSEC_INFINITY;
- return
- (nsec_t) ts->tv_sec * NSEC_PER_SEC +
- (nsec_t) ts->tv_nsec;
+ if ((nsec_t) ts->tv_sec >= (UINT64_MAX - ts->tv_nsec) / NSEC_PER_SEC)
+ return NSEC_INFINITY;
+
+ return (nsec_t) ts->tv_sec * NSEC_PER_SEC + (nsec_t) ts->tv_nsec;
}
#endif // 0
@@ -314,15 +333,15 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
const char *suffix;
usec_t usec;
} table[] = {
- { "y", USEC_PER_YEAR },
- { "month", USEC_PER_MONTH },
- { "w", USEC_PER_WEEK },
- { "d", USEC_PER_DAY },
- { "h", USEC_PER_HOUR },
- { "min", USEC_PER_MINUTE },
- { "s", USEC_PER_SEC },
- { "ms", USEC_PER_MSEC },
- { "us", 1 },
+ { "y", USEC_PER_YEAR },
+ { "month", USEC_PER_MONTH },
+ { "w", USEC_PER_WEEK },
+ { "d", USEC_PER_DAY },
+ { "h", USEC_PER_HOUR },
+ { "min", USEC_PER_MINUTE },
+ { "s", USEC_PER_SEC },
+ { "ms", USEC_PER_MSEC },
+ { "us", 1 },
};
unsigned i;
@@ -452,6 +471,7 @@ int dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
return 0;
}
+#endif // 0
int timestamp_deserialize(const char *value, usec_t *timestamp) {
int r;
@@ -464,6 +484,7 @@ int timestamp_deserialize(const char *value, usec_t *timestamp) {
return r;
}
+#if 0 /// UNNEEDED by elogind
int parse_timestamp(const char *t, usec_t *usec) {
static const struct {
const char *name;
@@ -699,42 +720,56 @@ finish:
}
#endif // 0
-int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
-
+static char* extract_multiplier(char *p, usec_t *multiplier) {
static const struct {
const char *suffix;
usec_t usec;
} table[] = {
- { "seconds", USEC_PER_SEC },
- { "second", USEC_PER_SEC },
- { "sec", USEC_PER_SEC },
- { "s", USEC_PER_SEC },
+ { "seconds", USEC_PER_SEC },
+ { "second", USEC_PER_SEC },
+ { "sec", USEC_PER_SEC },
+ { "s", USEC_PER_SEC },
{ "minutes", USEC_PER_MINUTE },
- { "minute", USEC_PER_MINUTE },
- { "min", USEC_PER_MINUTE },
- { "months", USEC_PER_MONTH },
- { "month", USEC_PER_MONTH },
+ { "minute", USEC_PER_MINUTE },
+ { "min", USEC_PER_MINUTE },
+ { "months", USEC_PER_MONTH },
+ { "month", USEC_PER_MONTH },
{ "M", USEC_PER_MONTH },
- { "msec", USEC_PER_MSEC },
- { "ms", USEC_PER_MSEC },
- { "m", USEC_PER_MINUTE },
- { "hours", USEC_PER_HOUR },
- { "hour", USEC_PER_HOUR },
- { "hr", USEC_PER_HOUR },
- { "h", USEC_PER_HOUR },
- { "days", USEC_PER_DAY },
- { "day", USEC_PER_DAY },
- { "d", USEC_PER_DAY },
- { "weeks", USEC_PER_WEEK },
- { "week", USEC_PER_WEEK },
- { "w", USEC_PER_WEEK },
- { "years", USEC_PER_YEAR },
- { "year", USEC_PER_YEAR },
- { "y", USEC_PER_YEAR },
- { "usec", 1ULL },
- { "us", 1ULL },
+ { "msec", USEC_PER_MSEC },
+ { "ms", USEC_PER_MSEC },
+ { "m", USEC_PER_MINUTE },
+ { "hours", USEC_PER_HOUR },
+ { "hour", USEC_PER_HOUR },
+ { "hr", USEC_PER_HOUR },
+ { "h", USEC_PER_HOUR },
+ { "days", USEC_PER_DAY },
+ { "day", USEC_PER_DAY },
+ { "d", USEC_PER_DAY },
+ { "weeks", USEC_PER_WEEK },
+ { "week", USEC_PER_WEEK },
+ { "w", USEC_PER_WEEK },
+ { "years", USEC_PER_YEAR },
+ { "year", USEC_PER_YEAR },
+ { "y", USEC_PER_YEAR },
+ { "usec", 1ULL },
+ { "us", 1ULL },
};
+ unsigned i;
+
+ for (i = 0; i < ELEMENTSOF(table); i++) {
+ char *e;
+ e = startswith(p, table[i].suffix);
+ if (e) {
+ *multiplier = table[i].usec;
+ return e;
+ }
+ }
+
+ return p;
+}
+
+int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
const char *p, *s;
usec_t r = 0;
bool something = false;
@@ -759,8 +794,8 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
for (;;) {
long long l, z = 0;
char *e;
- unsigned i, n = 0;
- usec_t multiplier, k;
+ unsigned n = 0;
+ usec_t multiplier = default_unit, k;
p += strspn(p, WHITESPACE);
@@ -773,10 +808,8 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
errno = 0;
l = strtoll(p, &e, 10);
-
if (errno > 0)
return -errno;
-
if (l < 0)
return -ERANGE;
@@ -800,18 +833,7 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
return -EINVAL;
e += strspn(e, WHITESPACE);
-
- for (i = 0; i < ELEMENTSOF(table); i++)
- if (startswith(e, table[i].suffix)) {
- multiplier = table[i].usec;
- p = e + strlen(table[i].suffix);
- break;
- }
-
- if (i >= ELEMENTSOF(table)) {
- multiplier = default_unit;
- p = e;
- }
+ p = extract_multiplier(e, &multiplier);
something = true;
@@ -1075,6 +1097,7 @@ bool timezone_is_valid(const char *name) {
return true;
}
+#endif // 0
bool clock_boottime_supported(void) {
static int supported = -1;
@@ -1095,6 +1118,7 @@ bool clock_boottime_supported(void) {
return supported;
}
+#if 0 /// UNNEEDED by elogind
clockid_t clock_boottime_or_monotonic(void) {
if (clock_boottime_supported())
return CLOCK_BOOTTIME;
diff --git a/src/basic/time-util.h b/src/basic/time-util.h
index 3c3fcca57..6feb75cc7 100644
--- a/src/basic/time-util.h
+++ b/src/basic/time-util.h
@@ -108,7 +108,10 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy);
#if 0 /// UNNEEDED by elogind
void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t);
int dual_timestamp_deserialize(const char *value, dual_timestamp *t);
+#endif // 0
+int timestamp_deserialize(const char *value, usec_t *timestamp);
+#if 0 /// UNNEEDED by elogind
int parse_timestamp(const char *t, usec_t *usec);
#endif // 0
@@ -122,6 +125,9 @@ bool ntp_synced(void);
int get_timezones(char ***l);
bool timezone_is_valid(const char *name);
+#endif // 0
+bool clock_boottime_supported(void);
+#if 0 /// UNNEEDED by elogind
clockid_t clock_boottime_or_monotonic(void);
#endif // 0
diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c
index 6e6bd3bdb..463301eeb 100644
--- a/src/basic/unit-name.c
+++ b/src/basic/unit-name.c
@@ -761,7 +761,7 @@ int slice_build_parent_slice(const char *slice, char **ret) {
else {
r = free_and_strdup(&s, "-.slice");
if (r < 0) {
- free(s);
+ free(s);
return r;
}
}
diff --git a/src/basic/util.c b/src/basic/util.c
index 68097b46a..1ef6f5f2b 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -785,16 +785,25 @@ uint64_t physical_memory(void) {
}
#if 0 /// UNNEEDED by elogind
-int update_reboot_param_file(const char *param) {
- int r = 0;
+int update_reboot_parameter_and_warn(const char *param) {
+ int r;
+
+ if (isempty(param)) {
+ if (unlink("/run/systemd/reboot-param") < 0) {
+ if (errno == ENOENT)
+ return 0;
+
+ return log_warning_errno(errno, "Failed to unlink reboot parameter file: %m");
+ }
- if (param) {
- RUN_WITH_UMASK(0022)
- r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE);
+ return 0;
+ }
+
+ RUN_WITH_UMASK(0022) {
+ r = write_string_file("/run/systemd/reboot-param", param, WRITE_STRING_FILE_CREATE);
if (r < 0)
- return log_error_errno(r, "Failed to write reboot param to "REBOOT_PARAM_FILE": %m");
- } else
- (void) unlink(REBOOT_PARAM_FILE);
+ return log_warning_errno(r, "Failed to write reboot parameter file: %m");
+ }
return 0;
}
diff --git a/src/basic/util.h b/src/basic/util.h
index 1fe660b62..af5a4fc9e 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -111,6 +111,16 @@ static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_
qsort(base, nmemb, size, compar);
}
+/**
+ * Normal memcpy requires src to be nonnull. We do nothing if n is 0.
+ */
+static inline void memcpy_safe(void *dst, const void *src, size_t n) {
+ if (n == 0)
+ return;
+ assert(src);
+ memcpy(dst, src, n);
+}
+
#if 0 /// UNNEEDED by elogind
int on_ac_power(void);
#endif // 0
@@ -129,7 +139,6 @@ static inline void _reset_errno_(int *saved_errno) {
#define PROTECT_ERRNO _cleanup_(_reset_errno_) __attribute__((unused)) int _saved_errno_ = errno
-#if 0 /// UNNEEDED by elogind
static inline int negative_errno(void) {
/* This helper should be used to shut up gcc if you know 'errno' is
* negative. Instead of "return -errno;", use "return negative_errno();"
@@ -138,7 +147,6 @@ static inline int negative_errno(void) {
assert_return(errno > 0, -EINVAL);
return -errno;
}
-#endif // 0
static inline unsigned u64log2(uint64_t n) {
#if __SIZEOF_LONG_LONG__ == 8
@@ -189,7 +197,7 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
uint64_t physical_memory(void);
#if 0 /// UNNEEDED by elogind
-int update_reboot_param_file(const char *param);
#endif // 0
+int update_reboot_parameter_and_warn(const char *param);
int version(void);
diff --git a/src/basic/virt.c b/src/basic/virt.c
index 6eb1d0c46..0c0820103 100644
--- a/src/basic/virt.c
+++ b/src/basic/virt.c
@@ -99,6 +99,8 @@ static int detect_vm_cpuid(void) {
: "0" (eax)
);
+ log_debug("Virtualization found, CPUID=%s", sig.text);
+
for (j = 0; j < ELEMENTSOF(cpuid_vendor_table); j ++)
if (streq(sig.text, cpuid_vendor_table[j].cpuid))
return cpuid_vendor_table[j].id;
@@ -106,6 +108,7 @@ static int detect_vm_cpuid(void) {
return VIRTUALIZATION_VM_OTHER;
}
#endif
+ log_debug("No virtualization found in CPUID");
return VIRTUALIZATION_NONE;
}
@@ -122,19 +125,25 @@ static int detect_vm_device_tree(void) {
dir = opendir("/proc/device-tree");
if (!dir) {
- if (errno == ENOENT)
+ if (errno == ENOENT) {
+ log_debug_errno(errno, "/proc/device-tree: %m");
return VIRTUALIZATION_NONE;
+ }
return -errno;
}
FOREACH_DIRENT(dent, dir, return -errno)
- if (strstr(dent->d_name, "fw-cfg"))
+ if (strstr(dent->d_name, "fw-cfg")) {
+ log_debug("Virtualization QEMU: \"fw-cfg\" present in /proc/device-tree/%s", dent->d_name);
return VIRTUALIZATION_QEMU;
+ }
+ log_debug("No virtualization found in /proc/device-tree/*");
return VIRTUALIZATION_NONE;
} else if (r < 0)
return r;
+ log_debug("Virtualization %s found in /proc/device-tree/hypervisor/compatible", hvtype);
if (streq(hvtype, "linux,kvm"))
return VIRTUALIZATION_KVM;
else if (strstr(hvtype, "xen"))
@@ -142,6 +151,7 @@ static int detect_vm_device_tree(void) {
else
return VIRTUALIZATION_VM_OTHER;
#else
+ log_debug("This platform does not support /proc/device-tree");
return VIRTUALIZATION_NONE;
#endif
}
@@ -180,47 +190,77 @@ static int detect_vm_dmi(void) {
r = read_one_line_file(dmi_vendors[i], &s);
if (r < 0) {
if (r == -ENOENT)
- continue;
+ continue;
return r;
- }
+ }
+
+
for (j = 0; j < ELEMENTSOF(dmi_vendor_table); j++)
- if (startswith(s, dmi_vendor_table[j].vendor))
+ if (startswith(s, dmi_vendor_table[j].vendor)) {
+ log_debug("Virtualization %s found in DMI (%s)", s, dmi_vendors[i]);
return dmi_vendor_table[j].id;
+ }
}
#endif
+ log_debug("No virtualization found in DMI");
+
return VIRTUALIZATION_NONE;
}
static int detect_vm_xen(void) {
+ /* Check for Dom0 will be executed later in detect_vm_xen_dom0
+ Thats why we dont check the content of /proc/xen/capabilities here. */
+ if (access("/proc/xen/capabilities", F_OK) < 0) {
+ log_debug("Virtualization XEN not found, /proc/xen/capabilities does not exist");
+ return VIRTUALIZATION_NONE;
+ }
+
+ log_debug("Virtualization XEN found (/proc/xen/capabilities exists)");
+ return VIRTUALIZATION_XEN;
+
+}
+
+static bool detect_vm_xen_dom0(void) {
_cleanup_free_ char *domcap = NULL;
char *cap, *i;
int r;
r = read_one_line_file("/proc/xen/capabilities", &domcap);
- if (r == -ENOENT)
- return VIRTUALIZATION_NONE;
+ if (r == -ENOENT) {
+ log_debug("Virtualization XEN not found, /proc/xen/capabilities does not exist");
+ return false;
+ }
+ if (r < 0)
+ return r;
i = domcap;
- while ((cap = strsep(&i, ",")))
- if (streq(cap, "control_d"))
- break;
+ while ((cap = strsep(&i, ",")))
+ if (streq(cap, "control_d"))
+ break;
+ if (!cap) {
+ log_debug("Virtualization XEN DomU found (/proc/xen/capabilites)");
+ return false;
+ }
- return cap ? VIRTUALIZATION_NONE : VIRTUALIZATION_XEN;
- }
+ log_debug("Virtualization XEN Dom0 ignored (/proc/xen/capabilities)");
+ return true;
+}
static int detect_vm_hypervisor(void) {
- _cleanup_free_ char *hvtype = NULL;
+ _cleanup_free_ char *hvtype = NULL;
int r;
- r = read_one_line_file("/sys/hypervisor/type", &hvtype);
+ r = read_one_line_file("/sys/hypervisor/type", &hvtype);
if (r == -ENOENT)
return VIRTUALIZATION_NONE;
if (r < 0)
return r;
+ log_debug("Virtualization %s found in /sys/hypervisor/type", hvtype);
+
if (streq(hvtype, "xen"))
return VIRTUALIZATION_XEN;
else
@@ -235,9 +275,13 @@ static int detect_vm_uml(void) {
r = read_full_file("/proc/cpuinfo", &cpuinfo_contents, NULL);
if (r < 0)
return r;
- if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n"))
+
+ if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n")) {
+ log_debug("UML virtualization found in /proc/cpuinfo");
return VIRTUALIZATION_UML;
+ }
+ log_debug("No virtualization found in /proc/cpuinfo.");
return VIRTUALIZATION_NONE;
}
@@ -253,14 +297,16 @@ static int detect_vm_zvm(void) {
if (r < 0)
return r;
+ log_debug("Virtualization %s found in /proc/sysinfo", t);
if (streq(t, "z/VM"))
return VIRTUALIZATION_ZVM;
else
return VIRTUALIZATION_KVM;
#else
+ log_debug("This platform does not support /proc/sysinfo");
return VIRTUALIZATION_NONE;
#endif
- }
+}
/* Returns a short identifier for the various VM implementations */
int detect_vm(void) {
@@ -318,14 +364,21 @@ int detect_vm(void) {
if (r < 0)
return r;
if (r != VIRTUALIZATION_NONE)
- goto finish;
+ goto finish;
r = detect_vm_zvm();
if (r < 0)
return r;
finish:
+ /* x86 xen Dom0 is detected as XEN in hypervisor and maybe others.
+ * In order to detect the Dom0 as not virtualization we need to
+ * double-check it */
+ if (r == VIRTUALIZATION_XEN && detect_vm_xen_dom0())
+ r = VIRTUALIZATION_NONE;
+
cached_found = r;
+ log_debug("Found VM virtualization %s", virtualization_to_string(r));
return r;
}
#endif // 0
@@ -414,6 +467,7 @@ int detect_container(void) {
r = VIRTUALIZATION_CONTAINER_OTHER;
finish:
+ log_debug("Found container virtualization %s", virtualization_to_string(r));
cached_found = r;
return r;
}
@@ -423,10 +477,10 @@ int detect_virtualization(void) {
int r;
r = detect_container();
- if (r != 0)
- return r;
+ if (r == 0)
+ r = detect_vm();
- return detect_vm();
+ return r;
}
#endif // 0
@@ -440,7 +494,6 @@ int running_in_chroot(void) {
return ret == 0;
}
-#if 0 /// UNNEEDED by elogind
static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
[VIRTUALIZATION_NONE] = "none",
[VIRTUALIZATION_KVM] = "kvm",
@@ -465,4 +518,3 @@ static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
};
DEFINE_STRING_TABLE_LOOKUP(virtualization, int);
-#endif // 0
diff --git a/src/basic/virt.h b/src/basic/virt.h
index 22dd815f3..1d88ab9ab 100644
--- a/src/basic/virt.h
+++ b/src/basic/virt.h
@@ -72,7 +72,5 @@ int detect_virtualization(void);
int running_in_chroot(void);
-#if 0 /// UNNEEDED by elogind
const char *virtualization_to_string(int v) _const_;
int virtualization_from_string(const char *s) _pure_;
-#endif // 0