2017-11-18 17:09:20 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
2012-07-18 19:07:51 +02:00
|
|
|
#pragma once
|
2009-11-18 00:42:52 +01:00
|
|
|
|
2013-04-17 23:19:38 +02:00
|
|
|
#include <alloca.h>
|
2015-11-30 21:43:37 +01:00
|
|
|
#include <errno.h>
|
2014-04-19 19:22:35 +02:00
|
|
|
#include <fcntl.h>
|
2009-11-18 00:42:52 +01:00
|
|
|
#include <inttypes.h>
|
2015-09-19 00:53:58 +02:00
|
|
|
#include <limits.h>
|
|
|
|
#include <locale.h>
|
2011-05-02 14:13:08 +02:00
|
|
|
#include <stdarg.h>
|
2009-11-18 00:42:52 +01:00
|
|
|
#include <stdbool.h>
|
2015-09-19 00:53:58 +02:00
|
|
|
#include <stddef.h>
|
2015-11-30 21:43:37 +01:00
|
|
|
#include <stdint.h>
|
2010-04-13 02:06:27 +02:00
|
|
|
#include <stdio.h>
|
2015-09-19 00:53:58 +02:00
|
|
|
#include <stdlib.h>
|
2015-11-30 21:43:37 +01:00
|
|
|
#include <string.h>
|
2015-09-19 00:53:58 +02:00
|
|
|
#include <sys/inotify.h>
|
2015-02-24 00:42:13 +01:00
|
|
|
#include <sys/socket.h>
|
2010-10-08 02:31:36 +02:00
|
|
|
#include <sys/stat.h>
|
2015-04-04 11:52:57 +02:00
|
|
|
#include <sys/statfs.h>
|
2016-03-14 22:44:49 +01:00
|
|
|
#include <sys/sysmacros.h>
|
2015-09-19 00:53:58 +02:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <unistd.h>
|
2009-11-18 00:42:52 +01:00
|
|
|
|
2016-11-07 16:14:59 +01:00
|
|
|
#include "format-util.h"
|
2010-06-23 19:46:29 +02:00
|
|
|
#include "macro.h"
|
2014-08-01 16:53:07 +02:00
|
|
|
#include "missing.h"
|
2012-11-23 22:07:24 +01:00
|
|
|
#include "time-util.h"
|
2010-05-24 01:45:54 +02:00
|
|
|
|
2014-11-25 19:24:45 +01:00
|
|
|
size_t page_size(void) _pure_;
|
2011-03-18 03:03:41 +01:00
|
|
|
#define PAGE_ALIGN(l) ALIGN_TO((l), page_size())
|
|
|
|
|
2009-11-18 00:42:52 +01:00
|
|
|
static inline const char* yes_no(bool b) {
|
|
|
|
return b ? "yes" : "no";
|
|
|
|
}
|
|
|
|
|
2013-12-17 10:55:28 +01:00
|
|
|
static inline const char* true_false(bool b) {
|
|
|
|
return b ? "true" : "false";
|
|
|
|
}
|
|
|
|
|
2015-01-13 20:07:13 +01:00
|
|
|
static inline const char* one_zero(bool b) {
|
|
|
|
return b ? "1" : "0";
|
|
|
|
}
|
|
|
|
|
2016-07-24 20:12:58 +02:00
|
|
|
static inline const char* enable_disable(bool b) {
|
|
|
|
return b ? "enable" : "disable";
|
|
|
|
}
|
|
|
|
|
2015-03-16 18:29:26 +01:00
|
|
|
bool plymouth_running(void);
|
|
|
|
|
2013-05-03 04:51:50 +02:00
|
|
|
bool display_is_local(const char *display) _pure_;
|
2011-06-27 22:44:12 +02:00
|
|
|
|
2010-11-08 05:02:45 +01:00
|
|
|
#define NULSTR_FOREACH(i, l) \
|
2010-08-20 02:26:05 +02:00
|
|
|
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
|
|
|
|
|
2010-10-27 05:47:48 +02:00
|
|
|
#define NULSTR_FOREACH_PAIR(i, j, l) \
|
|
|
|
for ((i) = (l), (j) = strchr((i), 0)+1; (i) && *(i); (i) = strchr((j), 0)+1, (j) = *(i) ? strchr((i), 0)+1 : (i))
|
|
|
|
|
2011-06-30 04:16:10 +02:00
|
|
|
extern int saved_argc;
|
|
|
|
extern char **saved_argv;
|
|
|
|
|
2011-08-22 14:58:50 +02:00
|
|
|
bool kexec_loaded(void);
|
|
|
|
|
2013-05-03 04:51:50 +02:00
|
|
|
int prot_from_flags(int flags) _const_;
|
2011-10-07 21:06:39 +02:00
|
|
|
|
2012-05-16 14:22:40 +02:00
|
|
|
bool in_initrd(void);
|
2016-06-13 16:28:42 +02:00
|
|
|
void in_initrd_force(bool value);
|
2012-05-30 15:01:51 +02:00
|
|
|
|
2012-10-22 14:31:46 +02:00
|
|
|
void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
|
2018-09-18 04:05:20 +02:00
|
|
|
__compar_d_fn_t compar, void *arg);
|
|
|
|
|
|
|
|
#define typesafe_bsearch_r(k, b, n, func, userdata) \
|
|
|
|
({ \
|
|
|
|
const typeof(b[0]) *_k = k; \
|
|
|
|
int (*_func_)(const typeof(b[0])*, const typeof(b[0])*, typeof(userdata)) = func; \
|
|
|
|
xbsearch_r((const void*) _k, (b), (n), sizeof((b)[0]), (__compar_d_fn_t) _func_, userdata); \
|
|
|
|
})
|
2012-11-02 17:27:15 +01:00
|
|
|
|
2018-03-25 22:43:43 +02:00
|
|
|
/**
|
|
|
|
* Normal bsearch requires base to be nonnull. Here were require
|
|
|
|
* that only if nmemb > 0.
|
|
|
|
*/
|
|
|
|
static inline void* bsearch_safe(const void *key, const void *base,
|
2018-09-18 04:05:20 +02:00
|
|
|
size_t nmemb, size_t size, __compar_fn_t compar) {
|
2018-03-25 22:43:43 +02:00
|
|
|
if (nmemb <= 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
assert(base);
|
|
|
|
return bsearch(key, base, nmemb, size, compar);
|
|
|
|
}
|
|
|
|
|
2018-09-18 04:05:20 +02:00
|
|
|
#define typesafe_bsearch(k, b, n, func) \
|
|
|
|
({ \
|
|
|
|
const typeof(b[0]) *_k = k; \
|
|
|
|
int (*_func_)(const typeof(b[0])*, const typeof(b[0])*) = func; \
|
|
|
|
bsearch_safe((const void*) _k, (b), (n), sizeof((b)[0]), (__compar_fn_t) _func_); \
|
|
|
|
})
|
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
/**
|
|
|
|
* Normal qsort requires base to be nonnull. Here were require
|
|
|
|
* that only if nmemb > 0.
|
|
|
|
*/
|
2018-09-18 01:58:21 +02:00
|
|
|
static inline void qsort_safe(void *base, size_t nmemb, size_t size, __compar_fn_t compar) {
|
2015-10-27 03:01:06 +01:00
|
|
|
if (nmemb <= 1)
|
|
|
|
return;
|
2013-02-11 05:09:29 +01:00
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
assert(base);
|
|
|
|
qsort(base, nmemb, size, compar);
|
2013-03-05 15:52:44 +01:00
|
|
|
}
|
2013-03-19 20:01:18 +01:00
|
|
|
|
2018-03-27 14:56:29 +02:00
|
|
|
/* A wrapper around the above, but that adds typesafety: the element size is automatically derived from the type and so
|
|
|
|
* is the prototype for the comparison function */
|
|
|
|
#define typesafe_qsort(p, n, func) \
|
|
|
|
({ \
|
|
|
|
int (*_func_)(const typeof(p[0])*, const typeof(p[0])*) = func; \
|
|
|
|
qsort_safe((p), (n), sizeof((p)[0]), (__compar_fn_t) _func_); \
|
|
|
|
})
|
|
|
|
|
2018-09-18 01:58:21 +02:00
|
|
|
static inline void qsort_r_safe(void *base, size_t nmemb, size_t size, __compar_d_fn_t compar, void *userdata) {
|
2018-04-11 19:51:39 +02:00
|
|
|
if (nmemb <= 1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
assert(base);
|
|
|
|
qsort_r(base, nmemb, size, compar, userdata);
|
|
|
|
}
|
|
|
|
|
2018-09-18 01:58:21 +02:00
|
|
|
#define typesafe_qsort_r(p, n, func, userdata) \
|
|
|
|
({ \
|
|
|
|
int (*_func_)(const typeof(p[0])*, const typeof(p[0])*, typeof(userdata)) = func; \
|
|
|
|
qsort_r_safe((p), (n), sizeof((p)[0]), (__compar_d_fn_t) _func_, userdata); \
|
|
|
|
})
|
|
|
|
|
2018-08-08 09:22:55 +02:00
|
|
|
/* Normal memcpy requires src to be nonnull. We do nothing if n is 0. */
|
2016-02-02 03:57:41 +01:00
|
|
|
static inline void memcpy_safe(void *dst, const void *src, size_t n) {
|
|
|
|
if (n == 0)
|
|
|
|
return;
|
|
|
|
assert(src);
|
|
|
|
memcpy(dst, src, n);
|
|
|
|
}
|
|
|
|
|
2018-08-08 09:22:55 +02:00
|
|
|
/* Normal memcmp requires s1 and s2 to be nonnull. We do nothing if n is 0. */
|
|
|
|
static inline int memcmp_safe(const void *s1, const void *s2, size_t n) {
|
|
|
|
if (n == 0)
|
|
|
|
return 0;
|
|
|
|
assert(s1);
|
|
|
|
assert(s2);
|
|
|
|
return memcmp(s1, s2, n);
|
|
|
|
}
|
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
int on_ac_power(void);
|
|
|
|
|
2018-10-10 11:34:30 +02:00
|
|
|
#define memzero(x,l) \
|
|
|
|
({ \
|
|
|
|
size_t _l_ = (l); \
|
|
|
|
void *_x_ = (x); \
|
|
|
|
_l_ == 0 ? _x_ : memset(_x_, 0, _l_); \
|
|
|
|
})
|
|
|
|
|
2015-10-27 01:48:17 +01:00
|
|
|
#define zero(x) (memzero(&(x), sizeof(x)))
|
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
static inline void *mempset(void *s, int c, size_t n) {
|
|
|
|
memset(s, c, n);
|
|
|
|
return (uint8_t*)s + n;
|
|
|
|
}
|
2014-02-25 12:20:25 +01:00
|
|
|
|
2013-04-04 03:39:39 +02:00
|
|
|
static inline void _reset_errno_(int *saved_errno) {
|
2013-04-02 16:31:55 +02:00
|
|
|
errno = *saved_errno;
|
|
|
|
}
|
|
|
|
|
2013-04-26 02:53:29 +02:00
|
|
|
#define PROTECT_ERRNO _cleanup_(_reset_errno_) __attribute__((unused)) int _saved_errno_ = errno
|
2013-04-04 03:39:39 +02:00
|
|
|
|
util: introduce negative_errno()
Imagine a constructor like this:
int object_new(void **out) {
void *my_object;
int r;
...
r = ioctl(...);
if (r < 0)
return -errno;
...
*out = my_object;
return 0;
}
We have a lot of those in systemd. If you now call those, gcc might inline
the call and optimize it. However, gcc cannot know that "errno" is
negative if "r" is. Therefore, a caller like this will produce warnings:
r = object_new(&obj);
if (r < 0)
return r;
obj->xyz = "foobar";
In case the ioctl in the constructor fails, gcc might assume "errno" is 0
and thus the error-handling is not triggered. Therefore, "obj" is
uninitialized, but accessed. Gcc will warn about that.
The new negative_errno() helper can be used to mitigate those warnings.
The helper is guaranteed to return a negative integer. Furthermore, it
spills out runtime warnings if "errno" is non-negative.
Instead of returning "-errno", you can use:
return negative_errno();
gcc will no longer assume that this can return >=0, thus, it will not warn
about it.
Use this new helper in libsystemd-terminal to fix some grdev-drm warnings.
2014-11-03 18:23:28 +01:00
|
|
|
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();"
|
|
|
|
* It will suppress bogus gcc warnings in case it assumes 'errno' might
|
|
|
|
* be 0 and thus the caller's error-handling might not be triggered. */
|
|
|
|
assert_return(errno > 0, -EINVAL);
|
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
|
2013-04-05 01:09:50 +02:00
|
|
|
static inline unsigned u64log2(uint64_t n) {
|
2014-01-30 16:46:48 +01:00
|
|
|
#if __SIZEOF_LONG_LONG__ == 8
|
2013-12-25 17:46:45 +01:00
|
|
|
return (n > 1) ? (unsigned) __builtin_clzll(n) ^ 63U : 0;
|
2014-01-30 16:46:48 +01:00
|
|
|
#else
|
|
|
|
#error "Wut?"
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned u32ctz(uint32_t n) {
|
|
|
|
#if __SIZEOF_INT__ == 4
|
|
|
|
return __builtin_ctz(n);
|
|
|
|
#else
|
|
|
|
#error "Wut?"
|
|
|
|
#endif
|
2013-04-05 01:09:50 +02:00
|
|
|
}
|
2013-03-26 11:36:31 +01:00
|
|
|
|
2015-02-01 21:26:46 +01:00
|
|
|
static inline unsigned log2i(int x) {
|
2014-03-15 02:43:56 +01:00
|
|
|
assert(x > 0);
|
|
|
|
|
|
|
|
return __SIZEOF_INT__ * 8 - __builtin_clz(x) - 1;
|
|
|
|
}
|
|
|
|
|
2014-10-15 01:28:54 +02:00
|
|
|
static inline unsigned log2u(unsigned x) {
|
|
|
|
assert(x > 0);
|
|
|
|
|
|
|
|
return sizeof(unsigned) * 8 - __builtin_clz(x) - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned log2u_round_up(unsigned x) {
|
|
|
|
assert(x > 0);
|
|
|
|
|
|
|
|
if (x == 1)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return log2u(x - 1) + 1;
|
|
|
|
}
|
|
|
|
|
2013-12-13 22:02:47 +01:00
|
|
|
int container_get_leader(const char *machine, pid_t *pid);
|
|
|
|
|
namespace helpers: Allow entering a UID namespace
To be able to use `systemd-run` or `machinectl login` on a container
that is in a private user namespace, the sub-process must have entered
the user namespace before connecting to the container's D-Bus, otherwise
the UID and GID in the peer credentials are garbage.
So we extend namespace_open and namespace_enter to support UID namespaces,
and we enter the UID namespace in bus_container_connect_{socket,kernel}.
namespace_open will degrade to a no-op if user namespaces are not enabled
in the kernel.
Special handling is required for the setns call in namespace_enter with
a user namespace, since transitioning to your own namespace is forbidden,
as it would result in re-entering your user namespace as root.
Arguably it may be valid to check this at the call site, rather than
inside namespace_enter, but it is less code to do it inside, and if the
intention of calling namespace_enter is to *be* in the target namespace,
rather than to transition to the target namespace, it is a reasonable
approach.
The check for whether the user namespace is the same must happen before
entering namespaces, as we may not be able to access /proc during the
intermediate transition stage.
We can't instead attempt to enter the user namespace and then ignore
the failure from it being the same namespace, since the error code is
not distinct, and we can't compare namespaces while mid-transition.
2015-08-17 10:52:13 +02:00
|
|
|
int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd);
|
|
|
|
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
|
2013-12-18 04:19:20 +01:00
|
|
|
|
2014-03-04 19:20:21 +01:00
|
|
|
uint64_t physical_memory(void);
|
2016-06-08 20:45:32 +02:00
|
|
|
uint64_t physical_memory_scale(uint64_t v, uint64_t max);
|
2014-03-06 21:14:26 +01:00
|
|
|
|
2016-07-19 15:58:49 +02:00
|
|
|
uint64_t system_tasks_max(void);
|
|
|
|
uint64_t system_tasks_max_scale(uint64_t v, uint64_t max);
|
|
|
|
|
2015-09-23 03:01:06 +02:00
|
|
|
int version(void);
|
2017-12-23 15:02:58 +01:00
|
|
|
|
|
|
|
int str_verscmp(const char *s1, const char *s2);
|
2018-01-10 10:36:14 +01:00
|
|
|
|
2018-01-10 18:37:54 +01:00
|
|
|
void disable_coredumps(void);
|