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
|
|
|
|
2010-02-03 13:03:47 +01:00
|
|
|
/***
|
|
|
|
This file is part of systemd.
|
|
|
|
|
|
|
|
Copyright 2010 Lennart Poettering
|
|
|
|
|
|
|
|
systemd is free software; you can redistribute it and/or modify it
|
2012-04-12 00:20:58 +02:00
|
|
|
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
|
2010-02-03 13:03:47 +01:00
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
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
|
2012-04-12 00:20:58 +02:00
|
|
|
Lesser General Public License for more details.
|
2010-02-03 13:03:47 +01:00
|
|
|
|
2012-04-12 00:20:58 +02:00
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
2010-02-03 13:03:47 +01:00
|
|
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
***/
|
|
|
|
|
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
|
|
|
int socket_from_display(const char *display, char **path);
|
|
|
|
|
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,
|
|
|
|
int (*compar) (const void *, const void *, void *),
|
|
|
|
void *arg);
|
2012-11-02 17:27:15 +01:00
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
/**
|
|
|
|
* Normal qsort requires base to be nonnull. Here were require
|
|
|
|
* that only if nmemb > 0.
|
|
|
|
*/
|
|
|
|
static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_fn_t compar) {
|
|
|
|
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
|
|
|
|
2016-02-02 03:57:41 +01:00
|
|
|
/**
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
int on_ac_power(void);
|
|
|
|
|
2015-10-27 01:48:17 +01:00
|
|
|
#define memzero(x,l) (memset((x), 0, (l)))
|
|
|
|
#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);
|
|
|
|
|
2016-04-07 16:53:37 +02:00
|
|
|
int update_reboot_parameter_and_warn(const char *param);
|
2014-06-05 21:35:35 +02:00
|
|
|
|
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
|
|
|
|
|
|
|
void disable_core_dumps(void);
|