summaryrefslogtreecommitdiff
path: root/src/udev
diff options
context:
space:
mode:
authorIan Stakenvicius <axs@gentoo.org>2012-11-29 15:33:24 -0500
committerAnthony G. Basile <blueness@gentoo.org>2012-12-01 13:49:20 -0500
commitff05ef7ab20ced0f8ae2cd2df313946c3a287bb7 (patch)
tree3abcfc474319fe5a6c11c8752d1af314529a881e /src/udev
parent1bbffd4f09a3715d1897e617ea83eefdcbff2c02 (diff)
Moved files to libudev that once were in upstream libsystemd-shared
Diffstat (limited to 'src/udev')
-rw-r--r--src/udev/Makefile.am30
-rw-r--r--src/udev/cgroup-util.c1256
-rw-r--r--src/udev/cgroup-util.h74
-rw-r--r--src/udev/conf-files.c153
-rw-r--r--src/udev/conf-files.h31
-rw-r--r--src/udev/def.h35
-rw-r--r--src/udev/exit-status.c192
-rw-r--r--src/udev/exit-status.h88
-rw-r--r--src/udev/hashmap.c835
-rw-r--r--src/udev/hashmap.h98
-rw-r--r--src/udev/ioprio.h57
-rw-r--r--src/udev/log.c865
-rw-r--r--src/udev/log.h137
-rw-r--r--src/udev/macro.h242
-rw-r--r--src/udev/missing.h247
-rw-r--r--src/udev/path-util.c419
-rw-r--r--src/udev/path-util.h45
-rw-r--r--src/udev/set.c130
-rw-r--r--src/udev/set.h71
-rw-r--r--src/udev/socket-util.h99
-rw-r--r--src/udev/sparse-endian.h87
-rw-r--r--src/udev/strbuf.c176
-rw-r--r--src/udev/strbuf.h56
-rw-r--r--src/udev/strv.c750
-rw-r--r--src/udev/strv.h84
-rw-r--r--src/udev/util.c6255
-rw-r--r--src/udev/util.h616
27 files changed, 2 insertions, 13126 deletions
diff --git a/src/udev/Makefile.am b/src/udev/Makefile.am
index 8f4eafe46e..b65048bf91 100644
--- a/src/udev/Makefile.am
+++ b/src/udev/Makefile.am
@@ -52,44 +52,18 @@ libudev_core_la_SOURCES = \
udev-builtin-net_id.c \
udev-builtin-path_id.c \
udev-builtin-usb_id.c \
- conf-files.c \
- cgroup-util.c \
dev-setup.c \
- exit-status.c \
- hashmap.c \
label.c \
- log.c \
mkdir.c \
- path-util.c \
sd-daemon.c \
- sd-login.c \
- set.c \
- strbuf.c \
- strv.c \
- util.c
+ sd-login.c
noinst_HEADERS = \
- cgroup-util.h \
- conf-files.h \
- def.h \
dev-setup.h \
- exit-status.h \
- hashmap.h \
- ioprio.h \
label.h \
- log.h \
- macro.h \
- missing.h \
mkdir.h \
- path-util.h \
sd-daemon.h \
- sd-login.h \
- set.h \
- socket-util.h \
- sparse-endian.h \
- strbuf.h \
- strv.h \
- util.h
+ sd-login.h
include_HEADERS = \
udev.h
diff --git a/src/udev/cgroup-util.c b/src/udev/cgroup-util.c
deleted file mode 100644
index b0d378de5a..0000000000
--- a/src/udev/cgroup-util.c
+++ /dev/null
@@ -1,1256 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <unistd.h>
-#include <signal.h>
-#include <string.h>
-#include <stdlib.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <ftw.h>
-
-#include "cgroup-util.h"
-#include "log.h"
-#include "set.h"
-#include "macro.h"
-#include "util.h"
-#include "path-util.h"
-#include "strv.h"
-
-int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
- char *fs;
- int r;
- FILE *f;
-
- assert(path);
- assert(_f);
-
- r = cg_get_path(controller, path, "cgroup.procs", &fs);
- if (r < 0)
- return r;
-
- f = fopen(fs, "re");
- free(fs);
-
- if (!f)
- return -errno;
-
- *_f = f;
- return 0;
-}
-
-int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f) {
- char *fs;
- int r;
- FILE *f;
-
- assert(path);
- assert(_f);
-
- r = cg_get_path(controller, path, "tasks", &fs);
- if (r < 0)
- return r;
-
- f = fopen(fs, "re");
- free(fs);
-
- if (!f)
- return -errno;
-
- *_f = f;
- return 0;
-}
-
-int cg_read_pid(FILE *f, pid_t *_pid) {
- unsigned long ul;
-
- /* Note that the cgroup.procs might contain duplicates! See
- * cgroups.txt for details. */
-
- errno = 0;
- if (fscanf(f, "%lu", &ul) != 1) {
-
- if (feof(f))
- return 0;
-
- return errno ? -errno : -EIO;
- }
-
- if (ul <= 0)
- return -EIO;
-
- *_pid = (pid_t) ul;
- return 1;
-}
-
-int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) {
- char *fs;
- int r;
- DIR *d;
-
- assert(path);
- assert(_d);
-
- /* This is not recursive! */
-
- r = cg_get_path(controller, path, NULL, &fs);
- if (r < 0)
- return r;
-
- d = opendir(fs);
- free(fs);
-
- if (!d)
- return -errno;
-
- *_d = d;
- return 0;
-}
-
-int cg_read_subgroup(DIR *d, char **fn) {
- struct dirent *de;
-
- assert(d);
-
- errno = 0;
- while ((de = readdir(d))) {
- char *b;
-
- if (de->d_type != DT_DIR)
- continue;
-
- if (streq(de->d_name, ".") ||
- streq(de->d_name, ".."))
- continue;
-
- if (!(b = strdup(de->d_name)))
- return -ENOMEM;
-
- *fn = b;
- return 1;
- }
-
- if (errno)
- return -errno;
-
- return 0;
-}
-
-int cg_rmdir(const char *controller, const char *path, bool honour_sticky) {
- char *p;
- int r;
-
- r = cg_get_path(controller, path, NULL, &p);
- if (r < 0)
- return r;
-
- if (honour_sticky) {
- char *tasks;
-
- /* If the sticky bit is set don't remove the directory */
-
- tasks = strappend(p, "/tasks");
- if (!tasks) {
- free(p);
- return -ENOMEM;
- }
-
- r = file_is_priv_sticky(tasks);
- free(tasks);
-
- if (r > 0) {
- free(p);
- return 0;
- }
- }
-
- r = rmdir(p);
- free(p);
-
- return (r < 0 && errno != ENOENT) ? -errno : 0;
-}
-
-int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) {
- bool done = false;
- int r, ret = 0;
- pid_t my_pid;
- FILE *f = NULL;
- Set *allocated_set = NULL;
-
- assert(controller);
- assert(path);
- assert(sig >= 0);
-
- /* This goes through the tasks list and kills them all. This
- * is repeated until no further processes are added to the
- * tasks list, to properly handle forking processes */
-
- if (!s)
- if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
- return -ENOMEM;
-
- my_pid = getpid();
-
- do {
- pid_t pid = 0;
- done = true;
-
- if ((r = cg_enumerate_processes(controller, path, &f)) < 0) {
- if (ret >= 0 && r != -ENOENT)
- ret = r;
-
- goto finish;
- }
-
- while ((r = cg_read_pid(f, &pid)) > 0) {
-
- if (pid == my_pid && ignore_self)
- continue;
-
- if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
- continue;
-
- /* If we haven't killed this process yet, kill
- * it */
- if (kill(pid, sig) < 0) {
- if (ret >= 0 && errno != ESRCH)
- ret = -errno;
- } else if (ret == 0) {
-
- if (sigcont)
- kill(pid, SIGCONT);
-
- ret = 1;
- }
-
- done = false;
-
- if ((r = set_put(s, LONG_TO_PTR(pid))) < 0) {
- if (ret >= 0)
- ret = r;
-
- goto finish;
- }
- }
-
- if (r < 0) {
- if (ret >= 0)
- ret = r;
-
- goto finish;
- }
-
- fclose(f);
- f = NULL;
-
- /* To avoid racing against processes which fork
- * quicker than we can kill them we repeat this until
- * no new pids need to be killed. */
-
- } while (!done);
-
-finish:
- if (allocated_set)
- set_free(allocated_set);
-
- if (f)
- fclose(f);
-
- return ret;
-}
-
-int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) {
- int r, ret = 0;
- DIR *d = NULL;
- char *fn;
- Set *allocated_set = NULL;
-
- assert(path);
- assert(controller);
- assert(sig >= 0);
-
- if (!s)
- if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
- return -ENOMEM;
-
- ret = cg_kill(controller, path, sig, sigcont, ignore_self, s);
-
- if ((r = cg_enumerate_subgroups(controller, path, &d)) < 0) {
- if (ret >= 0 && r != -ENOENT)
- ret = r;
-
- goto finish;
- }
-
- while ((r = cg_read_subgroup(d, &fn)) > 0) {
- char *p = NULL;
-
- r = asprintf(&p, "%s/%s", path, fn);
- free(fn);
-
- if (r < 0) {
- if (ret >= 0)
- ret = -ENOMEM;
-
- goto finish;
- }
-
- r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s);
- free(p);
-
- if (r != 0 && ret >= 0)
- ret = r;
- }
-
- if (r < 0 && ret >= 0)
- ret = r;
-
- if (rem)
- if ((r = cg_rmdir(controller, path, true)) < 0) {
- if (ret >= 0 &&
- r != -ENOENT &&
- r != -EBUSY)
- ret = r;
- }
-
-finish:
- if (d)
- closedir(d);
-
- if (allocated_set)
- set_free(allocated_set);
-
- return ret;
-}
-
-int cg_kill_recursive_and_wait(const char *controller, const char *path, bool rem) {
- unsigned i;
-
- assert(path);
- assert(controller);
-
- /* This safely kills all processes; first it sends a SIGTERM,
- * then checks 8 times after 200ms whether the group is now
- * empty, then kills everything that is left with SIGKILL and
- * finally checks 5 times after 200ms each whether the group
- * is finally empty. */
-
- for (i = 0; i < 15; i++) {
- int sig, r;
-
- if (i <= 0)
- sig = SIGTERM;
- else if (i == 9)
- sig = SIGKILL;
- else
- sig = 0;
-
- if ((r = cg_kill_recursive(controller, path, sig, true, true, rem, NULL)) <= 0)
- return r;
-
- usleep(200 * USEC_PER_MSEC);
- }
-
- return 0;
-}
-
-int cg_migrate(const char *controller, const char *from, const char *to, bool ignore_self) {
- bool done = false;
- Set *s;
- int r, ret = 0;
- pid_t my_pid;
- FILE *f = NULL;
-
- assert(controller);
- assert(from);
- assert(to);
-
- if (!(s = set_new(trivial_hash_func, trivial_compare_func)))
- return -ENOMEM;
-
- my_pid = getpid();
-
- do {
- pid_t pid = 0;
- done = true;
-
- if ((r = cg_enumerate_tasks(controller, from, &f)) < 0) {
- if (ret >= 0 && r != -ENOENT)
- ret = r;
-
- goto finish;
- }
-
- while ((r = cg_read_pid(f, &pid)) > 0) {
-
- /* This might do weird stuff if we aren't a
- * single-threaded program. However, we
- * luckily know we are not */
- if (pid == my_pid && ignore_self)
- continue;
-
- if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
- continue;
-
- if ((r = cg_attach(controller, to, pid)) < 0) {
- if (ret >= 0 && r != -ESRCH)
- ret = r;
- } else if (ret == 0)
- ret = 1;
-
- done = false;
-
- if ((r = set_put(s, LONG_TO_PTR(pid))) < 0) {
- if (ret >= 0)
- ret = r;
-
- goto finish;
- }
- }
-
- if (r < 0) {
- if (ret >= 0)
- ret = r;
-
- goto finish;
- }
-
- fclose(f);
- f = NULL;
-
- } while (!done);
-
-finish:
- set_free(s);
-
- if (f)
- fclose(f);
-
- return ret;
-}
-
-int cg_migrate_recursive(const char *controller, const char *from, const char *to, bool ignore_self, bool rem) {
- int r, ret = 0;
- DIR *d = NULL;
- char *fn;
-
- assert(controller);
- assert(from);
- assert(to);
-
- ret = cg_migrate(controller, from, to, ignore_self);
-
- if ((r = cg_enumerate_subgroups(controller, from, &d)) < 0) {
- if (ret >= 0 && r != -ENOENT)
- ret = r;
- goto finish;
- }
-
- while ((r = cg_read_subgroup(d, &fn)) > 0) {
- char *p = NULL;
-
- r = asprintf(&p, "%s/%s", from, fn);
- free(fn);
-
- if (r < 0) {
- if (ret >= 0)
- ret = -ENOMEM;
-
- goto finish;
- }
-
- r = cg_migrate_recursive(controller, p, to, ignore_self, rem);
- free(p);
-
- if (r != 0 && ret >= 0)
- ret = r;
- }
-
- if (r < 0 && ret >= 0)
- ret = r;
-
- if (rem)
- if ((r = cg_rmdir(controller, from, true)) < 0) {
- if (ret >= 0 &&
- r != -ENOENT &&
- r != -EBUSY)
- ret = r;
- }
-
-finish:
- if (d)
- closedir(d);
-
- return ret;
-}
-
-static const char *normalize_controller(const char *controller) {
-
- if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
- return "systemd";
- else if (startswith(controller, "name="))
- return controller + 5;
- else
- return controller;
-}
-
-static int join_path(const char *controller, const char *path, const char *suffix, char **fs) {
- char *t = NULL;
-
- if (!(controller || path))
- return -EINVAL;
-
- if (controller) {
- if (path && suffix)
- t = strjoin("/sys/fs/cgroup/", controller, "/", path, "/", suffix, NULL);
- else if (path)
- t = strjoin("/sys/fs/cgroup/", controller, "/", path, NULL);
- else if (suffix)
- t = strjoin("/sys/fs/cgroup/", controller, "/", suffix, NULL);
- else
- t = strjoin("/sys/fs/cgroup/", controller, NULL);
- } else {
- if (path && suffix)
- t = strjoin(path, "/", suffix, NULL);
- else if (path)
- t = strdup(path);
- }
-
- if (!t)
- return -ENOMEM;
-
- path_kill_slashes(t);
-
- *fs = t;
- return 0;
-}
-
-int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
- const char *p;
- static __thread bool good = false;
-
- assert(fs);
-
- if (_unlikely_(!good)) {
- int r;
-
- r = path_is_mount_point("/sys/fs/cgroup", false);
- if (r <= 0)
- return r < 0 ? r : -ENOENT;
-
- /* Cache this to save a few stat()s */
- good = true;
- }
-
- p = controller ? normalize_controller(controller) : NULL;
- return join_path(p, path, suffix, fs);
-}
-
-static int check(const char *p) {
- char *cc;
-
- assert(p);
-
- /* Check if this controller actually really exists */
- cc = alloca(sizeof("/sys/fs/cgroup/") + strlen(p));
- strcpy(stpcpy(cc, "/sys/fs/cgroup/"), p);
- if (access(cc, F_OK) < 0)
- return -errno;
-
- return 0;
-}
-
-int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) {
- const char *p;
- int r;
-
- assert(controller);
- assert(fs);
-
- if (isempty(controller))
- return -EINVAL;
-
- /* Normalize the controller syntax */
- p = normalize_controller(controller);
-
- /* Check if this controller actually really exists */
- r = check(p);
- if (r < 0)
- return r;
-
- return join_path(p, path, suffix, fs);
-}
-
-static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
- char *p;
- bool is_sticky;
-
- if (typeflag != FTW_DP)
- return 0;
-
- if (ftwbuf->level < 1)
- return 0;
-
- p = strappend(path, "/tasks");
- if (!p) {
- errno = ENOMEM;
- return 1;
- }
-
- is_sticky = file_is_priv_sticky(p) > 0;
- free(p);
-
- if (is_sticky)
- return 0;
-
- rmdir(path);
- return 0;
-}
-
-int cg_trim(const char *controller, const char *path, bool delete_root) {
- char *fs;
- int r = 0;
-
- assert(controller);
- assert(path);
-
- r = cg_get_path(controller, path, NULL, &fs);
- if (r < 0)
- return r;
-
- errno = 0;
- if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) < 0)
- r = errno ? -errno : -EIO;
-
- if (delete_root) {
- bool is_sticky;
- char *p;
-
- p = strappend(fs, "/tasks");
- if (!p) {
- free(fs);
- return -ENOMEM;
- }
-
- is_sticky = file_is_priv_sticky(p) > 0;
- free(p);
-
- if (!is_sticky)
- if (rmdir(fs) < 0 && errno != ENOENT) {
- if (r == 0)
- r = -errno;
- }
- }
-
- free(fs);
-
- return r;
-}
-
-int cg_delete(const char *controller, const char *path) {
- char *parent;
- int r;
-
- assert(controller);
- assert(path);
-
- if ((r = path_get_parent(path, &parent)) < 0)
- return r;
-
- r = cg_migrate_recursive(controller, path, parent, false, true);
- free(parent);
-
- return r == -ENOENT ? 0 : r;
-}
-
-int cg_attach(const char *controller, const char *path, pid_t pid) {
- char *fs;
- int r;
- char c[32];
-
- assert(controller);
- assert(path);
- assert(pid >= 0);
-
- r = cg_get_path_and_check(controller, path, "tasks", &fs);
- if (r < 0)
- return r;
-
- if (pid == 0)
- pid = getpid();
-
- snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
- char_array_0(c);
-
- r = write_one_line_file(fs, c);
- free(fs);
-
- return r;
-}
-
-int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
- char *fs;
- int r;
-
- assert(controller);
- assert(path);
-
- if (mode != (mode_t) -1)
- mode &= 0777;
-
- r = cg_get_path(controller, path, NULL, &fs);
- if (r < 0)
- return r;
-
- r = chmod_and_chown(fs, mode, uid, gid);
- free(fs);
-
- return r;
-}
-
-int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid, int sticky) {
- char *fs;
- int r;
-
- assert(controller);
- assert(path);
-
- if (mode == (mode_t) -1 && uid == (uid_t) -1 && gid == (gid_t) -1 && sticky < 0)
- return 0;
-
- if (mode != (mode_t) -1)
- mode &= 0666;
-
- r = cg_get_path(controller, path, "tasks", &fs);
- if (r < 0)
- return r;
-
- if (sticky >= 0 && mode != (mode_t) -1)
- /* Both mode and sticky param are passed */
- mode |= (sticky ? S_ISVTX : 0);
- else if ((sticky >= 0 && mode == (mode_t) -1) ||
- (mode != (mode_t) -1 && sticky < 0)) {
- struct stat st;
-
- /* Only one param is passed, hence read the current
- * mode from the file itself */
-
- r = lstat(fs, &st);
- if (r < 0) {
- free(fs);
- return -errno;
- }
-
- if (mode == (mode_t) -1)
- /* No mode set, we just shall set the sticky bit */
- mode = (st.st_mode & ~S_ISVTX) | (sticky ? S_ISVTX : 0);
- else
- /* Only mode set, leave sticky bit untouched */
- mode = (st.st_mode & ~0777) | mode;
- }
-
- r = chmod_and_chown(fs, mode, uid, gid);
- free(fs);
-
- return r;
-}
-
-int cg_get_by_pid(const char *controller, pid_t pid, char **path) {
- int r;
- char *p = NULL;
- FILE *f;
- char *fs;
- size_t cs;
-
- assert(controller);
- assert(path);
- assert(pid >= 0);
-
- if (pid == 0)
- pid = getpid();
-
- if (asprintf(&fs, "/proc/%lu/cgroup", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- f = fopen(fs, "re");
- free(fs);
-
- if (!f)
- return errno == ENOENT ? -ESRCH : -errno;
-
- cs = strlen(controller);
-
- while (!feof(f)) {
- char line[LINE_MAX];
- char *l;
-
- errno = 0;
- if (!(fgets(line, sizeof(line), f))) {
- if (feof(f))
- break;
-
- r = errno ? -errno : -EIO;
- goto finish;
- }
-
- truncate_nl(line);
-
- if (!(l = strchr(line, ':')))
- continue;
-
- l++;
- if (strncmp(l, controller, cs) != 0)
- continue;
-
- if (l[cs] != ':')
- continue;
-
- if (!(p = strdup(l + cs + 1))) {
- r = -ENOMEM;
- goto finish;
- }
-
- *path = p;
- r = 0;
- goto finish;
- }
-
- r = -ENOENT;
-
-finish:
- fclose(f);
-
- return r;
-}
-
-int cg_install_release_agent(const char *controller, const char *agent) {
- char *fs = NULL, *contents = NULL, *line = NULL, *sc;
- int r;
-
- assert(controller);
- assert(agent);
-
- if ((r = cg_get_path(controller, NULL, "release_agent", &fs)) < 0)
- return r;
-
- if ((r = read_one_line_file(fs, &contents)) < 0)
- goto finish;
-
- sc = strstrip(contents);
- if (sc[0] == 0) {
-
- if (asprintf(&line, "%s\n", agent) < 0) {
- r = -ENOMEM;
- goto finish;
- }
-
- if ((r = write_one_line_file(fs, line)) < 0)
- goto finish;
-
- } else if (!streq(sc, agent)) {
- r = -EEXIST;
- goto finish;
- }
-
- free(fs);
- fs = NULL;
- if ((r = cg_get_path(controller, NULL, "notify_on_release", &fs)) < 0)
- goto finish;
-
- free(contents);
- contents = NULL;
- if ((r = read_one_line_file(fs, &contents)) < 0)
- goto finish;
-
- sc = strstrip(contents);
-
- if (streq(sc, "0")) {
- if ((r = write_one_line_file(fs, "1\n")) < 0)
- goto finish;
-
- r = 1;
- } else if (!streq(sc, "1")) {
- r = -EIO;
- goto finish;
- } else
- r = 0;
-
-finish:
- free(fs);
- free(contents);
- free(line);
-
- return r;
-}
-
-int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
- pid_t pid = 0, self_pid;
- int r;
- FILE *f = NULL;
- bool found = false;
-
- assert(path);
-
- r = cg_enumerate_tasks(controller, path, &f);
- if (r < 0)
- return r == -ENOENT ? 1 : r;
-
- self_pid = getpid();
-
- while ((r = cg_read_pid(f, &pid)) > 0) {
-
- if (ignore_self && pid == self_pid)
- continue;
-
- found = true;
- break;
- }
-
- fclose(f);
-
- if (r < 0)
- return r;
-
- return !found;
-}
-
-int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
- int r;
- DIR *d = NULL;
- char *fn;
-
- assert(path);
-
- r = cg_is_empty(controller, path, ignore_self);
- if (r <= 0)
- return r;
-
- r = cg_enumerate_subgroups(controller, path, &d);
- if (r < 0)
- return r == -ENOENT ? 1 : r;
-
- while ((r = cg_read_subgroup(d, &fn)) > 0) {
- char *p = NULL;
-
- r = asprintf(&p, "%s/%s", path, fn);
- free(fn);
-
- if (r < 0) {
- r = -ENOMEM;
- goto finish;
- }
-
- r = cg_is_empty_recursive(controller, p, ignore_self);
- free(p);
-
- if (r <= 0)
- goto finish;
- }
-
- if (r >= 0)
- r = 1;
-
-finish:
-
- if (d)
- closedir(d);
-
- return r;
-}
-
-int cg_split_spec(const char *spec, char **controller, char **path) {
- const char *e;
- char *t = NULL, *u = NULL;
-
- assert(spec);
- assert(controller || path);
-
- if (*spec == '/') {
-
- if (path) {
- if (!(t = strdup(spec)))
- return -ENOMEM;
-
- *path = t;
- }
-
- if (controller)
- *controller = NULL;
-
- return 0;
- }
-
- if (!(e = strchr(spec, ':'))) {
-
- if (strchr(spec, '/') || spec[0] == 0)
- return -EINVAL;
-
- if (controller) {
- if (!(t = strdup(spec)))
- return -ENOMEM;
-
- *controller = t;
- }
-
- if (path)
- *path = NULL;
-
- return 0;
- }
-
- if (e[1] != '/' ||
- e == spec ||
- memchr(spec, '/', e-spec))
- return -EINVAL;
-
- if (controller)
- if (!(t = strndup(spec, e-spec)))
- return -ENOMEM;
-
- if (path)
- if (!(u = strdup(e+1))) {
- free(t);
- return -ENOMEM;
- }
-
- if (controller)
- *controller = t;
-
- if (path)
- *path = u;
-
- return 0;
-}
-
-int cg_join_spec(const char *controller, const char *path, char **spec) {
- assert(controller);
- assert(path);
-
- if (!path_is_absolute(path) ||
- controller[0] == 0 ||
- strchr(controller, ':') ||
- strchr(controller, '/'))
- return -EINVAL;
-
- if (asprintf(spec, "%s:%s", controller, path) < 0)
- return -ENOMEM;
-
- return 0;
-}
-
-int cg_fix_path(const char *path, char **result) {
- char *t, *c, *p;
- int r;
-
- assert(path);
- assert(result);
-
- /* First check if it already is a filesystem path */
- if (path_startswith(path, "/sys/fs/cgroup") &&
- access(path, F_OK) >= 0) {
-
- t = strdup(path);
- if (!t)
- return -ENOMEM;
-
- *result = t;
- return 0;
- }
-
- /* Otherwise treat it as cg spec */
- r = cg_split_spec(path, &c, &p);
- if (r < 0)
- return r;
-
- r = cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
- free(c);
- free(p);
-
- return r;
-}
-
-int cg_get_user_path(char **path) {
- char *root, *p;
-
- assert(path);
-
- /* Figure out the place to put user cgroups below. We use the
- * same as PID 1 has but with the "/system" suffix replaced by
- * "/user" */
-
- if (cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &root) < 0)
- p = strdup("/user");
- else {
- if (endswith(root, "/system"))
- root[strlen(root) - 7] = 0;
- else if (streq(root, "/"))
- root[0] = 0;
-
- p = strappend(root, "/user");
- free(root);
- }
-
- if (!p)
- return -ENOMEM;
-
- *path = p;
- return 0;
-}
-
-char **cg_shorten_controllers(char **controllers) {
- char **f, **t;
-
- controllers = strv_uniq(controllers);
-
- if (!controllers)
- return controllers;
-
- for (f = controllers, t = controllers; *f; f++) {
- int r;
- const char *p;
-
- if (streq(*f, "systemd") || streq(*f, SYSTEMD_CGROUP_CONTROLLER)) {
- free(*f);
- continue;
- }
-
- p = normalize_controller(*f);
-
- r = check(p);
- if (r < 0) {
- log_debug("Controller %s is not available, removing from controllers list.", *f);
- free(*f);
- continue;
- }
-
- *(t++) = *f;
- }
-
- *t = NULL;
- return controllers;
-}
-
-int cg_pid_get_cgroup(pid_t pid, char **root, char **cgroup) {
- char *cg_process, *cg_init, *p;
- int r;
-
- assert(pid >= 0);
-
- if (pid == 0)
- pid = getpid();
-
- r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process);
- if (r < 0)
- return r;
-
- r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &cg_init);
- if (r < 0) {
- free(cg_process);
- return r;
- }
-
- if (endswith(cg_init, "/system"))
- cg_init[strlen(cg_init)-7] = 0;
- else if (streq(cg_init, "/"))
- cg_init[0] = 0;
-
- if (startswith(cg_process, cg_init))
- p = cg_process + strlen(cg_init);
- else
- p = cg_process;
-
- free(cg_init);
-
- if (cgroup) {
- char* c;
-
- c = strdup(p);
- if (!c) {
- free(cg_process);
- return -ENOMEM;
- }
-
- *cgroup = c;
- }
-
- if (root) {
- cg_process[p-cg_process] = 0;
- *root = cg_process;
- } else
- free(cg_process);
-
- return 0;
-}
-
-int cg_pid_get_unit(pid_t pid, char **unit) {
- int r;
- char *cgroup, *p, *at, *b;
- size_t k;
-
- assert(pid >= 0);
- assert(unit);
-
- r = cg_pid_get_cgroup(pid, NULL, &cgroup);
- if (r < 0)
- return r;
-
- if (!startswith(cgroup, "/system/")) {
- free(cgroup);
- return -ENOENT;
- }
-
- p = cgroup + 8;
- k = strcspn(p, "/");
-
- at = memchr(p, '@', k);
- if (at && at[1] == '.') {
- size_t j;
-
- /* This is a templated service */
- if (p[k] != '/') {
- free(cgroup);
- return -EIO;
- }
-
- j = strcspn(p+k+1, "/");
-
- b = malloc(k + j + 1);
-
- if (b) {
- memcpy(b, p, at - p + 1);
- memcpy(b + (at - p) + 1, p + k + 1, j);
- memcpy(b + (at - p) + 1 + j, at + 1, k - (at - p) - 1);
- b[k+j] = 0;
- }
- } else
- b = strndup(p, k);
-
- free(cgroup);
-
- if (!b)
- return -ENOMEM;
-
- *unit = b;
- return 0;
-
-}
diff --git a/src/udev/cgroup-util.h b/src/udev/cgroup-util.h
deleted file mode 100644
index 697669deba..0000000000
--- a/src/udev/cgroup-util.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <dirent.h>
-
-#include "set.h"
-#include "def.h"
-
-int cg_enumerate_processes(const char *controller, const char *path, FILE **_f);
-int cg_enumerate_tasks(const char *controller, const char *path, FILE **_f);
-int cg_read_pid(FILE *f, pid_t *_pid);
-
-int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d);
-int cg_read_subgroup(DIR *d, char **fn);
-
-int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s);
-int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool remove, Set *s);
-int cg_kill_recursive_and_wait(const char *controller, const char *path, bool remove);
-
-int cg_migrate(const char *controller, const char *from, const char *to, bool ignore_self);
-int cg_migrate_recursive(const char *controller, const char *from, const char *to, bool ignore_self, bool remove);
-
-int cg_split_spec(const char *spec, char **controller, char **path);
-int cg_join_spec(const char *controller, const char *path, char **spec);
-int cg_fix_path(const char *path, char **result);
-
-int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs);
-int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs);
-int cg_get_by_pid(const char *controller, pid_t pid, char **path);
-
-int cg_trim(const char *controller, const char *path, bool delete_root);
-
-int cg_rmdir(const char *controller, const char *path, bool honour_sticky);
-int cg_delete(const char *controller, const char *path);
-
-int cg_create(const char *controller, const char *path);
-int cg_attach(const char *controller, const char *path, pid_t pid);
-int cg_create_and_attach(const char *controller, const char *path, pid_t pid);
-
-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, int sticky);
-
-int cg_install_release_agent(const char *controller, const char *agent);
-
-int cg_is_empty(const char *controller, const char *path, bool ignore_self);
-int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self);
-
-int cg_get_user_path(char **path);
-int cg_pid_get_cgroup(pid_t pid, char **root, char **cgroup);
-int cg_pid_get_unit(pid_t pid, char **unit);
-
-char **cg_shorten_controllers(char **controllers);
diff --git a/src/udev/conf-files.c b/src/udev/conf-files.c
deleted file mode 100644
index 34b86293d3..0000000000
--- a/src/udev/conf-files.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <assert.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <dirent.h>
-
-#include "macro.h"
-#include "util.h"
-#include "missing.h"
-#include "log.h"
-#include "strv.h"
-#include "path-util.h"
-#include "hashmap.h"
-#include "conf-files.h"
-
-static int files_add(Hashmap *h, const char *path, const char *suffix) {
- DIR *dir;
- int r = 0;
-
- dir = opendir(path);
- if (!dir) {
- if (errno == ENOENT)
- return 0;
- return -errno;
- }
-
- for (;;) {
- struct dirent *de;
- union dirent_storage buf;
- int k;
- char *p;
-
- k = readdir_r(dir, &buf.de, &de);
- if (k != 0) {
- r = -k;
- goto finish;
- }
-
- if (!de)
- break;
-
- if (!dirent_is_file_with_suffix(de, suffix))
- continue;
-
- if (asprintf(&p, "%s/%s", path, de->d_name) < 0) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (hashmap_put(h, path_get_file_name(p), p) <= 0) {
- log_debug("Skip overridden file: %s.", p);
- free(p);
- }
- }
-
-finish:
- closedir(dir);
- return r;
-}
-
-static int base_cmp(const void *a, const void *b) {
- const char *s1, *s2;
-
- s1 = *(char * const *)a;
- s2 = *(char * const *)b;
- return strcmp(path_get_file_name(s1), path_get_file_name(s2));
-}
-
-int conf_files_list_strv(char ***strv, const char *suffix, const char **dirs) {
- Hashmap *fh = NULL;
- char **files = NULL;
- const char **p;
- int r;
-
- assert(dirs);
-
- fh = hashmap_new(string_hash_func, string_compare_func);
- if (!fh) {
- r = -ENOMEM;
- goto finish;
- }
-
- STRV_FOREACH(p, dirs) {
- r = files_add(fh, *p, suffix);
- if (r < 0)
- log_warning("Failed to search for files in %s: %s",
- *p, strerror(-r));
- }
-
- files = hashmap_get_strv(fh);
- if (files == NULL) {
- log_error("Failed to compose list of files.");
- r = -ENOMEM;
- goto finish;
- }
- qsort(files, hashmap_size(fh), sizeof(char *), base_cmp);
- r = 0;
-
-finish:
- hashmap_free(fh);
- *strv = files;
- return r;
-}
-
-int conf_files_list(char ***strv, const char *suffix, const char *dir, ...) {
- char **dirs = NULL;
- va_list ap;
- int r;
-
- va_start(ap, dir);
- dirs = strv_new_ap(dir, ap);
- va_end(ap);
- if (!dirs) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (!path_strv_canonicalize(dirs)) {
- r = -ENOMEM;
- goto finish;
- }
- strv_uniq(dirs);
-
- r = conf_files_list_strv(strv, suffix, (const char **)dirs);
-
-finish:
- strv_free(dirs);
- return r;
-}
diff --git a/src/udev/conf-files.h b/src/udev/conf-files.h
deleted file mode 100644
index f37ee1f3db..0000000000
--- a/src/udev/conf-files.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef fooconffileshfoo
-#define fooconffileshfoo
-
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
- Copyright 2010-2012 Kay Sievers
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "macro.h"
-
-int conf_files_list(char ***strv, const char *suffix, const char *dir, ...);
-int conf_files_list_strv(char ***strv, const char *suffix, const char **dirs);
-
-#endif
diff --git a/src/udev/def.h b/src/udev/def.h
deleted file mode 100644
index 5ba170f965..0000000000
--- a/src/udev/def.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "util.h"
-
-#define DEFAULT_TIMEOUT_USEC (90*USEC_PER_SEC)
-#define DEFAULT_RESTART_USEC (100*USEC_PER_MSEC)
-#define DEFAULT_CONFIRM_USEC (30*USEC_PER_SEC)
-
-#define DEFAULT_EXIT_USEC (5*USEC_PER_MINUTE)
-
-#define SYSTEMD_CGROUP_CONTROLLER "name=systemd"
-
-#define SIGNALS_CRASH_HANDLER SIGSEGV,SIGILL,SIGFPE,SIGBUS,SIGQUIT,SIGABRT
-#define SIGNALS_IGNORE SIGKILL,SIGPIPE
diff --git a/src/udev/exit-status.c b/src/udev/exit-status.c
deleted file mode 100644
index 45131f2b2a..0000000000
--- a/src/udev/exit-status.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdlib.h>
-#include <sys/wait.h>
-
-#include "exit-status.h"
-#include "set.h"
-#include "macro.h"
-
-const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) {
-
- /* We cast to int here, so that -Wenum doesn't complain that
- * EXIT_SUCCESS/EXIT_FAILURE aren't in the enum */
-
- switch ((int) status) {
-
- case EXIT_SUCCESS:
- return "SUCCESS";
-
- case EXIT_FAILURE:
- return "FAILURE";
- }
-
-
- if (level == EXIT_STATUS_SYSTEMD || level == EXIT_STATUS_LSB) {
- switch ((int) status) {
-
- case EXIT_CHDIR:
- return "CHDIR";
-
- case EXIT_NICE:
- return "NICE";
-
- case EXIT_FDS:
- return "FDS";
-
- case EXIT_EXEC:
- return "EXEC";
-
- case EXIT_MEMORY:
- return "MEMORY";
-
- case EXIT_LIMITS:
- return "LIMITS";
-
- case EXIT_OOM_ADJUST:
- return "OOM_ADJUST";
-
- case EXIT_SIGNAL_MASK:
- return "SIGNAL_MASK";
-
- case EXIT_STDIN:
- return "STDIN";
-
- case EXIT_STDOUT:
- return "STDOUT";
-
- case EXIT_CHROOT:
- return "CHROOT";
-
- case EXIT_IOPRIO:
- return "IOPRIO";
-
- case EXIT_TIMERSLACK:
- return "TIMERSLACK";
-
- case EXIT_SECUREBITS:
- return "SECUREBITS";
-
- case EXIT_SETSCHEDULER:
- return "SETSCHEDULER";
-
- case EXIT_CPUAFFINITY:
- return "CPUAFFINITY";
-
- case EXIT_GROUP:
- return "GROUP";
-
- case EXIT_USER:
- return "USER";
-
- case EXIT_CAPABILITIES:
- return "CAPABILITIES";
-
- case EXIT_CGROUP:
- return "CGROUP";
-
- case EXIT_SETSID:
- return "SETSID";
-
- case EXIT_CONFIRM:
- return "CONFIRM";
-
- case EXIT_STDERR:
- return "STDERR";
-
- case EXIT_TCPWRAP:
- return "TCPWRAP";
-
- case EXIT_PAM:
- return "PAM";
-
- case EXIT_NETWORK:
- return "NETWORK";
-
- case EXIT_NAMESPACE:
- return "NAMESPACE";
-
- case EXIT_NO_NEW_PRIVILEGES:
- return "NO_NEW_PRIVILEGES";
-
- case EXIT_SECCOMP:
- return "SECCOMP";
- }
- }
-
- if (level == EXIT_STATUS_LSB) {
- switch ((int) status) {
-
- case EXIT_INVALIDARGUMENT:
- return "INVALIDARGUMENT";
-
- case EXIT_NOTIMPLEMENTED:
- return "NOTIMPLEMENTED";
-
- case EXIT_NOPERMISSION:
- return "NOPERMISSION";
-
- case EXIT_NOTINSTALLED:
- return "NOTINSSTALLED";
-
- case EXIT_NOTCONFIGURED:
- return "NOTCONFIGURED";
-
- case EXIT_NOTRUNNING:
- return "NOTRUNNING";
- }
- }
-
- return NULL;
-}
-
-
-bool is_clean_exit(int code, int status, ExitStatusSet *success_status) {
-
- if (code == CLD_EXITED)
- return status == 0 ||
- (success_status &&
- set_contains(success_status->code, INT_TO_PTR(status)));
-
- /* If a daemon does not implement handlers for some of the
- * signals that's not considered an unclean shutdown */
- if (code == CLD_KILLED)
- return
- status == SIGHUP ||
- status == SIGINT ||
- status == SIGTERM ||
- status == SIGPIPE ||
- (success_status &&
- set_contains(success_status->signal, INT_TO_PTR(status)));
-
- return false;
-}
-
-bool is_clean_exit_lsb(int code, int status, ExitStatusSet *success_status) {
-
- if (is_clean_exit(code, status, success_status))
- return true;
-
- return
- code == CLD_EXITED &&
- (status == EXIT_NOTINSTALLED || status == EXIT_NOTCONFIGURED);
-}
diff --git a/src/udev/exit-status.h b/src/udev/exit-status.h
deleted file mode 100644
index d3b548fc96..0000000000
--- a/src/udev/exit-status.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-#include "set.h"
-typedef enum ExitStatus {
- /* EXIT_SUCCESS defined by libc */
- /* EXIT_FAILURE defined by libc */
- EXIT_INVALIDARGUMENT = 2,
- EXIT_NOTIMPLEMENTED = 3,
- EXIT_NOPERMISSION = 4,
- EXIT_NOTINSTALLED = 5,
- EXIT_NOTCONFIGURED = 6,
- EXIT_NOTRUNNING = 7,
-
- /* The LSB suggests that error codes >= 200 are "reserved". We
- * use them here under the assumption that they hence are
- * unused by init scripts.
- *
- * http://refspecs.freestandards.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html */
-
- EXIT_CHDIR = 200,
- EXIT_NICE,
- EXIT_FDS,
- EXIT_EXEC,
- EXIT_MEMORY,
- EXIT_LIMITS,
- EXIT_OOM_ADJUST,
- EXIT_SIGNAL_MASK,
- EXIT_STDIN,
- EXIT_STDOUT,
- EXIT_CHROOT, /* 210 */
- EXIT_IOPRIO,
- EXIT_TIMERSLACK,
- EXIT_SECUREBITS,
- EXIT_SETSCHEDULER,
- EXIT_CPUAFFINITY,
- EXIT_GROUP,
- EXIT_USER,
- EXIT_CAPABILITIES,
- EXIT_CGROUP,
- EXIT_SETSID, /* 220 */
- EXIT_CONFIRM,
- EXIT_STDERR,
- EXIT_TCPWRAP,
- EXIT_PAM,
- EXIT_NETWORK,
- EXIT_NAMESPACE,
- EXIT_NO_NEW_PRIVILEGES,
- EXIT_SECCOMP
-} ExitStatus;
-
-typedef enum ExitStatusLevel {
- EXIT_STATUS_MINIMAL,
- EXIT_STATUS_SYSTEMD,
- EXIT_STATUS_LSB,
- EXIT_STATUS_FULL = EXIT_STATUS_LSB
-} ExitStatusLevel;
-
-typedef struct ExitStatusSet {
- Set *code;
- Set *signal;
-} ExitStatusSet;
-
-const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level);
-
-bool is_clean_exit(int code, int status, ExitStatusSet *success_status);
-bool is_clean_exit_lsb(int code, int status, ExitStatusSet *success_status);
diff --git a/src/udev/hashmap.c b/src/udev/hashmap.c
deleted file mode 100644
index dcfbb67228..0000000000
--- a/src/udev/hashmap.c
+++ /dev/null
@@ -1,835 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include "util.h"
-#include "hashmap.h"
-#include "macro.h"
-
-#define NBUCKETS 127
-
-struct hashmap_entry {
- const void *key;
- void *value;
- struct hashmap_entry *bucket_next, *bucket_previous;
- struct hashmap_entry *iterate_next, *iterate_previous;
-};
-
-struct Hashmap {
- hash_func_t hash_func;
- compare_func_t compare_func;
-
- struct hashmap_entry *iterate_list_head, *iterate_list_tail;
- unsigned n_entries;
-
- bool from_pool;
-};
-
-#define BY_HASH(h) ((struct hashmap_entry**) ((uint8_t*) (h) + ALIGN(sizeof(Hashmap))))
-
-struct pool {
- struct pool *next;
- unsigned n_tiles;
- unsigned n_used;
-};
-
-static struct pool *first_hashmap_pool = NULL;
-static void *first_hashmap_tile = NULL;
-
-static struct pool *first_entry_pool = NULL;
-static void *first_entry_tile = NULL;
-
-static void* allocate_tile(struct pool **first_pool, void **first_tile, size_t tile_size) {
- unsigned i;
-
- if (*first_tile) {
- void *r;
-
- r = *first_tile;
- *first_tile = * (void**) (*first_tile);
- return r;
- }
-
- if (_unlikely_(!*first_pool) || _unlikely_((*first_pool)->n_used >= (*first_pool)->n_tiles)) {
- unsigned n;
- size_t size;
- struct pool *p;
-
- n = *first_pool ? (*first_pool)->n_tiles : 0;
- n = MAX(512U, n * 2);
- size = PAGE_ALIGN(ALIGN(sizeof(struct pool)) + n*tile_size);
- n = (size - ALIGN(sizeof(struct pool))) / tile_size;
-
- p = malloc(size);
- if (!p)
- return NULL;
-
- p->next = *first_pool;
- p->n_tiles = n;
- p->n_used = 0;
-
- *first_pool = p;
- }
-
- i = (*first_pool)->n_used++;
-
- return ((uint8_t*) (*first_pool)) + ALIGN(sizeof(struct pool)) + i*tile_size;
-}
-
-static void deallocate_tile(void **first_tile, void *p) {
- * (void**) p = *first_tile;
- *first_tile = p;
-}
-
-#ifndef __OPTIMIZE__
-
-static void drop_pool(struct pool *p) {
- while (p) {
- struct pool *n;
- n = p->next;
- free(p);
- p = n;
- }
-}
-
-__attribute__((destructor)) static void cleanup_pool(void) {
- /* Be nice to valgrind */
-
- drop_pool(first_hashmap_pool);
- drop_pool(first_entry_pool);
-}
-
-#endif
-
-unsigned string_hash_func(const void *p) {
- unsigned hash = 5381;
- const signed char *c;
-
- /* DJB's hash function */
-
- for (c = p; *c; c++)
- hash = (hash << 5) + hash + (unsigned) *c;
-
- return hash;
-}
-
-int string_compare_func(const void *a, const void *b) {
- return strcmp(a, b);
-}
-
-unsigned trivial_hash_func(const void *p) {
- return PTR_TO_UINT(p);
-}
-
-int trivial_compare_func(const void *a, const void *b) {
- return a < b ? -1 : (a > b ? 1 : 0);
-}
-
-unsigned uint64_hash_func(const void *p) {
- uint64_t u;
-
- assert_cc(sizeof(uint64_t) == 2*sizeof(unsigned));
-
- u = *(const uint64_t*) p;
-
- return (unsigned) ((u >> 32) ^ u);
-}
-
-int uint64_compare_func(const void *_a, const void *_b) {
- uint64_t a, b;
-
- a = *(const uint64_t*) _a;
- b = *(const uint64_t*) _b;
-
- return a < b ? -1 : (a > b ? 1 : 0);
-}
-
-Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func) {
- bool b;
- Hashmap *h;
- size_t size;
-
- b = is_main_thread();
-
- size = ALIGN(sizeof(Hashmap)) + NBUCKETS * sizeof(struct hashmap_entry*);
-
- if (b) {
- h = allocate_tile(&first_hashmap_pool, &first_hashmap_tile, size);
- if (!h)
- return NULL;
-
- memset(h, 0, size);
- } else {
- h = malloc0(size);
-
- if (!h)
- return NULL;
- }
-
- h->hash_func = hash_func ? hash_func : trivial_hash_func;
- h->compare_func = compare_func ? compare_func : trivial_compare_func;
-
- h->n_entries = 0;
- h->iterate_list_head = h->iterate_list_tail = NULL;
-
- h->from_pool = b;
-
- return h;
-}
-
-int hashmap_ensure_allocated(Hashmap **h, hash_func_t hash_func, compare_func_t compare_func) {
- assert(h);
-
- if (*h)
- return 0;
-
- if (!(*h = hashmap_new(hash_func, compare_func)))
- return -ENOMEM;
-
- return 0;
-}
-
-static void link_entry(Hashmap *h, struct hashmap_entry *e, unsigned hash) {
- assert(h);
- assert(e);
-
- /* Insert into hash table */
- e->bucket_next = BY_HASH(h)[hash];
- e->bucket_previous = NULL;
- if (BY_HASH(h)[hash])
- BY_HASH(h)[hash]->bucket_previous = e;
- BY_HASH(h)[hash] = e;
-
- /* Insert into iteration list */
- e->iterate_previous = h->iterate_list_tail;
- e->iterate_next = NULL;
- if (h->iterate_list_tail) {
- assert(h->iterate_list_head);
- h->iterate_list_tail->iterate_next = e;
- } else {
- assert(!h->iterate_list_head);
- h->iterate_list_head = e;
- }
- h->iterate_list_tail = e;
-
- h->n_entries++;
- assert(h->n_entries >= 1);
-}
-
-static void unlink_entry(Hashmap *h, struct hashmap_entry *e, unsigned hash) {
- assert(h);
- assert(e);
-
- /* Remove from iteration list */
- if (e->iterate_next)
- e->iterate_next->iterate_previous = e->iterate_previous;
- else
- h->iterate_list_tail = e->iterate_previous;
-
- if (e->iterate_previous)
- e->iterate_previous->iterate_next = e->iterate_next;
- else
- h->iterate_list_head = e->iterate_next;
-
- /* Remove from hash table bucket list */
- if (e->bucket_next)
- e->bucket_next->bucket_previous = e->bucket_previous;
-
- if (e->bucket_previous)
- e->bucket_previous->bucket_next = e->bucket_next;
- else
- BY_HASH(h)[hash] = e->bucket_next;
-
- assert(h->n_entries >= 1);
- h->n_entries--;
-}
-
-static void remove_entry(Hashmap *h, struct hashmap_entry *e) {
- unsigned hash;
-
- assert(h);
- assert(e);
-
- hash = h->hash_func(e->key) % NBUCKETS;
-
- unlink_entry(h, e, hash);
-
- if (h->from_pool)
- deallocate_tile(&first_entry_tile, e);
- else
- free(e);
-}
-
-void hashmap_free(Hashmap*h) {
-
- /* Free the hashmap, but nothing in it */
-
- if (!h)
- return;
-
- hashmap_clear(h);
-
- if (h->from_pool)
- deallocate_tile(&first_hashmap_tile, h);
- else
- free(h);
-}
-
-void hashmap_free_free(Hashmap *h) {
-
- /* Free the hashmap and all data objects in it, but not the
- * keys */
-
- if (!h)
- return;
-
- hashmap_clear_free(h);
- hashmap_free(h);
-}
-
-void hashmap_clear(Hashmap *h) {
- if (!h)
- return;
-
- while (h->iterate_list_head)
- remove_entry(h, h->iterate_list_head);
-}
-
-void hashmap_clear_free(Hashmap *h) {
- void *p;
-
- if (!h)
- return;
-
- while ((p = hashmap_steal_first(h)))
- free(p);
-}
-
-static struct hashmap_entry *hash_scan(Hashmap *h, unsigned hash, const void *key) {
- struct hashmap_entry *e;
- assert(h);
- assert(hash < NBUCKETS);
-
- for (e = BY_HASH(h)[hash]; e; e = e->bucket_next)
- if (h->compare_func(e->key, key) == 0)
- return e;
-
- return NULL;
-}
-
-int hashmap_put(Hashmap *h, const void *key, void *value) {
- struct hashmap_entry *e;
- unsigned hash;
-
- assert(h);
-
- hash = h->hash_func(key) % NBUCKETS;
-
- e = hash_scan(h, hash, key);
- if (e) {
-
- if (e->value == value)
- return 0;
-
- return -EEXIST;
- }
-
- if (h->from_pool)
- e = allocate_tile(&first_entry_pool, &first_entry_tile, sizeof(struct hashmap_entry));
- else
- e = new(struct hashmap_entry, 1);
-
- if (!e)
- return -ENOMEM;
-
- e->key = key;
- e->value = value;
-
- link_entry(h, e, hash);
-
- return 1;
-}
-
-int hashmap_replace(Hashmap *h, const void *key, void *value) {
- struct hashmap_entry *e;
- unsigned hash;
-
- assert(h);
-
- hash = h->hash_func(key) % NBUCKETS;
- e = hash_scan(h, hash, key);
- if (e) {
- e->key = key;
- e->value = value;
- return 0;
- }
-
- return hashmap_put(h, key, value);
-}
-
-int hashmap_update(Hashmap *h, const void *key, void *value) {
- struct hashmap_entry *e;
- unsigned hash;
-
- assert(h);
-
- hash = h->hash_func(key) % NBUCKETS;
- e = hash_scan(h, hash, key);
- if (!e)
- return -ENOENT;
-
- e->value = value;
- return 0;
-}
-
-void* hashmap_get(Hashmap *h, const void *key) {
- unsigned hash;
- struct hashmap_entry *e;
-
- if (!h)
- return NULL;
-
- hash = h->hash_func(key) % NBUCKETS;
- e = hash_scan(h, hash, key);
- if (!e)
- return NULL;
-
- return e->value;
-}
-
-void* hashmap_get2(Hashmap *h, const void *key, void **key2) {
- unsigned hash;
- struct hashmap_entry *e;
-
- if (!h)
- return NULL;
-
- hash = h->hash_func(key) % NBUCKETS;
- e = hash_scan(h, hash, key);
- if (!e)
- return NULL;
-
- if (key2)
- *key2 = (void*) e->key;
-
- return e->value;
-}
-
-bool hashmap_contains(Hashmap *h, const void *key) {
- unsigned hash;
-
- if (!h)
- return false;
-
- hash = h->hash_func(key) % NBUCKETS;
-
- if (!hash_scan(h, hash, key))
- return false;
-
- return true;
-}
-
-void* hashmap_remove(Hashmap *h, const void *key) {
- struct hashmap_entry *e;
- unsigned hash;
- void *data;
-
- if (!h)
- return NULL;
-
- hash = h->hash_func(key) % NBUCKETS;
-
- if (!(e = hash_scan(h, hash, key)))
- return NULL;
-
- data = e->value;
- remove_entry(h, e);
-
- return data;
-}
-
-int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value) {
- struct hashmap_entry *e;
- unsigned old_hash, new_hash;
-
- if (!h)
- return -ENOENT;
-
- old_hash = h->hash_func(old_key) % NBUCKETS;
- if (!(e = hash_scan(h, old_hash, old_key)))
- return -ENOENT;
-
- new_hash = h->hash_func(new_key) % NBUCKETS;
- if (hash_scan(h, new_hash, new_key))
- return -EEXIST;
-
- unlink_entry(h, e, old_hash);
-
- e->key = new_key;
- e->value = value;
-
- link_entry(h, e, new_hash);
-
- return 0;
-}
-
-int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value) {
- struct hashmap_entry *e, *k;
- unsigned old_hash, new_hash;
-
- if (!h)
- return -ENOENT;
-
- old_hash = h->hash_func(old_key) % NBUCKETS;
- if (!(e = hash_scan(h, old_hash, old_key)))
- return -ENOENT;
-
- new_hash = h->hash_func(new_key) % NBUCKETS;
-
- if ((k = hash_scan(h, new_hash, new_key)))
- if (e != k)
- remove_entry(h, k);
-
- unlink_entry(h, e, old_hash);
-
- e->key = new_key;
- e->value = value;
-
- link_entry(h, e, new_hash);
-
- return 0;
-}
-
-void* hashmap_remove_value(Hashmap *h, const void *key, void *value) {
- struct hashmap_entry *e;
- unsigned hash;
-
- if (!h)
- return NULL;
-
- hash = h->hash_func(key) % NBUCKETS;
-
- if (!(e = hash_scan(h, hash, key)))
- return NULL;
-
- if (e->value != value)
- return NULL;
-
- remove_entry(h, e);
-
- return value;
-}
-
-void *hashmap_iterate(Hashmap *h, Iterator *i, const void **key) {
- struct hashmap_entry *e;
-
- assert(i);
-
- if (!h)
- goto at_end;
-
- if (*i == ITERATOR_LAST)
- goto at_end;
-
- if (*i == ITERATOR_FIRST && !h->iterate_list_head)
- goto at_end;
-
- e = *i == ITERATOR_FIRST ? h->iterate_list_head : (struct hashmap_entry*) *i;
-
- if (e->iterate_next)
- *i = (Iterator) e->iterate_next;
- else
- *i = ITERATOR_LAST;
-
- if (key)
- *key = e->key;
-
- return e->value;
-
-at_end:
- *i = ITERATOR_LAST;
-
- if (key)
- *key = NULL;
-
- return NULL;
-}
-
-void *hashmap_iterate_backwards(Hashmap *h, Iterator *i, const void **key) {
- struct hashmap_entry *e;
-
- assert(i);
-
- if (!h)
- goto at_beginning;
-
- if (*i == ITERATOR_FIRST)
- goto at_beginning;
-
- if (*i == ITERATOR_LAST && !h->iterate_list_tail)
- goto at_beginning;
-
- e = *i == ITERATOR_LAST ? h->iterate_list_tail : (struct hashmap_entry*) *i;
-
- if (e->iterate_previous)
- *i = (Iterator) e->iterate_previous;
- else
- *i = ITERATOR_FIRST;
-
- if (key)
- *key = e->key;
-
- return e->value;
-
-at_beginning:
- *i = ITERATOR_FIRST;
-
- if (key)
- *key = NULL;
-
- return NULL;
-}
-
-void *hashmap_iterate_skip(Hashmap *h, const void *key, Iterator *i) {
- unsigned hash;
- struct hashmap_entry *e;
-
- if (!h)
- return NULL;
-
- hash = h->hash_func(key) % NBUCKETS;
-
- if (!(e = hash_scan(h, hash, key)))
- return NULL;
-
- *i = (Iterator) e;
-
- return e->value;
-}
-
-void* hashmap_first(Hashmap *h) {
-
- if (!h)
- return NULL;
-
- if (!h->iterate_list_head)
- return NULL;
-
- return h->iterate_list_head->value;
-}
-
-void* hashmap_first_key(Hashmap *h) {
-
- if (!h)
- return NULL;
-
- if (!h->iterate_list_head)
- return NULL;
-
- return (void*) h->iterate_list_head->key;
-}
-
-void* hashmap_last(Hashmap *h) {
-
- if (!h)
- return NULL;
-
- if (!h->iterate_list_tail)
- return NULL;
-
- return h->iterate_list_tail->value;
-}
-
-void* hashmap_steal_first(Hashmap *h) {
- void *data;
-
- if (!h)
- return NULL;
-
- if (!h->iterate_list_head)
- return NULL;
-
- data = h->iterate_list_head->value;
- remove_entry(h, h->iterate_list_head);
-
- return data;
-}
-
-void* hashmap_steal_first_key(Hashmap *h) {
- void *key;
-
- if (!h)
- return NULL;
-
- if (!h->iterate_list_head)
- return NULL;
-
- key = (void*) h->iterate_list_head->key;
- remove_entry(h, h->iterate_list_head);
-
- return key;
-}
-
-unsigned hashmap_size(Hashmap *h) {
-
- if (!h)
- return 0;
-
- return h->n_entries;
-}
-
-bool hashmap_isempty(Hashmap *h) {
-
- if (!h)
- return true;
-
- return h->n_entries == 0;
-}
-
-int hashmap_merge(Hashmap *h, Hashmap *other) {
- struct hashmap_entry *e;
-
- assert(h);
-
- if (!other)
- return 0;
-
- for (e = other->iterate_list_head; e; e = e->iterate_next) {
- int r;
-
- if ((r = hashmap_put(h, e->key, e->value)) < 0)
- if (r != -EEXIST)
- return r;
- }
-
- return 0;
-}
-
-void hashmap_move(Hashmap *h, Hashmap *other) {
- struct hashmap_entry *e, *n;
-
- assert(h);
-
- /* The same as hashmap_merge(), but every new item from other
- * is moved to h. This function is guaranteed to succeed. */
-
- if (!other)
- return;
-
- for (e = other->iterate_list_head; e; e = n) {
- unsigned h_hash, other_hash;
-
- n = e->iterate_next;
-
- h_hash = h->hash_func(e->key) % NBUCKETS;
-
- if (hash_scan(h, h_hash, e->key))
- continue;
-
- other_hash = other->hash_func(e->key) % NBUCKETS;
-
- unlink_entry(other, e, other_hash);
- link_entry(h, e, h_hash);
- }
-}
-
-int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key) {
- unsigned h_hash, other_hash;
- struct hashmap_entry *e;
-
- if (!other)
- return 0;
-
- assert(h);
-
- h_hash = h->hash_func(key) % NBUCKETS;
- if (hash_scan(h, h_hash, key))
- return -EEXIST;
-
- other_hash = other->hash_func(key) % NBUCKETS;
- if (!(e = hash_scan(other, other_hash, key)))
- return -ENOENT;
-
- unlink_entry(other, e, other_hash);
- link_entry(h, e, h_hash);
-
- return 0;
-}
-
-Hashmap *hashmap_copy(Hashmap *h) {
- Hashmap *copy;
-
- assert(h);
-
- if (!(copy = hashmap_new(h->hash_func, h->compare_func)))
- return NULL;
-
- if (hashmap_merge(copy, h) < 0) {
- hashmap_free(copy);
- return NULL;
- }
-
- return copy;
-}
-
-char **hashmap_get_strv(Hashmap *h) {
- char **sv;
- Iterator it;
- char *item;
- int n;
-
- sv = new(char*, h->n_entries+1);
- if (!sv)
- return NULL;
-
- n = 0;
- HASHMAP_FOREACH(item, h, it)
- sv[n++] = item;
- sv[n] = NULL;
-
- return sv;
-}
-
-void *hashmap_next(Hashmap *h, const void *key) {
- unsigned hash;
- struct hashmap_entry *e;
-
- assert(h);
- assert(key);
-
- if (!h)
- return NULL;
-
- hash = h->hash_func(key) % NBUCKETS;
- e = hash_scan(h, hash, key);
- if (!e)
- return NULL;
-
- e = e->iterate_next;
- if (!e)
- return NULL;
-
- return e->value;
-}
diff --git a/src/udev/hashmap.h b/src/udev/hashmap.h
deleted file mode 100644
index 6fd71cf519..0000000000
--- a/src/udev/hashmap.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-
-/* Pretty straightforward hash table implementation. As a minor
- * optimization a NULL hashmap object will be treated as empty hashmap
- * for all read operations. That way it is not necessary to
- * instantiate an object for each Hashmap use. */
-
-typedef struct Hashmap Hashmap;
-typedef struct _IteratorStruct _IteratorStruct;
-typedef _IteratorStruct* Iterator;
-
-#define ITERATOR_FIRST ((Iterator) 0)
-#define ITERATOR_LAST ((Iterator) -1)
-
-typedef unsigned (*hash_func_t)(const void *p);
-typedef int (*compare_func_t)(const void *a, const void *b);
-
-unsigned string_hash_func(const void *p);
-int string_compare_func(const void *a, const void *b);
-
-unsigned trivial_hash_func(const void *p);
-int trivial_compare_func(const void *a, const void *b);
-
-unsigned uint64_hash_func(const void *p);
-int uint64_compare_func(const void *a, const void *b);
-
-Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func);
-void hashmap_free(Hashmap *h);
-void hashmap_free_free(Hashmap *h);
-Hashmap *hashmap_copy(Hashmap *h);
-int hashmap_ensure_allocated(Hashmap **h, hash_func_t hash_func, compare_func_t compare_func);
-
-int hashmap_put(Hashmap *h, const void *key, void *value);
-int hashmap_update(Hashmap *h, const void *key, void *value);
-int hashmap_replace(Hashmap *h, const void *key, void *value);
-void* hashmap_get(Hashmap *h, const void *key);
-void* hashmap_get2(Hashmap *h, const void *key, void **rkey);
-bool hashmap_contains(Hashmap *h, const void *key);
-void* hashmap_remove(Hashmap *h, const void *key);
-void* hashmap_remove_value(Hashmap *h, const void *key, void *value);
-int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value);
-int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value);
-
-int hashmap_merge(Hashmap *h, Hashmap *other);
-void hashmap_move(Hashmap *h, Hashmap *other);
-int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key);
-
-unsigned hashmap_size(Hashmap *h);
-bool hashmap_isempty(Hashmap *h);
-
-void *hashmap_iterate(Hashmap *h, Iterator *i, const void **key);
-void *hashmap_iterate_backwards(Hashmap *h, Iterator *i, const void **key);
-void *hashmap_iterate_skip(Hashmap *h, const void *key, Iterator *i);
-
-void hashmap_clear(Hashmap *h);
-void hashmap_clear_free(Hashmap *h);
-
-void *hashmap_steal_first(Hashmap *h);
-void *hashmap_steal_first_key(Hashmap *h);
-void* hashmap_first(Hashmap *h);
-void* hashmap_first_key(Hashmap *h);
-void* hashmap_last(Hashmap *h);
-
-void *hashmap_next(Hashmap *h, const void *key);
-
-char **hashmap_get_strv(Hashmap *h);
-
-#define HASHMAP_FOREACH(e, h, i) \
- for ((i) = ITERATOR_FIRST, (e) = hashmap_iterate((h), &(i), NULL); (e); (e) = hashmap_iterate((h), &(i), NULL))
-
-#define HASHMAP_FOREACH_KEY(e, k, h, i) \
- for ((i) = ITERATOR_FIRST, (e) = hashmap_iterate((h), &(i), (const void**) &(k)); (e); (e) = hashmap_iterate((h), &(i), (const void**) &(k)))
-
-#define HASHMAP_FOREACH_BACKWARDS(e, h, i) \
- for ((i) = ITERATOR_LAST, (e) = hashmap_iterate_backwards((h), &(i), NULL); (e); (e) = hashmap_iterate_backwards((h), &(i), NULL))
diff --git a/src/udev/ioprio.h b/src/udev/ioprio.h
deleted file mode 100644
index 9800fc2553..0000000000
--- a/src/udev/ioprio.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef IOPRIO_H
-#define IOPRIO_H
-
-/* This is minimal version of Linux' linux/ioprio.h header file, which
- * is licensed GPL2 */
-
-#include <unistd.h>
-#include <sys/syscall.h>
-
-/*
- * Gives us 8 prio classes with 13-bits of data for each class
- */
-#define IOPRIO_BITS (16)
-#define IOPRIO_CLASS_SHIFT (13)
-#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
-
-#define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT)
-#define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK)
-#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data)
-
-#define ioprio_valid(mask) (IOPRIO_PRIO_CLASS((mask)) != IOPRIO_CLASS_NONE)
-
-/*
- * These are the io priority groups as implemented by CFQ. RT is the realtime
- * class, it always gets premium service. BE is the best-effort scheduling
- * class, the default for any process. IDLE is the idle scheduling class, it
- * is only served when no one else is using the disk.
- */
-enum {
- IOPRIO_CLASS_NONE,
- IOPRIO_CLASS_RT,
- IOPRIO_CLASS_BE,
- IOPRIO_CLASS_IDLE,
-};
-
-/*
- * 8 best effort priority levels are supported
- */
-#define IOPRIO_BE_NR (8)
-
-enum {
- IOPRIO_WHO_PROCESS = 1,
- IOPRIO_WHO_PGRP,
- IOPRIO_WHO_USER,
-};
-
-static inline int ioprio_set(int which, int who, int ioprio)
-{
- return syscall(__NR_ioprio_set, which, who, ioprio);
-}
-
-static inline int ioprio_get(int which, int who)
-{
- return syscall(__NR_ioprio_get, which, who);
-}
-
-#endif
diff --git a/src/udev/log.c b/src/udev/log.c
deleted file mode 100644
index 5c07b626c2..0000000000
--- a/src/udev/log.c
+++ /dev/null
@@ -1,865 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <stddef.h>
-#include <printf.h>
-
-#include "log.h"
-#include "util.h"
-#include "missing.h"
-#include "macro.h"
-#include "socket-util.h"
-
-#define SNDBUF_SIZE (8*1024*1024)
-
-static LogTarget log_target = LOG_TARGET_CONSOLE;
-static int log_max_level = LOG_INFO;
-static int log_facility = LOG_DAEMON;
-
-static int console_fd = STDERR_FILENO;
-static int syslog_fd = -1;
-static int kmsg_fd = -1;
-static int journal_fd = -1;
-
-static bool syslog_is_stream = false;
-
-static bool show_color = false;
-static bool show_location = false;
-
-/* Akin to glibc's __abort_msg; which is private and we hence cannot
- * use here. */
-static char *log_abort_msg = NULL;
-
-void log_close_console(void) {
-
- if (console_fd < 0)
- return;
-
- if (getpid() == 1) {
- if (console_fd >= 3)
- close_nointr_nofail(console_fd);
-
- console_fd = -1;
- }
-}
-
-static int log_open_console(void) {
-
- if (console_fd >= 0)
- return 0;
-
- if (getpid() == 1) {
- console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
- if (console_fd < 0)
- return console_fd;
- } else
- console_fd = STDERR_FILENO;
-
- return 0;
-}
-
-void log_close_kmsg(void) {
-
- if (kmsg_fd < 0)
- return;
-
- close_nointr_nofail(kmsg_fd);
- kmsg_fd = -1;
-}
-
-static int log_open_kmsg(void) {
-
- if (kmsg_fd >= 0)
- return 0;
-
- kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
- if (kmsg_fd < 0)
- return -errno;
-
- return 0;
-}
-
-void log_close_syslog(void) {
-
- if (syslog_fd < 0)
- return;
-
- close_nointr_nofail(syslog_fd);
- syslog_fd = -1;
-}
-
-static int create_log_socket(int type) {
- int fd;
-
- /* All output to the syslog/journal fds we do asynchronously,
- * and if the buffers are full we just drop the messages */
-
- fd = socket(AF_UNIX, type|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (fd < 0)
- return -errno;
-
- fd_inc_sndbuf(fd, SNDBUF_SIZE);
-
- return fd;
-}
-
-static int log_open_syslog(void) {
- union sockaddr_union sa;
- int r;
-
- if (syslog_fd >= 0)
- return 0;
-
- zero(sa);
- sa.un.sun_family = AF_UNIX;
- strncpy(sa.un.sun_path, "/dev/log", sizeof(sa.un.sun_path));
-
- syslog_fd = create_log_socket(SOCK_DGRAM);
- if (syslog_fd < 0) {
- r = syslog_fd;
- goto fail;
- }
-
- if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
- close_nointr_nofail(syslog_fd);
-
- /* Some legacy syslog systems still use stream
- * sockets. They really shouldn't. But what can we
- * do... */
- syslog_fd = create_log_socket(SOCK_STREAM);
- if (syslog_fd < 0) {
- r = syslog_fd;
- goto fail;
- }
-
- if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
- r = -errno;
- goto fail;
- }
-
- syslog_is_stream = true;
- } else
- syslog_is_stream = false;
-
- return 0;
-
-fail:
- log_close_syslog();
- return r;
-}
-
-void log_close_journal(void) {
-
- if (journal_fd < 0)
- return;
-
- close_nointr_nofail(journal_fd);
- journal_fd = -1;
-}
-
-static int log_open_journal(void) {
- union sockaddr_union sa;
- int r;
-
- if (journal_fd >= 0)
- return 0;
-
- journal_fd = create_log_socket(SOCK_DGRAM);
- if (journal_fd < 0) {
- r = journal_fd;
- goto fail;
- }
-
- zero(sa);
- sa.un.sun_family = AF_UNIX;
- strncpy(sa.un.sun_path, "/run/systemd/journal/socket", sizeof(sa.un.sun_path));
-
- if (connect(journal_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
- r = -errno;
- goto fail;
- }
-
- return 0;
-
-fail:
- log_close_journal();
- return r;
-}
-
-int log_open(void) {
- int r;
-
- /* If we don't use the console we close it here, to not get
- * killed by SAK. If we don't use syslog we close it here so
- * that we are not confused by somebody deleting the socket in
- * the fs. If we don't use /dev/kmsg we still keep it open,
- * because there is no reason to close it. */
-
- if (log_target == LOG_TARGET_NULL) {
- log_close_journal();
- log_close_syslog();
- log_close_console();
- return 0;
- }
-
- if ((log_target != LOG_TARGET_AUTO && log_target != LOG_TARGET_SAFE) ||
- getpid() == 1 ||
- isatty(STDERR_FILENO) <= 0) {
-
- if (log_target == LOG_TARGET_AUTO ||
- log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
- log_target == LOG_TARGET_JOURNAL) {
- r = log_open_journal();
- if (r >= 0) {
- log_close_syslog();
- log_close_console();
- return r;
- }
- }
-
- if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
- log_target == LOG_TARGET_SYSLOG) {
- r = log_open_syslog();
- if (r >= 0) {
- log_close_journal();
- log_close_console();
- return r;
- }
- }
-
- if (log_target == LOG_TARGET_AUTO ||
- log_target == LOG_TARGET_SAFE ||
- 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) {
- log_close_journal();
- log_close_syslog();
- log_close_console();
- return r;
- }
- }
- }
-
- log_close_journal();
- log_close_syslog();
-
- /* Get the real /dev/console if we are PID=1, hence reopen */
- log_close_console();
- return log_open_console();
-}
-
-void log_set_target(LogTarget target) {
- assert(target >= 0);
- assert(target < _LOG_TARGET_MAX);
-
- log_target = target;
-}
-
-void log_close(void) {
- log_close_journal();
- log_close_syslog();
- log_close_kmsg();
- log_close_console();
-}
-
-void log_forget_fds(void) {
- console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
-}
-
-void log_set_max_level(int level) {
- assert((level & LOG_PRIMASK) == level);
-
- log_max_level = level;
-}
-
-void log_set_facility(int facility) {
- log_facility = facility;
-}
-
-static int write_to_console(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *buffer) {
-
- char location[64];
- struct iovec iovec[5];
- unsigned n = 0;
- bool highlight;
-
- if (console_fd < 0)
- return 0;
-
- highlight = LOG_PRI(level) <= LOG_ERR && show_color;
-
- zero(iovec);
-
- if (show_location) {
- snprintf(location, sizeof(location), "(%s:%u) ", file, line);
- char_array_0(location);
- IOVEC_SET_STRING(iovec[n++], location);
- }
-
- if (highlight)
- IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_RED_ON);
- IOVEC_SET_STRING(iovec[n++], buffer);
- if (highlight)
- IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_OFF);
- IOVEC_SET_STRING(iovec[n++], "\n");
-
- if (writev(console_fd, iovec, n) < 0)
- return -errno;
-
- return 1;
-}
-
-static int write_to_syslog(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *buffer) {
-
- char header_priority[16], header_time[64], header_pid[16];
- struct iovec iovec[5];
- struct msghdr msghdr;
- time_t t;
- struct tm *tm;
-
- if (syslog_fd < 0)
- return 0;
-
- snprintf(header_priority, sizeof(header_priority), "<%i>", level);
- char_array_0(header_priority);
-
- t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
- if (!(tm = localtime(&t)))
- return -EINVAL;
-
- if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
- return -EINVAL;
-
- snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) getpid());
- char_array_0(header_pid);
-
- zero(iovec);
- IOVEC_SET_STRING(iovec[0], header_priority);
- IOVEC_SET_STRING(iovec[1], header_time);
- IOVEC_SET_STRING(iovec[2], program_invocation_short_name);
- IOVEC_SET_STRING(iovec[3], header_pid);
- IOVEC_SET_STRING(iovec[4], buffer);
-
- /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
- if (syslog_is_stream)
- iovec[4].iov_len++;
-
- zero(msghdr);
- msghdr.msg_iov = iovec;
- msghdr.msg_iovlen = ELEMENTSOF(iovec);
-
- for (;;) {
- ssize_t n;
-
- n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
- if (n < 0)
- return -errno;
-
- if (!syslog_is_stream ||
- (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
- break;
-
- IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
- }
-
- return 1;
-}
-
-static int write_to_kmsg(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *buffer) {
-
- char header_priority[16], header_pid[16];
- struct iovec iovec[5];
-
- if (kmsg_fd < 0)
- return 0;
-
- snprintf(header_priority, sizeof(header_priority), "<%i>", level);
- char_array_0(header_priority);
-
- snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) getpid());
- char_array_0(header_pid);
-
- zero(iovec);
- IOVEC_SET_STRING(iovec[0], header_priority);
- IOVEC_SET_STRING(iovec[1], program_invocation_short_name);
- IOVEC_SET_STRING(iovec[2], header_pid);
- IOVEC_SET_STRING(iovec[3], buffer);
- IOVEC_SET_STRING(iovec[4], "\n");
-
- if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
- return -errno;
-
- return 1;
-}
-
-static int write_to_journal(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *buffer) {
-
- char header[LINE_MAX];
- struct iovec iovec[3];
- struct msghdr mh;
-
- if (journal_fd < 0)
- return 0;
-
- snprintf(header, sizeof(header),
- "PRIORITY=%i\n"
- "SYSLOG_FACILITY=%i\n"
- "CODE_FILE=%s\n"
- "CODE_LINE=%i\n"
- "CODE_FUNCTION=%s\n"
- "SYSLOG_IDENTIFIER=%s\n"
- "MESSAGE=",
- LOG_PRI(level),
- LOG_FAC(level),
- file,
- line,
- func,
- program_invocation_short_name);
-
- char_array_0(header);
-
- zero(iovec);
- IOVEC_SET_STRING(iovec[0], header);
- IOVEC_SET_STRING(iovec[1], buffer);
- IOVEC_SET_STRING(iovec[2], "\n");
-
- zero(mh);
- mh.msg_iov = iovec;
- mh.msg_iovlen = ELEMENTSOF(iovec);
-
- if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
- return -errno;
-
- return 1;
-}
-
-static int log_dispatch(
- int level,
- const char*file,
- int line,
- const char *func,
- char *buffer) {
-
- int r = 0;
-
- if (log_target == LOG_TARGET_NULL)
- return 0;
-
- /* Patch in LOG_DAEMON facility if necessary */
- if ((level & LOG_FACMASK) == 0)
- level = log_facility | LOG_PRI(level);
-
- do {
- char *e;
- int k = 0;
-
- buffer += strspn(buffer, NEWLINE);
-
- if (buffer[0] == 0)
- break;
-
- if ((e = strpbrk(buffer, NEWLINE)))
- *(e++) = 0;
-
- if (log_target == LOG_TARGET_AUTO ||
- log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
- log_target == LOG_TARGET_JOURNAL) {
-
- k = write_to_journal(level, file, line, func, buffer);
- if (k < 0) {
- if (k != -EAGAIN)
- log_close_journal();
- log_open_kmsg();
- } else if (k > 0)
- r++;
- }
-
- if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
- log_target == LOG_TARGET_SYSLOG) {
-
- k = write_to_syslog(level, file, line, func, buffer);
- if (k < 0) {
- if (k != -EAGAIN)
- log_close_syslog();
- log_open_kmsg();
- } else if (k > 0)
- r++;
- }
-
- if (k <= 0 &&
- (log_target == LOG_TARGET_AUTO ||
- log_target == LOG_TARGET_SAFE ||
- log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
- log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
- log_target == LOG_TARGET_KMSG)) {
-
- k = write_to_kmsg(level, file, line, func, buffer);
- if (k < 0) {
- log_close_kmsg();
- log_open_console();
- } else if (k > 0)
- r++;
- }
-
- if (k <= 0) {
- k = write_to_console(level, file, line, func, buffer);
- if (k < 0)
- return k;
- }
-
- buffer = e;
- } while (buffer);
-
- return r;
-}
-
-int log_dump_internal(
- int level,
- const char*file,
- int line,
- const char *func,
- char *buffer) {
-
- int saved_errno, r;
-
- /* This modifies the buffer... */
-
- if (_likely_(LOG_PRI(level) > log_max_level))
- return 0;
-
- saved_errno = errno;
- r = log_dispatch(level, file, line, func, buffer);
- errno = saved_errno;
-
- return r;
-}
-
-int log_metav(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *format,
- va_list ap) {
-
- char buffer[LINE_MAX];
- int saved_errno, r;
-
- if (_likely_(LOG_PRI(level) > log_max_level))
- return 0;
-
- saved_errno = errno;
- vsnprintf(buffer, sizeof(buffer), format, ap);
- char_array_0(buffer);
-
- r = log_dispatch(level, file, line, func, buffer);
- errno = saved_errno;
-
- return r;
-}
-
-int log_meta(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *format, ...) {
-
- int r;
- va_list ap;
-
- va_start(ap, format);
- r = log_metav(level, file, line, func, format, ap);
- va_end(ap);
-
- return r;
-}
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wformat-nonliteral"
-_noreturn_ static void log_assert(const char *text, const char *file, int line, const char *func, const char *format) {
- static char buffer[LINE_MAX];
-
- snprintf(buffer, sizeof(buffer), format, text, file, line, func);
-
- char_array_0(buffer);
- log_abort_msg = buffer;
-
- log_dispatch(LOG_CRIT, file, line, func, buffer);
- abort();
-}
-#pragma GCC diagnostic pop
-
-_noreturn_ void log_assert_failed(const char *text, const char *file, int line, const char *func) {
- log_assert(text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
-}
-
-_noreturn_ void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) {
- log_assert(text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
-}
-
-int log_oom_internal(const char *file, int line, const char *func) {
- log_meta(LOG_ERR, file, line, func, "Out of memory.");
- return -ENOMEM;
-}
-
-int log_struct_internal(
- int level,
- const char *file,
- int line,
- const char *func,
- const char *format, ...) {
-
- int saved_errno;
- va_list ap;
- int r;
-
- if (_likely_(LOG_PRI(level) > log_max_level))
- return 0;
-
- if (log_target == LOG_TARGET_NULL)
- return 0;
-
- if ((level & LOG_FACMASK) == 0)
- level = log_facility | LOG_PRI(level);
-
- saved_errno = errno;
-
- if ((log_target == LOG_TARGET_AUTO ||
- log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
- log_target == LOG_TARGET_JOURNAL) &&
- journal_fd >= 0) {
-
- char header[LINE_MAX];
- struct iovec iovec[17];
- unsigned n = 0, i;
- struct msghdr mh;
- const char nl = '\n';
-
- /* If the journal is available do structured logging */
-
- snprintf(header, sizeof(header),
- "PRIORITY=%i\n"
- "SYSLOG_FACILITY=%i\n"
- "CODE_FILE=%s\n"
- "CODE_LINE=%i\n"
- "CODE_FUNCTION=%s\n"
- "SYSLOG_IDENTIFIER=%s\n",
- LOG_PRI(level),
- LOG_FAC(level),
- file,
- line,
- func,
- program_invocation_short_name);
- char_array_0(header);
-
- zero(iovec);
- IOVEC_SET_STRING(iovec[n++], header);
-
- va_start(ap, format);
- while (format && n + 1 < ELEMENTSOF(iovec)) {
- char *buf;
- va_list aq;
-
- /* We need to copy the va_list structure,
- * since vasprintf() leaves it afterwards at
- * an undefined location */
-
- va_copy(aq, ap);
- if (vasprintf(&buf, format, aq) < 0) {
- va_end(aq);
- r = -ENOMEM;
- goto finish;
- }
- va_end(aq);
-
- /* Now, jump enough ahead, so that we point to
- * the next format string */
- VA_FORMAT_ADVANCE(format, ap);
-
- IOVEC_SET_STRING(iovec[n++], buf);
-
- iovec[n].iov_base = (char*) &nl;
- iovec[n].iov_len = 1;
- n++;
-
- format = va_arg(ap, char *);
- }
-
- zero(mh);
- mh.msg_iov = iovec;
- mh.msg_iovlen = n;
-
- if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
- r = -errno;
- else
- r = 1;
-
- finish:
- va_end(ap);
- for (i = 1; i < n; i += 2)
- free(iovec[i].iov_base);
-
- } else {
- char buf[LINE_MAX];
- bool found = false;
-
- /* Fallback if journal logging is not available */
-
- va_start(ap, format);
- while (format) {
- va_list aq;
-
- va_copy(aq, ap);
- vsnprintf(buf, sizeof(buf), format, aq);
- va_end(aq);
- char_array_0(buf);
-
- if (startswith(buf, "MESSAGE=")) {
- found = true;
- break;
- }
-
- VA_FORMAT_ADVANCE(format, ap);
-
- format = va_arg(ap, char *);
- }
- va_end(ap);
-
- if (found)
- r = log_dispatch(level, file, line, func, buf + 8);
- else
- r = -EINVAL;
- }
-
- errno = saved_errno;
- return r;
-}
-
-int log_set_target_from_string(const char *e) {
- LogTarget t;
-
- t = log_target_from_string(e);
- if (t < 0)
- return -EINVAL;
-
- log_set_target(t);
- return 0;
-}
-
-int log_set_max_level_from_string(const char *e) {
- int t;
-
- t = log_level_from_string(e);
- if (t < 0)
- return t;
-
- log_set_max_level(t);
- return 0;
-}
-
-LogTarget log_get_target(void) {
- return log_target;
-}
-
-int log_get_max_level(void) {
- return log_max_level;
-}
-
-void log_show_color(bool b) {
- show_color = b;
-}
-
-void log_show_location(bool b) {
- show_location = b;
-}
-
-int log_show_color_from_string(const char *e) {
- int t;
-
- t = parse_boolean(e);
- if (t < 0)
- return t;
-
- log_show_color(t);
- return 0;
-}
-
-int log_show_location_from_string(const char *e) {
- int t;
-
- t = parse_boolean(e);
- if (t < 0)
- return t;
-
- log_show_location(t);
- return 0;
-}
-
-bool log_on_console(void) {
- if (log_target == LOG_TARGET_CONSOLE)
- return true;
-
- return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
-}
-
-static const char *const log_target_table[] = {
- [LOG_TARGET_CONSOLE] = "console",
- [LOG_TARGET_KMSG] = "kmsg",
- [LOG_TARGET_JOURNAL] = "journal",
- [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
- [LOG_TARGET_SYSLOG] = "syslog",
- [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
- [LOG_TARGET_AUTO] = "auto",
- [LOG_TARGET_SAFE] = "safe",
- [LOG_TARGET_NULL] = "null"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
diff --git a/src/udev/log.h b/src/udev/log.h
deleted file mode 100644
index fd2285cb61..0000000000
--- a/src/udev/log.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <syslog.h>
-#include <stdbool.h>
-#include <stdarg.h>
-#include <errno.h>
-
-#include "macro.h"
-
-typedef enum LogTarget{
- LOG_TARGET_CONSOLE,
- LOG_TARGET_KMSG,
- LOG_TARGET_JOURNAL,
- LOG_TARGET_JOURNAL_OR_KMSG,
- LOG_TARGET_SYSLOG,
- LOG_TARGET_SYSLOG_OR_KMSG,
- LOG_TARGET_AUTO, /* console if stderr is tty, JOURNAL_OR_KMSG otherwise */
- LOG_TARGET_SAFE, /* console if stderr is tty, KMSG otherwise */
- LOG_TARGET_NULL,
- _LOG_TARGET_MAX,
- _LOG_TARGET_INVALID = -1
-} LogTarget;
-
-void log_set_target(LogTarget target);
-void log_set_max_level(int level);
-void log_set_facility(int facility);
-
-int log_set_target_from_string(const char *e);
-int log_set_max_level_from_string(const char *e);
-
-void log_show_color(bool b);
-void log_show_location(bool b);
-
-int log_show_color_from_string(const char *e);
-int log_show_location_from_string(const char *e);
-
-LogTarget log_get_target(void);
-int log_get_max_level(void);
-
-int log_open(void);
-void log_close(void);
-void log_forget_fds(void);
-
-void log_close_syslog(void);
-void log_close_journal(void);
-void log_close_kmsg(void);
-void log_close_console(void);
-
-int log_meta(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *format, ...) _printf_attr_(5,6);
-
-int log_metav(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *format,
- va_list ap);
-
-int log_struct_internal(
- int level,
- const char *file,
- int line,
- const char *func,
- const char *format, ...) _sentinel_;
-
-int log_oom_internal(
- const char *file,
- int line,
- const char *func);
-
-/* This modifies the buffer passed! */
-int log_dump_internal(
- int level,
- const char*file,
- int line,
- const char *func,
- char *buffer);
-
-_noreturn_ void log_assert_failed(
- const char *text,
- const char *file,
- int line,
- const char *func);
-
-_noreturn_ void log_assert_failed_unreachable(
- const char *text,
- const char *file,
- int line,
- const char *func);
-
-#define log_full(level, ...) log_meta(level, __FILE__, __LINE__, __func__, __VA_ARGS__)
-
-#define log_debug(...) log_meta(LOG_DEBUG, __FILE__, __LINE__, __func__, __VA_ARGS__)
-#define log_info(...) log_meta(LOG_INFO, __FILE__, __LINE__, __func__, __VA_ARGS__)
-#define log_notice(...) log_meta(LOG_NOTICE, __FILE__, __LINE__, __func__, __VA_ARGS__)
-#define log_warning(...) log_meta(LOG_WARNING, __FILE__, __LINE__, __func__, __VA_ARGS__)
-#define log_error(...) log_meta(LOG_ERR, __FILE__, __LINE__, __func__, __VA_ARGS__)
-
-#define log_struct(level, ...) log_struct_internal(level, __FILE__, __LINE__, __func__, __VA_ARGS__)
-
-#define log_oom() log_oom_internal(__FILE__, __LINE__, __func__)
-
-/* This modifies the buffer passed! */
-#define log_dump(level, buffer) log_dump_internal(level, __FILE__, __LINE__, __func__, buffer)
-
-bool log_on_console(void);
-
-const char *log_target_to_string(LogTarget target);
-LogTarget log_target_from_string(const char *s);
-
-#define MESSAGE_ID(x) "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(x)
diff --git a/src/udev/macro.h b/src/udev/macro.h
deleted file mode 100644
index e930fdab53..0000000000
--- a/src/udev/macro.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <assert.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <inttypes.h>
-
-#define _printf_attr_(a,b) __attribute__ ((format (printf, a, b)))
-#define _sentinel_ __attribute__ ((sentinel))
-#define _noreturn_ __attribute__((noreturn))
-#define _unused_ __attribute__ ((unused))
-#define _destructor_ __attribute__ ((destructor))
-#define _pure_ __attribute__ ((pure))
-#define _const_ __attribute__ ((const))
-#define _deprecated_ __attribute__ ((deprecated))
-#define _packed_ __attribute__ ((packed))
-#define _malloc_ __attribute__ ((malloc))
-#define _weak_ __attribute__ ((weak))
-#define _likely_(x) (__builtin_expect(!!(x),1))
-#define _unlikely_(x) (__builtin_expect(!!(x),0))
-#define _public_ __attribute__ ((visibility("default")))
-#define _hidden_ __attribute__ ((visibility("hidden")))
-#define _weakref_(x) __attribute__((weakref(#x)))
-#define _introspect_(x) __attribute__((section("introspect." x)))
-#define _alignas_(x) __attribute__((aligned(__alignof(x))))
-
-#define XSTRINGIFY(x) #x
-#define STRINGIFY(x) XSTRINGIFY(x)
-
-/* Rounds up */
-#define ALIGN(l) ALIGN_TO((l), sizeof(void*))
-static inline size_t ALIGN_TO(size_t l, size_t ali) {
- return ((l + ali - 1) & ~(ali - 1));
-}
-
-#define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
-
-/*
- * container_of - cast a member of a structure out to the containing structure
- * @ptr: the pointer to the member.
- * @type: the type of the container struct this is embedded in.
- * @member: the name of the member within the struct.
- *
- */
-#define container_of(ptr, type, member) ({ \
- const typeof( ((type *)0)->member ) *__mptr = (ptr); \
- (type *)( (char *)__mptr - offsetof(type,member) );})
-
-#ifndef MAX
-#define MAX(a,b) \
- __extension__ ({ \
- typeof(a) _a = (a); \
- typeof(b) _b = (b); \
- _a > _b ? _a : _b; \
- })
-#endif
-
-#define MAX3(a,b,c) \
- MAX(MAX(a,b),c)
-
-#ifndef MIN
-#define MIN(a,b) \
- __extension__ ({ \
- typeof(a) _a = (a); \
- typeof(b) _b = (b); \
- _a < _b ? _a : _b; \
- })
-#endif
-
-#define MIN3(a,b,c) \
- MIN(MIN(a,b),c)
-
-#define CLAMP(x, low, high) \
- __extension__ ({ \
- typeof(x) _x = (x); \
- typeof(low) _low = (low); \
- typeof(high) _high = (high); \
- ((_x > _high) ? _high : ((_x < _low) ? _low : _x)); \
- })
-
-#define assert_se(expr) \
- do { \
- if (_unlikely_(!(expr))) \
- log_assert_failed(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
- } while (false) \
-
-/* We override the glibc assert() here. */
-#undef assert
-#ifdef NDEBUG
-#define assert(expr) do {} while(false)
-#else
-#define assert(expr) assert_se(expr)
-#endif
-
-#define assert_not_reached(t) \
- do { \
- log_assert_failed_unreachable(t, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
- } while (false)
-
-#define assert_cc(expr) \
- do { \
- switch (0) { \
- case 0: \
- case !!(expr): \
- ; \
- } \
- } while (false)
-
-#define PTR_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
-#define UINT_TO_PTR(u) ((void*) ((uintptr_t) (u)))
-
-#define PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p)))
-#define UINT32_TO_PTR(u) ((void*) ((uintptr_t) (u)))
-
-#define PTR_TO_ULONG(p) ((unsigned long) ((uintptr_t) (p)))
-#define ULONG_TO_PTR(u) ((void*) ((uintptr_t) (u)))
-
-#define PTR_TO_INT(p) ((int) ((intptr_t) (p)))
-#define INT_TO_PTR(u) ((void*) ((intptr_t) (u)))
-
-#define TO_INT32(p) ((int32_t) ((intptr_t) (p)))
-#define INT32_TO_PTR(u) ((void*) ((intptr_t) (u)))
-
-#define PTR_TO_LONG(p) ((long) ((intptr_t) (p)))
-#define LONG_TO_PTR(u) ((void*) ((intptr_t) (u)))
-
-#define memzero(x,l) (memset((x), 0, (l)))
-#define zero(x) (memzero(&(x), sizeof(x)))
-
-#define char_array_0(x) x[sizeof(x)-1] = 0;
-
-#define IOVEC_SET_STRING(i, s) \
- do { \
- struct iovec *_i = &(i); \
- char *_s = (char *)(s); \
- _i->iov_base = _s; \
- _i->iov_len = strlen(_s); \
- } while(false)
-
-static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) {
- unsigned j;
- size_t r = 0;
-
- for (j = 0; j < n; j++)
- r += i[j].iov_len;
-
- return r;
-}
-
-static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) {
- unsigned j;
-
- for (j = 0; j < n; j++) {
- size_t sub;
-
- if (_unlikely_(k <= 0))
- break;
-
- sub = MIN(i[j].iov_len, k);
- i[j].iov_len -= sub;
- i[j].iov_base = (uint8_t*) i[j].iov_base + sub;
- k -= sub;
- }
-
- return k;
-}
-
-#define _cleanup_free_ __attribute__((cleanup(freep)))
-#define _cleanup_fclose_ __attribute__((cleanup(fclosep)))
-#define _cleanup_close_ __attribute__((cleanup(closep)))
-#define _cleanup_closedir_ __attribute__((cleanup(closedirp)))
-#define _cleanup_umask_ __attribute__((cleanup(umaskp)))
-#define _cleanup_strv_free_ __attribute__((cleanup(strv_freep)))
-
-#define VA_FORMAT_ADVANCE(format, ap) \
-do { \
- int _argtypes[128]; \
- size_t _i, _k; \
- _k = parse_printf_format((format), ELEMENTSOF(_argtypes), _argtypes); \
- assert(_k < ELEMENTSOF(_argtypes)); \
- for (_i = 0; _i < _k; _i++) { \
- if (_argtypes[_i] & PA_FLAG_PTR) { \
- (void) va_arg(ap, void*); \
- continue; \
- } \
- \
- switch (_argtypes[_i]) { \
- case PA_INT: \
- case PA_INT|PA_FLAG_SHORT: \
- case PA_CHAR: \
- (void) va_arg(ap, int); \
- break; \
- case PA_INT|PA_FLAG_LONG: \
- (void) va_arg(ap, long int); \
- break; \
- case PA_INT|PA_FLAG_LONG_LONG: \
- (void) va_arg(ap, long long int); \
- break; \
- case PA_WCHAR: \
- (void) va_arg(ap, wchar_t); \
- break; \
- case PA_WSTRING: \
- case PA_STRING: \
- case PA_POINTER: \
- (void) va_arg(ap, void*); \
- break; \
- case PA_FLOAT: \
- case PA_DOUBLE: \
- (void) va_arg(ap, double); \
- break; \
- case PA_DOUBLE|PA_FLAG_LONG_DOUBLE: \
- (void) va_arg(ap, long double); \
- break; \
- default: \
- assert_not_reached("Unknown format string argument."); \
- } \
- } \
-} while(false)
-
-#include "log.h"
diff --git a/src/udev/missing.h b/src/udev/missing.h
deleted file mode 100644
index 0c8ae7f381..0000000000
--- a/src/udev/missing.h
+++ /dev/null
@@ -1,247 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-/* Missing glibc definitions to access certain kernel APIs */
-
-#include <sys/resource.h>
-#include <sys/syscall.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <linux/oom.h>
-
-#ifdef HAVE_AUDIT
-#include <libaudit.h>
-#endif
-
-#include "macro.h"
-
-#ifdef ARCH_MIPS
-#include <asm/sgidefs.h>
-#endif
-
-#ifndef RLIMIT_RTTIME
-#define RLIMIT_RTTIME 15
-#endif
-
-#ifndef F_LINUX_SPECIFIC_BASE
-#define F_LINUX_SPECIFIC_BASE 1024
-#endif
-
-#ifndef F_SETPIPE_SZ
-#define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
-#endif
-
-#ifndef F_GETPIPE_SZ
-#define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8)
-#endif
-
-#ifndef IP_FREEBIND
-#define IP_FREEBIND 15
-#endif
-
-#ifndef OOM_SCORE_ADJ_MIN
-#define OOM_SCORE_ADJ_MIN (-1000)
-#endif
-
-#ifndef OOM_SCORE_ADJ_MAX
-#define OOM_SCORE_ADJ_MAX 1000
-#endif
-
-#ifndef AUDIT_SERVICE_START
-#define AUDIT_SERVICE_START 1130 /* Service (daemon) start */
-#endif
-
-#ifndef AUDIT_SERVICE_STOP
-#define AUDIT_SERVICE_STOP 1131 /* Service (daemon) stop */
-#endif
-
-#ifndef TIOCVHANGUP
-#define TIOCVHANGUP 0x5437
-#endif
-
-#ifndef IP_TRANSPARENT
-#define IP_TRANSPARENT 19
-#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
-
-#ifdef __x86_64__
-# ifndef __NR_fanotify_init
-# define __NR_fanotify_init 300
-# endif
-# ifndef __NR_fanotify_mark
-# define __NR_fanotify_mark 301
-# endif
-#elif defined _MIPS_SIM
-# if _MIPS_SIM == _MIPS_SIM_ABI32
-# ifndef __NR_fanotify_init
-# define __NR_fanotify_init 4336
-# endif
-# ifndef __NR_fanotify_mark
-# define __NR_fanotify_mark 4337
-# endif
-# elif _MIPS_SIM == _MIPS_SIM_NABI32
-# ifndef __NR_fanotify_init
-# define __NR_fanotify_init 6300
-# endif
-# ifndef __NR_fanotify_mark
-# define __NR_fanotify_mark 6301
-# endif
-# elif _MIPS_SIM == _MIPS_SIM_ABI64
-# ifndef __NR_fanotify_init
-# define __NR_fanotify_init 5295
-# endif
-# ifndef __NR_fanotify_mark
-# define __NR_fanotify_mark 5296
-# endif
-# endif
-#else
-# ifndef __NR_fanotify_init
-# define __NR_fanotify_init 338
-# endif
-# ifndef __NR_fanotify_mark
-# define __NR_fanotify_mark 339
-# endif
-#endif
-
-#ifndef HAVE_FANOTIFY_INIT
-static inline int fanotify_init(unsigned int flags, unsigned int event_f_flags) {
- return syscall(__NR_fanotify_init, flags, event_f_flags);
-}
-#endif
-
-#ifndef HAVE_FANOTIFY_MARK
-static inline int fanotify_mark(int fanotify_fd, unsigned int flags, uint64_t mask,
- int dfd, const char *pathname) {
-#if defined _MIPS_SIM && _MIPS_SIM == _MIPS_SIM_ABI32 || defined __powerpc__ && !defined __powerpc64__
- union {
- uint64_t _64;
- uint32_t _32[2];
- } _mask;
- _mask._64 = mask;
-
- return syscall(__NR_fanotify_mark, fanotify_fd, flags,
- _mask._32[0], _mask._32[1], dfd, pathname);
-#else
- return syscall(__NR_fanotify_mark, fanotify_fd, flags, mask, dfd, pathname);
-#endif
-}
-#endif
-
-#ifndef BTRFS_IOCTL_MAGIC
-#define BTRFS_IOCTL_MAGIC 0x94
-#endif
-
-#ifndef BTRFS_PATH_NAME_MAX
-#define BTRFS_PATH_NAME_MAX 4087
-#endif
-
-struct btrfs_ioctl_vol_args {
- int64_t fd;
- char name[BTRFS_PATH_NAME_MAX + 1];
-};
-
-#ifndef BTRFS_IOC_DEFRAG
-#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, struct btrfs_ioctl_vol_args)
-#endif
-
-#ifndef BTRFS_SUPER_MAGIC
-#define BTRFS_SUPER_MAGIC 0x9123683E
-#endif
-
-#ifndef MS_MOVE
-#define MS_MOVE 8192
-#endif
-
-#ifndef MS_PRIVATE
-#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
-
-#ifndef MS_STRICTATIME
-#define MS_STRICTATIME (1<<24)
-#endif
-
-#ifndef PR_SET_NO_NEW_PRIVS
-#define PR_SET_NO_NEW_PRIVS 38
-#endif
-
-#ifndef PR_SET_CHILD_SUBREAPER
-#define PR_SET_CHILD_SUBREAPER 36
-#endif
-
-#ifndef MAX_HANDLE_SZ
-#define MAX_HANDLE_SZ 128
-#endif
-
-#if defined __x86_64__
-# ifndef __NR_name_to_handle_at
-# define __NR_name_to_handle_at 303
-# endif
-#elif defined __i386__
-# ifndef __NR_name_to_handle_at
-# define __NR_name_to_handle_at 341
-# endif
-#elif defined __arm__
-# ifndef __NR_name_to_handle_at
-# define __NR_name_to_handle_at 370
-# endif
-#elif defined __powerpc__
-# ifndef __NR_name_to_handle_at
-# define __NR_name_to_handle_at 345
-# endif
-#else
-# ifndef __NR_name_to_handle_at
-# 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 CIFS_MAGIC_NUMBER
-#define CIFS_MAGIC_NUMBER 0xFF534D42
-#endif
diff --git a/src/udev/path-util.c b/src/udev/path-util.c
deleted file mode 100644
index 70c8a8af06..0000000000
--- a/src/udev/path-util.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <assert.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <sys/statvfs.h>
-
-#include "macro.h"
-#include "util.h"
-#include "log.h"
-#include "strv.h"
-#include "path-util.h"
-#include "missing.h"
-
-bool path_is_absolute(const char *p) {
- return p[0] == '/';
-}
-
-bool is_path(const char *p) {
- return !!strchr(p, '/');
-}
-
-char *path_get_file_name(const char *p) {
- char *r;
-
- assert(p);
-
- if ((r = strrchr(p, '/')))
- return r + 1;
-
- return (char*) p;
-}
-
-int path_get_parent(const char *path, char **_r) {
- const char *e, *a = NULL, *b = NULL, *p;
- char *r;
- bool slash = false;
-
- assert(path);
- assert(_r);
-
- if (!*path)
- return -EINVAL;
-
- for (e = path; *e; e++) {
-
- if (!slash && *e == '/') {
- a = b;
- b = e;
- slash = true;
- } else if (slash && *e != '/')
- slash = false;
- }
-
- if (*(e-1) == '/')
- p = a;
- else
- p = b;
-
- if (!p)
- return -EINVAL;
-
- if (p == path)
- r = strdup("/");
- else
- r = strndup(path, p-path);
-
- if (!r)
- return -ENOMEM;
-
- *_r = r;
- return 0;
-}
-
-char **path_split_and_make_absolute(const char *p) {
- char **l;
- assert(p);
-
- if (!(l = strv_split(p, ":")))
- return NULL;
-
- if (!path_strv_make_absolute_cwd(l)) {
- strv_free(l);
- return NULL;
- }
-
- return l;
-}
-
-char *path_make_absolute(const char *p, const char *prefix) {
- assert(p);
-
- /* Makes every item in the list an absolute path by prepending
- * the prefix, if specified and necessary */
-
- if (path_is_absolute(p) || !prefix)
- return strdup(p);
-
- return strjoin(prefix, "/", p, NULL);
-}
-
-char *path_make_absolute_cwd(const char *p) {
- char *cwd, *r;
-
- assert(p);
-
- /* Similar to path_make_absolute(), but prefixes with the
- * current working directory. */
-
- if (path_is_absolute(p))
- return strdup(p);
-
- if (!(cwd = get_current_dir_name()))
- return NULL;
-
- r = path_make_absolute(p, cwd);
- free(cwd);
-
- return r;
-}
-
-char **path_strv_make_absolute_cwd(char **l) {
- char **s;
-
- /* Goes through every item in the string list and makes it
- * absolute. This works in place and won't rollback any
- * changes on failure. */
-
- STRV_FOREACH(s, l) {
- char *t;
-
- if (!(t = path_make_absolute_cwd(*s)))
- return NULL;
-
- free(*s);
- *s = t;
- }
-
- return l;
-}
-
-char **path_strv_canonicalize(char **l) {
- char **s;
- unsigned k = 0;
- bool enomem = false;
-
- if (strv_isempty(l))
- return l;
-
- /* Goes through every item in the string list and canonicalize
- * the path. This works in place and won't rollback any
- * changes on failure. */
-
- STRV_FOREACH(s, l) {
- char *t, *u;
-
- t = path_make_absolute_cwd(*s);
- free(*s);
-
- if (!t) {
- enomem = true;
- continue;
- }
-
- errno = 0;
- u = canonicalize_file_name(t);
- free(t);
-
- if (!u) {
- if (errno == ENOMEM || !errno)
- enomem = true;
-
- continue;
- }
-
- l[k++] = u;
- }
-
- l[k] = NULL;
-
- if (enomem)
- return NULL;
-
- return l;
-}
-
-char **path_strv_remove_empty(char **l) {
- char **f, **t;
-
- if (!l)
- return NULL;
-
- for (f = t = l; *f; f++) {
-
- if (dir_is_empty(*f) > 0) {
- free(*f);
- continue;
- }
-
- *(t++) = *f;
- }
-
- *t = NULL;
- return l;
-}
-
-char *path_kill_slashes(char *path) {
- char *f, *t;
- bool slash = false;
-
- /* Removes redundant inner and trailing slashes. Modifies the
- * passed string in-place.
- *
- * ///foo///bar/ becomes /foo/bar
- */
-
- for (f = path, t = path; *f; f++) {
-
- if (*f == '/') {
- slash = true;
- continue;
- }
-
- if (slash) {
- slash = false;
- *(t++) = '/';
- }
-
- *(t++) = *f;
- }
-
- /* Special rule, if we are talking of the root directory, a
- trailing slash is good */
-
- if (t == path && slash)
- *(t++) = '/';
-
- *t = 0;
- return path;
-}
-
-char* path_startswith(const char *path, const char *prefix) {
- assert(path);
- assert(prefix);
-
- if ((path[0] == '/') != (prefix[0] == '/'))
- return NULL;
-
- for (;;) {
- size_t a, b;
-
- path += strspn(path, "/");
- prefix += strspn(prefix, "/");
-
- if (*prefix == 0)
- return (char*) path;
-
- if (*path == 0)
- return NULL;
-
- a = strcspn(path, "/");
- b = strcspn(prefix, "/");
-
- if (a != b)
- return NULL;
-
- if (memcmp(path, prefix, a) != 0)
- return NULL;
-
- path += a;
- prefix += b;
- }
-}
-
-bool path_equal(const char *a, const char *b) {
- assert(a);
- assert(b);
-
- if ((a[0] == '/') != (b[0] == '/'))
- return false;
-
- for (;;) {
- size_t j, k;
-
- a += strspn(a, "/");
- b += strspn(b, "/");
-
- if (*a == 0 && *b == 0)
- return true;
-
- if (*a == 0 || *b == 0)
- return false;
-
- j = strcspn(a, "/");
- k = strcspn(b, "/");
-
- if (j != k)
- return false;
-
- if (memcmp(a, b, j) != 0)
- return false;
-
- a += j;
- b += k;
- }
-}
-
-int path_is_mount_point(const char *t, bool allow_symlink) {
- char *parent;
- int r;
- struct file_handle *h;
- int mount_id, mount_id_parent;
- struct stat a, b;
-
- /* We are not actually interested in the file handles, but
- * name_to_handle_at() also passes us the mount ID, hence use
- * it but throw the handle away */
-
- if (path_equal(t, "/"))
- return 1;
-
- h = alloca(MAX_HANDLE_SZ);
- h->handle_bytes = MAX_HANDLE_SZ;
-
- r = name_to_handle_at(AT_FDCWD, t, h, &mount_id, allow_symlink ? AT_SYMLINK_FOLLOW : 0);
- if (r < 0) {
- if (errno == ENOSYS || errno == ENOTSUP)
- /* This kernel or file system does not support
- * name_to_handle_at(), hence fallback to the
- * traditional stat() logic */
- goto fallback;
-
- if (errno == ENOENT)
- return 0;
-
- return -errno;
- }
-
- r = path_get_parent(t, &parent);
- if (r < 0)
- return r;
-
- h->handle_bytes = MAX_HANDLE_SZ;
- r = name_to_handle_at(AT_FDCWD, parent, h, &mount_id_parent, 0);
- free(parent);
-
- if (r < 0) {
- /* The parent can't do name_to_handle_at() but the
- * directory we are interested in can? If so, it must
- * be a mount point */
- if (errno == ENOTSUP)
- return 1;
-
- return -errno;
- }
-
- return mount_id != mount_id_parent;
-
-fallback:
- if (allow_symlink)
- r = stat(t, &a);
- else
- r = lstat(t, &a);
-
- if (r < 0) {
- if (errno == ENOENT)
- return 0;
-
- return -errno;
- }
-
- r = path_get_parent(t, &parent);
- if (r < 0)
- return r;
-
- r = lstat(parent, &b);
- free(parent);
-
- if (r < 0)
- return -errno;
-
- return a.st_dev != b.st_dev;
-}
-
-int path_is_read_only_fs(const char *path) {
- struct statvfs st;
-
- assert(path);
-
- if (statvfs(path, &st) < 0)
- return -errno;
-
- return !!(st.f_flag & ST_RDONLY);
-}
diff --git a/src/udev/path-util.h b/src/udev/path-util.h
deleted file mode 100644
index e81821a28f..0000000000
--- a/src/udev/path-util.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#ifndef foopathutilhfoo
-#define foopathutilhfoo
-
-/***
- This file is part of systemd.
-
- Copyright 2010-2012 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "stdbool.h"
-
-bool is_path(const char *p);
-char **path_split_and_make_absolute(const char *p);
-char *path_get_file_name(const char *p);
-int path_get_parent(const char *path, char **parent);
-bool path_is_absolute(const char *p);
-char *path_make_absolute(const char *p, const char *prefix);
-char *path_make_absolute_cwd(const char *p);
-char *path_kill_slashes(char *path);
-char *path_startswith(const char *path, const char *prefix);
-bool path_equal(const char *a, const char *b);
-
-char **path_strv_make_absolute_cwd(char **l);
-char **path_strv_canonicalize(char **l);
-char **path_strv_remove_empty(char **l);
-
-int path_is_mount_point(const char *path, bool allow_symlink);
-int path_is_read_only_fs(const char *path);
-
-#endif
diff --git a/src/udev/set.c b/src/udev/set.c
deleted file mode 100644
index 5f83c50839..0000000000
--- a/src/udev/set.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdlib.h>
-
-#include "set.h"
-#include "hashmap.h"
-
-#define MAKE_SET(h) ((Set*) (h))
-#define MAKE_HASHMAP(s) ((Hashmap*) (s))
-
-/* For now this is not much more than a wrapper around a hashmap */
-
-Set *set_new(hash_func_t hash_func, compare_func_t compare_func) {
- return MAKE_SET(hashmap_new(hash_func, compare_func));
-}
-
-void set_free(Set* s) {
- hashmap_free(MAKE_HASHMAP(s));
-}
-
-void set_free_free(Set *s) {
- hashmap_free_free(MAKE_HASHMAP(s));
-}
-
-int set_ensure_allocated(Set **s, hash_func_t hash_func, compare_func_t compare_func) {
- return hashmap_ensure_allocated((Hashmap**) s, hash_func, compare_func);
-}
-
-int set_put(Set *s, void *value) {
- return hashmap_put(MAKE_HASHMAP(s), value, value);
-}
-
-int set_replace(Set *s, void *value) {
- return hashmap_replace(MAKE_HASHMAP(s), value, value);
-}
-
-void *set_get(Set *s, void *value) {
- return hashmap_get(MAKE_HASHMAP(s), value);
-}
-
-bool set_contains(Set *s, void *value) {
- return hashmap_contains(MAKE_HASHMAP(s), value);
-}
-
-void *set_remove(Set *s, void *value) {
- return hashmap_remove(MAKE_HASHMAP(s), value);
-}
-
-int set_remove_and_put(Set *s, void *old_value, void *new_value) {
- return hashmap_remove_and_put(MAKE_HASHMAP(s), old_value, new_value, new_value);
-}
-
-unsigned set_size(Set *s) {
- return hashmap_size(MAKE_HASHMAP(s));
-}
-
-bool set_isempty(Set *s) {
- return hashmap_isempty(MAKE_HASHMAP(s));
-}
-
-void *set_iterate(Set *s, Iterator *i) {
- return hashmap_iterate(MAKE_HASHMAP(s), i, NULL);
-}
-
-void *set_iterate_backwards(Set *s, Iterator *i) {
- return hashmap_iterate_backwards(MAKE_HASHMAP(s), i, NULL);
-}
-
-void *set_iterate_skip(Set *s, void *value, Iterator *i) {
- return hashmap_iterate_skip(MAKE_HASHMAP(s), value, i);
-}
-
-void *set_steal_first(Set *s) {
- return hashmap_steal_first(MAKE_HASHMAP(s));
-}
-
-void* set_first(Set *s) {
- return hashmap_first(MAKE_HASHMAP(s));
-}
-
-void* set_last(Set *s) {
- return hashmap_last(MAKE_HASHMAP(s));
-}
-
-int set_merge(Set *s, Set *other) {
- return hashmap_merge(MAKE_HASHMAP(s), MAKE_HASHMAP(other));
-}
-
-void set_move(Set *s, Set *other) {
- return hashmap_move(MAKE_HASHMAP(s), MAKE_HASHMAP(other));
-}
-
-int set_move_one(Set *s, Set *other, void *value) {
- return hashmap_move_one(MAKE_HASHMAP(s), MAKE_HASHMAP(other), value);
-}
-
-Set* set_copy(Set *s) {
- return MAKE_SET(hashmap_copy(MAKE_HASHMAP(s)));
-}
-
-void set_clear(Set *s) {
- hashmap_clear(MAKE_HASHMAP(s));
-}
-
-void set_clear_free(Set *s) {
- hashmap_clear_free(MAKE_HASHMAP(s));
-}
-
-char **set_get_strv(Set *s) {
- return hashmap_get_strv(MAKE_HASHMAP(s));
-}
diff --git a/src/udev/set.h b/src/udev/set.h
deleted file mode 100644
index 9162e2ae80..0000000000
--- a/src/udev/set.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-/* Pretty straightforward set implementation. Internally based on the
- * hashmap. That means that as a minor optimization a NULL set
- * object will be treated as empty set for all read
- * operations. That way it is not necessary to instantiate an object
- * for each set use. */
-
-#include "hashmap.h"
-
-typedef struct Set Set;
-
-Set *set_new(hash_func_t hash_func, compare_func_t compare_func);
-void set_free(Set* s);
-void set_free_free(Set *s);
-Set* set_copy(Set *s);
-int set_ensure_allocated(Set **s, hash_func_t hash_func, compare_func_t compare_func);
-
-int set_put(Set *s, void *value);
-int set_replace(Set *s, void *value);
-void *set_get(Set *s, void *value);
-bool set_contains(Set *s, void *value);
-void *set_remove(Set *s, void *value);
-int set_remove_and_put(Set *s, void *old_value, void *new_value);
-
-int set_merge(Set *s, Set *other);
-void set_move(Set *s, Set *other);
-int set_move_one(Set *s, Set *other, void *value);
-
-unsigned set_size(Set *s);
-bool set_isempty(Set *s);
-
-void *set_iterate(Set *s, Iterator *i);
-void *set_iterate_backwards(Set *s, Iterator *i);
-void *set_iterate_skip(Set *s, void *value, Iterator *i);
-
-void set_clear(Set *s);
-void set_clear_free(Set *s);
-
-void *set_steal_first(Set *s);
-void* set_first(Set *s);
-void* set_last(Set *s);
-
-char **set_get_strv(Set *s);
-
-#define SET_FOREACH(e, s, i) \
- for ((i) = ITERATOR_FIRST, (e) = set_iterate((s), &(i)); (e); (e) = set_iterate((s), &(i)))
-
-#define SET_FOREACH_BACKWARDS(e, s, i) \
- for ((i) = ITERATOR_LAST, (e) = set_iterate_backwards((s), &(i)); (e); (e) = set_iterate_backwards((s), &(i)))
diff --git a/src/udev/socket-util.h b/src/udev/socket-util.h
deleted file mode 100644
index 04cfb83f5a..0000000000
--- a/src/udev/socket-util.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <sys/un.h>
-#include <net/if.h>
-#include <asm/types.h>
-#include <linux/netlink.h>
-
-#include "macro.h"
-#include "util.h"
-
-union sockaddr_union {
- struct sockaddr sa;
- struct sockaddr_in in4;
- struct sockaddr_in6 in6;
- struct sockaddr_un un;
- struct sockaddr_nl nl;
- struct sockaddr_storage storage;
-};
-
-typedef struct SocketAddress {
- union sockaddr_union sockaddr;
-
- /* We store the size here explicitly due to the weird
- * sockaddr_un semantics for abstract sockets */
- socklen_t size;
-
- /* Socket type, i.e. SOCK_STREAM, SOCK_DGRAM, ... */
- int type;
-
- /* Socket protocol, IPPROTO_xxx, usually 0, except for netlink */
- int protocol;
-} SocketAddress;
-
-typedef enum SocketAddressBindIPv6Only {
- SOCKET_ADDRESS_DEFAULT,
- SOCKET_ADDRESS_BOTH,
- SOCKET_ADDRESS_IPV6_ONLY,
- _SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX,
- _SOCKET_ADDRESS_BIND_IPV6_ONLY_INVALID = -1
-} SocketAddressBindIPv6Only;
-
-#define socket_address_family(a) ((a)->sockaddr.sa.sa_family)
-
-int socket_address_parse(SocketAddress *a, const char *s);
-int socket_address_parse_netlink(SocketAddress *a, const char *s);
-int socket_address_print(const SocketAddress *a, char **p);
-int socket_address_verify(const SocketAddress *a);
-
-bool socket_address_can_accept(const SocketAddress *a);
-
-int socket_address_listen(
- const SocketAddress *a,
- int backlog,
- SocketAddressBindIPv6Only only,
- const char *bind_to_device,
- bool free_bind,
- bool transparent,
- mode_t directory_mode,
- mode_t socket_mode,
- const char *label,
- int *ret);
-
-bool socket_address_is(const SocketAddress *a, const char *s, int type);
-bool socket_address_is_netlink(const SocketAddress *a, const char *s);
-
-bool socket_address_equal(const SocketAddress *a, const SocketAddress *b);
-
-bool socket_address_needs_mount(const SocketAddress *a, const char *prefix);
-
-const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b);
-SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s);
-
-int netlink_family_to_string_alloc(int b, char **s);
-int netlink_family_from_string(const char *s);
-
-bool socket_ipv6_is_supported(void);
diff --git a/src/udev/sparse-endian.h b/src/udev/sparse-endian.h
deleted file mode 100644
index eb4dbf3615..0000000000
--- a/src/udev/sparse-endian.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* Copyright (c) 2012 Josh Triplett <josh@joshtriplett.org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#ifndef SPARSE_ENDIAN_H
-#define SPARSE_ENDIAN_H
-
-#include <endian.h>
-#include <stdint.h>
-
-#ifdef __CHECKER__
-#define __bitwise __attribute__((bitwise))
-#define __force __attribute__((force))
-#else
-#define __bitwise
-#define __force
-#endif
-
-typedef uint16_t __bitwise le16_t;
-typedef uint16_t __bitwise be16_t;
-typedef uint32_t __bitwise le32_t;
-typedef uint32_t __bitwise be32_t;
-typedef uint64_t __bitwise le64_t;
-typedef uint64_t __bitwise be64_t;
-
-#undef htobe16
-#undef htole16
-#undef be16toh
-#undef le16toh
-#undef htobe32
-#undef htole32
-#undef be32toh
-#undef le32toh
-#undef htobe64
-#undef htole64
-#undef be64toh
-#undef le64toh
-
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define bswap_16_on_le(x) __bswap_16(x)
-#define bswap_32_on_le(x) __bswap_32(x)
-#define bswap_64_on_le(x) __bswap_64(x)
-#define bswap_16_on_be(x) (x)
-#define bswap_32_on_be(x) (x)
-#define bswap_64_on_be(x) (x)
-#elif __BYTE_ORDER == __BIG_ENDIAN
-#define bswap_16_on_le(x) (x)
-#define bswap_32_on_le(x) (x)
-#define bswap_64_on_le(x) (x)
-#define bswap_16_on_be(x) __bswap_16(x)
-#define bswap_32_on_be(x) __bswap_32(x)
-#define bswap_64_on_be(x) __bswap_64(x)
-#endif
-
-static inline le16_t htole16(uint16_t value) { return (le16_t __force) bswap_16_on_be(value); }
-static inline le32_t htole32(uint32_t value) { return (le32_t __force) bswap_32_on_be(value); }
-static inline le64_t htole64(uint64_t value) { return (le64_t __force) bswap_64_on_be(value); }
-
-static inline be16_t htobe16(uint16_t value) { return (be16_t __force) bswap_16_on_le(value); }
-static inline be32_t htobe32(uint32_t value) { return (be32_t __force) bswap_32_on_le(value); }
-static inline be64_t htobe64(uint64_t value) { return (be64_t __force) bswap_64_on_le(value); }
-
-static inline uint16_t le16toh(le16_t value) { return bswap_16_on_be((uint16_t __force)value); }
-static inline uint32_t le32toh(le32_t value) { return bswap_32_on_be((uint32_t __force)value); }
-static inline uint64_t le64toh(le64_t value) { return bswap_64_on_be((uint64_t __force)value); }
-
-static inline uint16_t be16toh(be16_t value) { return bswap_16_on_le((uint16_t __force)value); }
-static inline uint32_t be32toh(be32_t value) { return bswap_32_on_le((uint32_t __force)value); }
-static inline uint64_t be64toh(be64_t value) { return bswap_64_on_le((uint64_t __force)value); }
-
-#endif /* SPARSE_ENDIAN_H */
diff --git a/src/udev/strbuf.c b/src/udev/strbuf.c
deleted file mode 100644
index 915cd3ac99..0000000000
--- a/src/udev/strbuf.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Kay Sievers <kay@vrfy.org>
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "util.h"
-#include "strbuf.h"
-
-/*
- * Strbuf stores given strings in a single continous allocated memory
- * area. Identical strings are de-duplicated and return the same offset
- * as the first string stored. If the tail of a string already exists
- * in the buffer, the tail is returned.
- *
- * A trie (http://en.wikipedia.org/wiki/Trie) is used to maintain the
- * information about the stored strings.
- *
- * Example of udev rules:
- * $ ./udevadm test .
- * ...
- * read rules file: /usr/lib/udev/rules.d/99-systemd.rules
- * rules contain 196608 bytes tokens (16384 * 12 bytes), 39742 bytes strings
- * 23939 strings (207859 bytes), 20404 de-duplicated (171653 bytes), 3536 trie nodes used
- * ...
- */
-
-struct strbuf *strbuf_new(void) {
- struct strbuf *str;
-
- str = new0(struct strbuf, 1);
- if (!str)
- return NULL;
-
- str->buf = new0(char, 1);
- if (!str->buf)
- goto err;
- str->len = 1;
-
- str->root = new0(struct strbuf_node, 1);
- if (!str->root)
- goto err;
- str->nodes_count = 1;
- return str;
-err:
- free(str->buf);
- free(str->root);
- free(str);
- return NULL;
-}
-
-static void strbuf_node_cleanup(struct strbuf_node *node) {
- size_t i;
-
- for (i = 0; i < node->children_count; i++)
- strbuf_node_cleanup(node->children[i].child);
- free(node->children);
- free(node);
-}
-
-/* clean up trie data, leave only the string buffer */
-void strbuf_complete(struct strbuf *str) {
- if (!str)
- return;
- if (str->root)
- strbuf_node_cleanup(str->root);
- str->root = NULL;
-}
-
-/* clean up everything */
-void strbuf_cleanup(struct strbuf *str) {
- if (!str)
- return;
- if (str->root)
- strbuf_node_cleanup(str->root);
- free(str->buf);
- free(str);
-}
-
-static int strbuf_children_cmp(const void *v1, const void *v2) {
- const struct strbuf_child_entry *n1 = v1;
- const struct strbuf_child_entry *n2 = v2;
-
- return n1->c - n2->c;
-}
-
-/* add string, return the index/offset into the buffer */
-ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len) {
- uint8_t c;
- struct strbuf_node *node;
- size_t depth;
- char *buf_new;
- struct strbuf_child_entry *child;
- struct strbuf_node *node_child;
- ssize_t off;
-
- if (!str->root)
- return -EINVAL;
-
- /* search string; start from last character to find possibly matching tails */
- if (len == 0)
- return 0;
- str->in_count++;
- str->in_len += len;
-
- node = str->root;
- c = s[len-1];
- for (depth = 0; depth <= len; depth++) {
- struct strbuf_child_entry search;
-
- /* match against current node */
- off = node->value_off + node->value_len - len;
- if (depth == len || (node->value_len >= len && memcmp(str->buf + off, s, len) == 0)) {
- str->dedup_len += len;
- str->dedup_count++;
- return off;
- }
-
- /* lookup child node */
- c = s[len - 1 - depth];
- search.c = c;
- child = bsearch(&search, node->children, node->children_count, sizeof(struct strbuf_child_entry),
- strbuf_children_cmp);
- if (!child)
- break;
- node = child->child;
- }
-
- /* add new string */
- buf_new = realloc(str->buf, str->len + len+1);
- if (!buf_new)
- return -ENOMEM;
- str->buf = buf_new;
- off = str->len;
- memcpy(str->buf + off, s, len);
- str->len += len;
- str->buf[str->len++] = '\0';
-
- /* new node */
- node_child = new0(struct strbuf_node, 1);
- if (!node_child)
- return -ENOMEM;
- str->nodes_count++;
- node_child->value_off = off;
- node_child->value_len = len;
-
- /* extend array, add new entry, sort for bisection */
- child = realloc(node->children, (node->children_count + 1) * sizeof(struct strbuf_child_entry));
- if (!child)
- return -ENOMEM;
- node->children = child;
- node->children[node->children_count].c = c;
- node->children[node->children_count].child = node_child;
- node->children_count++;
- qsort(node->children, node->children_count, sizeof(struct strbuf_child_entry), strbuf_children_cmp);
-
- return off;
-}
diff --git a/src/udev/strbuf.h b/src/udev/strbuf.h
deleted file mode 100644
index 2347fd4328..0000000000
--- a/src/udev/strbuf.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2012 Kay Sievers <kay@vrfy.org>
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdbool.h>
-
-struct strbuf {
- char *buf;
- size_t len;
- struct strbuf_node *root;
-
- size_t nodes_count;
- size_t in_count;
- size_t in_len;
- size_t dedup_len;
- size_t dedup_count;
-};
-
-struct strbuf_node {
- size_t value_off;
- size_t value_len;
-
- struct strbuf_child_entry *children;
- uint8_t children_count;
-};
-
-struct strbuf_child_entry {
- uint8_t c;
- struct strbuf_node *child;
-};
-
-struct strbuf *strbuf_new(void);
-ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len);
-void strbuf_complete(struct strbuf *str);
-void strbuf_cleanup(struct strbuf *str);
diff --git a/src/udev/strv.c b/src/udev/strv.c
deleted file mode 100644
index 6b76d0eaef..0000000000
--- a/src/udev/strv.c
+++ /dev/null
@@ -1,750 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-
-#include "util.h"
-#include "strv.h"
-
-char *strv_find(char **l, const char *name) {
- char **i;
-
- assert(name);
-
- STRV_FOREACH(i, l)
- if (streq(*i, name))
- return *i;
-
- return NULL;
-}
-
-char *strv_find_prefix(char **l, const char *name) {
- char **i;
-
- assert(name);
-
- STRV_FOREACH(i, l)
- if (startswith(*i, name))
- return *i;
-
- return NULL;
-}
-
-void strv_free(char **l) {
- char **k;
-
- if (!l)
- return;
-
- for (k = l; *k; k++)
- free(*k);
-
- free(l);
-}
-
-void strv_freep(char ***l) {
- if (!l)
- return;
-
- strv_free(*l);
- *l = NULL;
-}
-
-char **strv_copy(char **l) {
- char **r, **k;
-
- k = r = new(char*, strv_length(l) + 1);
- if (!r)
- return NULL;
-
- if (l)
- for (; *l; k++, l++) {
- *k = strdup(*l);
- if (!*k) {
- strv_free(r);
- return NULL;
- }
- }
-
- *k = NULL;
- return r;
-}
-
-unsigned strv_length(char **l) {
- unsigned n = 0;
-
- if (!l)
- return 0;
-
- for (; *l; l++)
- n++;
-
- return n;
-}
-
-char **strv_new_ap(const char *x, va_list ap) {
- const char *s;
- char **a;
- unsigned n = 0, i = 0;
- va_list aq;
-
- /* As a special trick we ignore all listed strings that equal
- * (const char*) -1. This is supposed to be used with the
- * STRV_IFNOTNULL() macro to include possibly NULL strings in
- * the string list. */
-
- if (x) {
- n = x == (const char*) -1 ? 0 : 1;
-
- va_copy(aq, ap);
- while ((s = va_arg(aq, const char*))) {
- if (s == (const char*) -1)
- continue;
-
- n++;
- }
-
- va_end(aq);
- }
-
- a = new(char*, n+1);
- if (!a)
- return NULL;
-
- if (x) {
- if (x != (const char*) -1) {
- a[i] = strdup(x);
- if (!a[i])
- goto fail;
- i++;
- }
-
- while ((s = va_arg(ap, const char*))) {
-
- if (s == (const char*) -1)
- continue;
-
- a[i] = strdup(s);
- if (!a[i])
- goto fail;
-
- i++;
- }
- }
-
- a[i] = NULL;
-
- return a;
-
-fail:
- strv_free(a);
- return NULL;
-}
-
-char **strv_new(const char *x, ...) {
- char **r;
- va_list ap;
-
- va_start(ap, x);
- r = strv_new_ap(x, ap);
- va_end(ap);
-
- return r;
-}
-
-char **strv_merge(char **a, char **b) {
- char **r, **k;
-
- if (!a)
- return strv_copy(b);
-
- if (!b)
- return strv_copy(a);
-
- r = new(char*, strv_length(a) + strv_length(b) + 1);
- if (!r)
- return NULL;
-
- for (k = r; *a; k++, a++) {
- *k = strdup(*a);
- if (!*k)
- goto fail;
- }
-
- for (; *b; k++, b++) {
- *k = strdup(*b);
- if (!*k)
- goto fail;
- }
-
- *k = NULL;
- return r;
-
-fail:
- strv_free(r);
- return NULL;
-}
-
-char **strv_merge_concat(char **a, char **b, const char *suffix) {
- char **r, **k;
-
- /* Like strv_merge(), but appends suffix to all strings in b, before adding */
-
- if (!b)
- return strv_copy(a);
-
- r = new(char*, strv_length(a) + strv_length(b) + 1);
- if (!r)
- return NULL;
-
- k = r;
- if (a)
- for (; *a; k++, a++) {
- *k = strdup(*a);
- if (!*k)
- goto fail;
- }
-
- for (; *b; k++, b++) {
- *k = strappend(*b, suffix);
- if (!*k)
- goto fail;
- }
-
- *k = NULL;
- return r;
-
-fail:
- strv_free(r);
- return NULL;
-
-}
-
-char **strv_split(const char *s, const char *separator) {
- char *state;
- char *w;
- size_t l;
- unsigned n, i;
- char **r;
-
- assert(s);
-
- n = 0;
- FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
- n++;
-
- r = new(char*, n+1);
- if (!r)
- return NULL;
-
- i = 0;
- FOREACH_WORD_SEPARATOR(w, l, s, separator, state) {
- r[i] = strndup(w, l);
- if (!r[i]) {
- strv_free(r);
- return NULL;
- }
-
- i++;
- }
-
- r[i] = NULL;
- return r;
-}
-
-char **strv_split_quoted(const char *s) {
- char *state;
- char *w;
- size_t l;
- unsigned n, i;
- char **r;
-
- assert(s);
-
- n = 0;
- FOREACH_WORD_QUOTED(w, l, s, state)
- n++;
-
- r = new(char*, n+1);
- if (!r)
- return NULL;
-
- i = 0;
- FOREACH_WORD_QUOTED(w, l, s, state) {
- r[i] = cunescape_length(w, l);
- if (!r[i]) {
- strv_free(r);
- return NULL;
- }
- i++;
- }
-
- r[i] = NULL;
- return r;
-}
-
-char *strv_join(char **l, const char *separator) {
- char *r, *e;
- char **s;
- size_t n, k;
-
- if (!separator)
- separator = " ";
-
- k = strlen(separator);
-
- n = 0;
- STRV_FOREACH(s, l) {
- if (n != 0)
- n += k;
- n += strlen(*s);
- }
-
- r = new(char, n+1);
- if (!r)
- return NULL;
-
- e = r;
- STRV_FOREACH(s, l) {
- if (e != r)
- e = stpcpy(e, separator);
-
- e = stpcpy(e, *s);
- }
-
- *e = 0;
-
- return r;
-}
-
-char **strv_append(char **l, const char *s) {
- char **r, **k;
-
- if (!l)
- return strv_new(s, NULL);
-
- if (!s)
- return strv_copy(l);
-
- r = new(char*, strv_length(l)+2);
- if (!r)
- return NULL;
-
- for (k = r; *l; k++, l++) {
- *k = strdup(*l);
- if (!*k)
- goto fail;
- }
-
- k[0] = strdup(s);
- if (!k[0])
- goto fail;
-
- k[1] = NULL;
- return r;
-
-fail:
- strv_free(r);
- return NULL;
-}
-
-char **strv_uniq(char **l) {
- char **i;
-
- /* Drops duplicate entries. The first identical string will be
- * kept, the others dropped */
-
- STRV_FOREACH(i, l)
- strv_remove(i+1, *i);
-
- return l;
-}
-
-char **strv_remove(char **l, const char *s) {
- char **f, **t;
-
- if (!l)
- return NULL;
-
- assert(s);
-
- /* Drops every occurrence of s in the string list, edits
- * in-place. */
-
- for (f = t = l; *f; f++) {
-
- if (streq(*f, s)) {
- free(*f);
- continue;
- }
-
- *(t++) = *f;
- }
-
- *t = NULL;
- return l;
-}
-
-char **strv_remove_prefix(char **l, const char *s) {
- char **f, **t;
-
- if (!l)
- return NULL;
-
- assert(s);
-
- /* Drops every occurrence of a string prefixed with s in the
- * string list, edits in-place. */
-
- for (f = t = l; *f; f++) {
-
- if (startswith(*f, s)) {
- free(*f);
- continue;
- }
-
- *(t++) = *f;
- }
-
- *t = NULL;
- return l;
-}
-
-static int env_append(char **r, char ***k, char **a) {
- assert(r);
- assert(k);
-
- if (!a)
- return 0;
-
- /* Add the entries of a to *k unless they already exist in *r
- * in which case they are overridden instead. This assumes
- * there is enough space in the r array. */
-
- for (; *a; a++) {
- char **j;
- size_t n;
-
- n = strcspn(*a, "=");
-
- if ((*a)[n] == '=')
- n++;
-
- for (j = r; j < *k; j++)
- if (strncmp(*j, *a, n) == 0)
- break;
-
- if (j >= *k)
- (*k)++;
- else
- free(*j);
-
- *j = strdup(*a);
- if (!*j)
- return -ENOMEM;
- }
-
- return 0;
-}
-
-char **strv_env_merge(unsigned n_lists, ...) {
- size_t n = 0;
- char **l, **k, **r;
- va_list ap;
- unsigned i;
-
- /* Merges an arbitrary number of environment sets */
-
- va_start(ap, n_lists);
- for (i = 0; i < n_lists; i++) {
- l = va_arg(ap, char**);
- n += strv_length(l);
- }
- va_end(ap);
-
- r = new(char*, n+1);
- if (!r)
- return NULL;
-
- k = r;
-
- va_start(ap, n_lists);
- for (i = 0; i < n_lists; i++) {
- l = va_arg(ap, char**);
- if (env_append(r, &k, l) < 0)
- goto fail;
- }
- va_end(ap);
-
- *k = NULL;
-
- return r;
-
-fail:
- va_end(ap);
- strv_free(r);
-
- return NULL;
-}
-
-static bool env_match(const char *t, const char *pattern) {
- assert(t);
- assert(pattern);
-
- /* pattern a matches string a
- * a matches a=
- * a matches a=b
- * a= matches a=
- * a=b matches a=b
- * a= does not match a
- * a=b does not match a=
- * a=b does not match a
- * a=b does not match a=c */
-
- if (streq(t, pattern))
- return true;
-
- if (!strchr(pattern, '=')) {
- size_t l = strlen(pattern);
-
- return strncmp(t, pattern, l) == 0 && t[l] == '=';
- }
-
- return false;
-}
-
-char **strv_env_delete(char **x, unsigned n_lists, ...) {
- size_t n, i = 0;
- char **k, **r;
- va_list ap;
-
- /* Deletes every entry from x that is mentioned in the other
- * string lists */
-
- n = strv_length(x);
-
- r = new(char*, n+1);
- if (!r)
- return NULL;
-
- STRV_FOREACH(k, x) {
- unsigned v;
-
- va_start(ap, n_lists);
- for (v = 0; v < n_lists; v++) {
- char **l, **j;
-
- l = va_arg(ap, char**);
- STRV_FOREACH(j, l)
- if (env_match(*k, *j))
- goto skip;
- }
- va_end(ap);
-
- r[i] = strdup(*k);
- if (!r[i]) {
- strv_free(r);
- return NULL;
- }
-
- i++;
- continue;
-
- skip:
- va_end(ap);
- }
-
- r[i] = NULL;
-
- assert(i <= n);
-
- return r;
-}
-
-char **strv_env_unset(char **l, const char *p) {
-
- char **f, **t;
-
- if (!l)
- return NULL;
-
- assert(p);
-
- /* Drops every occurrence of the env var setting p in the
- * string list. edits in-place. */
-
- for (f = t = l; *f; f++) {
-
- if (env_match(*f, p)) {
- free(*f);
- continue;
- }
-
- *(t++) = *f;
- }
-
- *t = NULL;
- return l;
-}
-
-char **strv_env_set(char **x, const char *p) {
-
- char **k, **r;
- char* m[2] = { (char*) p, NULL };
-
- /* Overrides the env var setting of p, returns a new copy */
-
- r = new(char*, strv_length(x)+2);
- if (!r)
- return NULL;
-
- k = r;
- if (env_append(r, &k, x) < 0)
- goto fail;
-
- if (env_append(r, &k, m) < 0)
- goto fail;
-
- *k = NULL;
-
- return r;
-
-fail:
- strv_free(r);
- return NULL;
-
-}
-
-char *strv_env_get_with_length(char **l, const char *name, size_t k) {
- char **i;
-
- assert(name);
-
- STRV_FOREACH(i, l)
- if (strncmp(*i, name, k) == 0 &&
- (*i)[k] == '=')
- return *i + k + 1;
-
- return NULL;
-}
-
-char *strv_env_get(char **l, const char *name) {
- return strv_env_get_with_length(l, name, strlen(name));
-}
-
-char **strv_env_clean(char **l) {
- char **r, **ret;
-
- for (r = ret = l; *l; l++) {
- const char *equal;
-
- equal = strchr(*l, '=');
-
- if (equal && equal[1] == 0) {
- free(*l);
- continue;
- }
-
- *(r++) = *l;
- }
-
- *r = NULL;
-
- return ret;
-}
-
-char **strv_parse_nulstr(const char *s, size_t l) {
- const char *p;
- unsigned c = 0, i = 0;
- char **v;
-
- assert(s || l <= 0);
-
- if (l <= 0)
- return strv_new(NULL, NULL);
-
- for (p = s; p < s + l; p++)
- if (*p == 0)
- c++;
-
- if (s[l-1] != 0)
- c++;
-
- v = new0(char*, c+1);
- if (!v)
- return NULL;
-
- p = s;
- while (p < s + l) {
- const char *e;
-
- e = memchr(p, 0, s + l - p);
-
- v[i] = strndup(p, e ? e - p : s + l - p);
- if (!v[i]) {
- strv_free(v);
- return NULL;
- }
-
- i++;
-
- if (!e)
- break;
-
- p = e + 1;
- }
-
- assert(i == c);
-
- return v;
-}
-
-bool strv_overlap(char **a, char **b) {
- char **i, **j;
-
- STRV_FOREACH(i, a) {
- STRV_FOREACH(j, b) {
- if (streq(*i, *j))
- return true;
- }
- }
-
- return false;
-}
-
-static int str_compare(const void *_a, const void *_b) {
- const char **a = (const char**) _a, **b = (const char**) _b;
-
- return strcmp(*a, *b);
-}
-
-char **strv_sort(char **l) {
-
- if (strv_isempty(l))
- return l;
-
- qsort(l, strv_length(l), sizeof(char*), str_compare);
- return l;
-}
diff --git a/src/udev/strv.h b/src/udev/strv.h
deleted file mode 100644
index 45558d8960..0000000000
--- a/src/udev/strv.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdarg.h>
-#include <stdbool.h>
-
-#include "macro.h"
-
-char *strv_find(char **l, const char *name);
-char *strv_find_prefix(char **l, const char *name);
-
-void strv_free(char **l);
-void strv_freep(char ***l);
-char **strv_copy(char **l) _malloc_;
-unsigned strv_length(char **l);
-
-char **strv_merge(char **a, char **b);
-char **strv_merge_concat(char **a, char **b, const char *suffix);
-char **strv_append(char **l, const char *s);
-
-char **strv_remove(char **l, const char *s);
-char **strv_remove_prefix(char **l, const char *s);
-char **strv_uniq(char **l);
-
-#define strv_contains(l, s) (!!strv_find((l), (s)))
-
-char **strv_new(const char *x, ...) _sentinel_ _malloc_;
-char **strv_new_ap(const char *x, va_list ap) _malloc_;
-
-static inline const char* STRV_IFNOTNULL(const char *x) {
- return x ? x : (const char *) -1;
-}
-
-static inline bool strv_isempty(char **l) {
- return !l || !*l;
-}
-
-char **strv_split(const char *s, const char *separator) _malloc_;
-char **strv_split_quoted(const char *s) _malloc_;
-
-char *strv_join(char **l, const char *separator) _malloc_;
-
-char **strv_env_merge(unsigned n_lists, ...);
-char **strv_env_delete(char **x, unsigned n_lists, ...);
-
-char **strv_env_set(char **x, const char *p);
-char **strv_env_unset(char **l, const char *p);
-
-char *strv_env_get_with_length(char **l, const char *name, size_t k);
-char *strv_env_get(char **x, const char *n);
-
-char **strv_env_clean(char **l);
-
-char **strv_parse_nulstr(const char *s, size_t l);
-
-bool strv_overlap(char **a, char **b);
-
-#define STRV_FOREACH(s, l) \
- for ((s) = (l); (s) && *(s); (s)++)
-
-#define STRV_FOREACH_BACKWARDS(s, l) \
- for (; (l) && ((s) >= (l)); (s)--)
-
-char **strv_sort(char **l);
diff --git a/src/udev/util.c b/src/udev/util.c
deleted file mode 100644
index d8c5bb2e1e..0000000000
--- a/src/udev/util.c
+++ /dev/null
@@ -1,6255 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <assert.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <stdio.h>
-#include <syslog.h>
-#include <sched.h>
-#include <sys/resource.h>
-#include <linux/sched.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <sys/ioctl.h>
-#include <linux/vt.h>
-#include <linux/tiocl.h>
-#include <termios.h>
-#include <stdarg.h>
-#include <sys/inotify.h>
-#include <sys/poll.h>
-#include <libgen.h>
-#include <ctype.h>
-#include <sys/prctl.h>
-#include <sys/utsname.h>
-#include <pwd.h>
-#include <netinet/ip.h>
-#include <linux/kd.h>
-#include <dlfcn.h>
-#include <sys/wait.h>
-#include <sys/time.h>
-#include <glob.h>
-#include <grp.h>
-#include <sys/mman.h>
-#include <sys/vfs.h>
-#include <linux/magic.h>
-#include <limits.h>
-#include <langinfo.h>
-#include <locale.h>
-
-#include "macro.h"
-#include "util.h"
-#include "ioprio.h"
-#include "missing.h"
-#include "log.h"
-#include "strv.h"
-#include "label.h"
-#include "path-util.h"
-#include "exit-status.h"
-#include "hashmap.h"
-
-int saved_argc = 0;
-char **saved_argv = NULL;
-
-static volatile unsigned cached_columns = 0;
-static volatile unsigned cached_lines = 0;
-
-bool is_efiboot(void) {
- return access("/sys/firmware/efi", F_OK) >= 0;
-}
-
-size_t page_size(void) {
- static __thread size_t pgsz = 0;
- long r;
-
- if (_likely_(pgsz > 0))
- return pgsz;
-
- r = sysconf(_SC_PAGESIZE);
- assert(r > 0);
-
- pgsz = (size_t) r;
- return pgsz;
-}
-
-bool streq_ptr(const char *a, const char *b) {
-
- /* Like streq(), but tries to make sense of NULL pointers */
-
- if (a && b)
- return streq(a, b);
-
- if (!a && !b)
- return true;
-
- return false;
-}
-
-usec_t now(clockid_t clock_id) {
- struct timespec ts;
-
- assert_se(clock_gettime(clock_id, &ts) == 0);
-
- return timespec_load(&ts);
-}
-
-dual_timestamp* dual_timestamp_get(dual_timestamp *ts) {
- assert(ts);
-
- ts->realtime = now(CLOCK_REALTIME);
- ts->monotonic = now(CLOCK_MONOTONIC);
-
- return ts;
-}
-
-dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
- int64_t delta;
- assert(ts);
-
- ts->realtime = u;
-
- if (u == 0)
- ts->monotonic = 0;
- else {
- delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u;
-
- ts->monotonic = now(CLOCK_MONOTONIC);
-
- if ((int64_t) ts->monotonic > delta)
- ts->monotonic -= delta;
- else
- ts->monotonic = 0;
- }
-
- return ts;
-}
-
-usec_t timespec_load(const struct timespec *ts) {
- assert(ts);
-
- if (ts->tv_sec == (time_t) -1 &&
- ts->tv_nsec == (long) -1)
- return (usec_t) -1;
-
- if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC)
- return (usec_t) -1;
-
- return
- (usec_t) ts->tv_sec * USEC_PER_SEC +
- (usec_t) ts->tv_nsec / NSEC_PER_USEC;
-}
-
-struct timespec *timespec_store(struct timespec *ts, usec_t u) {
- assert(ts);
-
- if (u == (usec_t) -1) {
- ts->tv_sec = (time_t) -1;
- ts->tv_nsec = (long) -1;
- return ts;
- }
-
- ts->tv_sec = (time_t) (u / USEC_PER_SEC);
- ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC);
-
- return ts;
-}
-
-usec_t timeval_load(const struct timeval *tv) {
- assert(tv);
-
- if (tv->tv_sec == (time_t) -1 &&
- tv->tv_usec == (suseconds_t) -1)
- return (usec_t) -1;
-
- if ((usec_t) tv->tv_sec > (UINT64_MAX - tv->tv_usec) / USEC_PER_SEC)
- return (usec_t) -1;
-
- return
- (usec_t) tv->tv_sec * USEC_PER_SEC +
- (usec_t) tv->tv_usec;
-}
-
-struct timeval *timeval_store(struct timeval *tv, usec_t u) {
- assert(tv);
-
- if (u == (usec_t) -1) {
- tv->tv_sec = (time_t) -1;
- tv->tv_usec = (suseconds_t) -1;
- return tv;
- }
-
- tv->tv_sec = (time_t) (u / USEC_PER_SEC);
- tv->tv_usec = (suseconds_t) (u % USEC_PER_SEC);
-
- return tv;
-}
-
-char* endswith(const char *s, const char *postfix) {
- size_t sl, pl;
-
- assert(s);
- assert(postfix);
-
- sl = strlen(s);
- pl = strlen(postfix);
-
- if (pl == 0)
- return (char*) s + sl;
-
- if (sl < pl)
- return NULL;
-
- if (memcmp(s + sl - pl, postfix, pl) != 0)
- return NULL;
-
- return (char*) s + sl - pl;
-}
-
-char* startswith(const char *s, const char *prefix) {
- const char *a, *b;
-
- assert(s);
- assert(prefix);
-
- a = s, b = prefix;
- for (;;) {
- if (*b == 0)
- return (char*) a;
- if (*a != *b)
- return NULL;
-
- a++, b++;
- }
-}
-
-char* startswith_no_case(const char *s, const char *prefix) {
- const char *a, *b;
-
- assert(s);
- assert(prefix);
-
- a = s, b = prefix;
- for (;;) {
- if (*b == 0)
- return (char*) a;
- if (tolower(*a) != tolower(*b))
- return NULL;
-
- a++, b++;
- }
-}
-
-bool first_word(const char *s, const char *word) {
- size_t sl, wl;
-
- assert(s);
- assert(word);
-
- sl = strlen(s);
- wl = strlen(word);
-
- if (sl < wl)
- return false;
-
- if (wl == 0)
- return true;
-
- if (memcmp(s, word, wl) != 0)
- return false;
-
- return s[wl] == 0 ||
- strchr(WHITESPACE, s[wl]);
-}
-
-int close_nointr(int fd) {
- assert(fd >= 0);
-
- for (;;) {
- int r;
-
- r = close(fd);
- if (r >= 0)
- return r;
-
- if (errno != EINTR)
- return -errno;
- }
-}
-
-void close_nointr_nofail(int fd) {
- int saved_errno = errno;
-
- /* like close_nointr() but cannot fail, and guarantees errno
- * is unchanged */
-
- assert_se(close_nointr(fd) == 0);
-
- errno = saved_errno;
-}
-
-void close_many(const int fds[], unsigned n_fd) {
- unsigned i;
-
- for (i = 0; i < n_fd; i++)
- close_nointr_nofail(fds[i]);
-}
-
-int parse_boolean(const char *v) {
- assert(v);
-
- if (streq(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
- return 1;
- else if (streq(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
- return 0;
-
- return -EINVAL;
-}
-
-int parse_pid(const char *s, pid_t* ret_pid) {
- unsigned long ul = 0;
- pid_t pid;
- int r;
-
- assert(s);
- assert(ret_pid);
-
- r = safe_atolu(s, &ul);
- if (r < 0)
- return r;
-
- pid = (pid_t) ul;
-
- if ((unsigned long) pid != ul)
- return -ERANGE;
-
- if (pid <= 0)
- return -ERANGE;
-
- *ret_pid = pid;
- return 0;
-}
-
-int parse_uid(const char *s, uid_t* ret_uid) {
- unsigned long ul = 0;
- uid_t uid;
- int r;
-
- assert(s);
- assert(ret_uid);
-
- r = safe_atolu(s, &ul);
- if (r < 0)
- return r;
-
- uid = (uid_t) ul;
-
- if ((unsigned long) uid != ul)
- return -ERANGE;
-
- *ret_uid = uid;
- return 0;
-}
-
-int safe_atou(const char *s, unsigned *ret_u) {
- char *x = NULL;
- unsigned long l;
-
- assert(s);
- assert(ret_u);
-
- errno = 0;
- l = strtoul(s, &x, 0);
-
- if (!x || x == s || *x || errno)
- return errno ? -errno : -EINVAL;
-
- if ((unsigned long) (unsigned) l != l)
- return -ERANGE;
-
- *ret_u = (unsigned) l;
- return 0;
-}
-
-int safe_atoi(const char *s, int *ret_i) {
- char *x = NULL;
- long l;
-
- assert(s);
- assert(ret_i);
-
- errno = 0;
- l = strtol(s, &x, 0);
-
- if (!x || x == s || *x || errno)
- return errno ? -errno : -EINVAL;
-
- if ((long) (int) l != l)
- return -ERANGE;
-
- *ret_i = (int) l;
- return 0;
-}
-
-int safe_atollu(const char *s, long long unsigned *ret_llu) {
- char *x = NULL;
- unsigned long long l;
-
- assert(s);
- assert(ret_llu);
-
- errno = 0;
- l = strtoull(s, &x, 0);
-
- if (!x || x == s || *x || errno)
- return errno ? -errno : -EINVAL;
-
- *ret_llu = l;
- return 0;
-}
-
-int safe_atolli(const char *s, long long int *ret_lli) {
- char *x = NULL;
- long long l;
-
- assert(s);
- assert(ret_lli);
-
- errno = 0;
- l = strtoll(s, &x, 0);
-
- if (!x || x == s || *x || errno)
- return errno ? -errno : -EINVAL;
-
- *ret_lli = l;
- return 0;
-}
-
-/* Split a string into words. */
-char *split(const char *c, size_t *l, const char *separator, char **state) {
- char *current;
-
- current = *state ? *state : (char*) c;
-
- if (!*current || *c == 0)
- return NULL;
-
- current += strspn(current, separator);
- *l = strcspn(current, separator);
- *state = current+*l;
-
- return (char*) current;
-}
-
-/* Split a string into words, but consider strings enclosed in '' and
- * "" as words even if they include spaces. */
-char *split_quoted(const char *c, size_t *l, char **state) {
- char *current, *e;
- bool escaped = false;
-
- current = *state ? *state : (char*) c;
-
- if (!*current || *c == 0)
- return NULL;
-
- current += strspn(current, WHITESPACE);
-
- if (*current == '\'') {
- current ++;
-
- for (e = current; *e; e++) {
- if (escaped)
- escaped = false;
- else if (*e == '\\')
- escaped = true;
- else if (*e == '\'')
- break;
- }
-
- *l = e-current;
- *state = *e == 0 ? e : e+1;
- } else if (*current == '\"') {
- current ++;
-
- for (e = current; *e; e++) {
- if (escaped)
- escaped = false;
- else if (*e == '\\')
- escaped = true;
- else if (*e == '\"')
- break;
- }
-
- *l = e-current;
- *state = *e == 0 ? e : e+1;
- } else {
- for (e = current; *e; e++) {
- if (escaped)
- escaped = false;
- else if (*e == '\\')
- escaped = true;
- else if (strchr(WHITESPACE, *e))
- break;
- }
- *l = e-current;
- *state = e;
- }
-
- return (char*) current;
-}
-
-int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
- int r;
- _cleanup_fclose_ FILE *f = NULL;
- char fn[PATH_MAX], line[LINE_MAX], *p;
- long unsigned ppid;
-
- assert(pid > 0);
- assert(_ppid);
-
- assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
- char_array_0(fn);
-
- f = fopen(fn, "re");
- if (!f)
- return -errno;
-
- if (!fgets(line, sizeof(line), f)) {
- r = feof(f) ? -EIO : -errno;
- fclose(f);
- return r;
- }
-
- /* Let's skip the pid and comm fields. The latter is enclosed
- * in () but does not escape any () in its value, so let's
- * skip over it manually */
-
- p = strrchr(line, ')');
- if (!p)
- return -EIO;
-
- p++;
-
- if (sscanf(p, " "
- "%*c " /* state */
- "%lu ", /* ppid */
- &ppid) != 1)
- return -EIO;
-
- if ((long unsigned) (pid_t) ppid != ppid)
- return -ERANGE;
-
- *_ppid = (pid_t) ppid;
-
- return 0;
-}
-
-int get_starttime_of_pid(pid_t pid, unsigned long long *st) {
- _cleanup_fclose_ FILE *f = NULL;
- char fn[PATH_MAX], line[LINE_MAX], *p;
-
- assert(pid > 0);
- assert(st);
-
- assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
- char_array_0(fn);
-
- f = fopen(fn, "re");
- if (!f)
- return -errno;
-
- if (!fgets(line, sizeof(line), f)) {
- if (ferror(f))
- return -errno;
-
- return -EIO;
- }
-
- /* Let's skip the pid and comm fields. The latter is enclosed
- * in () but does not escape any () in its value, so let's
- * skip over it manually */
-
- p = strrchr(line, ')');
- if (!p)
- return -EIO;
-
- p++;
-
- if (sscanf(p, " "
- "%*c " /* state */
- "%*d " /* ppid */
- "%*d " /* pgrp */
- "%*d " /* session */
- "%*d " /* tty_nr */
- "%*d " /* tpgid */
- "%*u " /* flags */
- "%*u " /* minflt */
- "%*u " /* cminflt */
- "%*u " /* majflt */
- "%*u " /* cmajflt */
- "%*u " /* utime */
- "%*u " /* stime */
- "%*d " /* cutime */
- "%*d " /* cstime */
- "%*d " /* priority */
- "%*d " /* nice */
- "%*d " /* num_threads */
- "%*d " /* itrealvalue */
- "%llu " /* starttime */,
- st) != 1)
- return -EIO;
-
- return 0;
-}
-
-int write_one_line_file(const char *fn, const char *line) {
- _cleanup_fclose_ FILE *f = NULL;
-
- assert(fn);
- assert(line);
-
- f = fopen(fn, "we");
- if (!f)
- return -errno;
-
- errno = 0;
- if (fputs(line, f) < 0)
- return errno ? -errno : -EIO;
-
- if (!endswith(line, "\n"))
- fputc('\n', f);
-
- fflush(f);
-
- if (ferror(f))
- return errno ? -errno : -EIO;
-
- return 0;
-}
-
-int fchmod_umask(int fd, mode_t m) {
- mode_t u;
- int r;
-
- u = umask(0777);
- r = fchmod(fd, m & (~u)) < 0 ? -errno : 0;
- umask(u);
-
- return r;
-}
-
-int write_one_line_file_atomic(const char *fn, const char *line) {
- FILE *f;
- int r;
- char *p;
-
- assert(fn);
- assert(line);
-
- r = fopen_temporary(fn, &f, &p);
- if (r < 0)
- return r;
-
- fchmod_umask(fileno(f), 0644);
-
- errno = 0;
- if (fputs(line, f) < 0) {
- r = -errno;
- goto finish;
- }
-
- if (!endswith(line, "\n"))
- fputc('\n', f);
-
- fflush(f);
-
- if (ferror(f)) {
- if (errno != 0)
- r = -errno;
- else
- r = -EIO;
- } else {
- if (rename(p, fn) < 0)
- r = -errno;
- else
- r = 0;
- }
-
-finish:
- if (r < 0)
- unlink(p);
-
- fclose(f);
- free(p);
-
- return r;
-}
-
-int read_one_line_file(const char *fn, char **line) {
- _cleanup_fclose_ FILE *f = NULL;
- char t[LINE_MAX], *c;
-
- assert(fn);
- assert(line);
-
- f = fopen(fn, "re");
- if (!f)
- return -errno;
-
- if (!fgets(t, sizeof(t), f)) {
-
- if (ferror(f))
- return errno ? -errno : -EIO;
-
- t[0] = 0;
- }
-
- c = strdup(t);
- if (!c)
- return -ENOMEM;
- truncate_nl(c);
-
- *line = c;
- return 0;
-}
-
-int read_full_file(const char *fn, char **contents, size_t *size) {
- _cleanup_fclose_ FILE *f = NULL;
- size_t n, l;
- _cleanup_free_ char *buf = NULL;
- struct stat st;
-
- f = fopen(fn, "re");
- if (!f)
- return -errno;
-
- if (fstat(fileno(f), &st) < 0)
- return -errno;
-
- /* Safety check */
- if (st.st_size > 4*1024*1024)
- return -E2BIG;
-
- n = st.st_size > 0 ? st.st_size : LINE_MAX;
- l = 0;
-
- for (;;) {
- char *t;
- size_t k;
-
- t = realloc(buf, n+1);
- if (!t)
- return -ENOMEM;
-
- buf = t;
- k = fread(buf + l, 1, n - l, f);
-
- if (k <= 0) {
- if (ferror(f))
- return -errno;
-
- break;
- }
-
- l += k;
- n *= 2;
-
- /* Safety check */
- if (n > 4*1024*1024)
- return -E2BIG;
- }
-
- buf[l] = 0;
- *contents = buf;
- buf = NULL;
-
- if (size)
- *size = l;
-
- return 0;
-}
-
-int parse_env_file(
- const char *fname,
- const char *separator, ...) {
-
- int r = 0;
- char *contents = NULL, *p;
-
- assert(fname);
- assert(separator);
-
- if ((r = read_full_file(fname, &contents, NULL)) < 0)
- return r;
-
- p = contents;
- for (;;) {
- const char *key = NULL;
-
- p += strspn(p, separator);
- p += strspn(p, WHITESPACE);
-
- if (!*p)
- break;
-
- if (!strchr(COMMENTS, *p)) {
- va_list ap;
- char **value;
-
- va_start(ap, separator);
- while ((key = va_arg(ap, char *))) {
- size_t n;
- char *v;
-
- value = va_arg(ap, char **);
-
- n = strlen(key);
- if (strncmp(p, key, n) != 0 ||
- p[n] != '=')
- continue;
-
- p += n + 1;
- n = strcspn(p, separator);
-
- if (n >= 2 &&
- strchr(QUOTES, p[0]) &&
- p[n-1] == p[0])
- v = strndup(p+1, n-2);
- else
- v = strndup(p, n);
-
- if (!v) {
- r = -ENOMEM;
- va_end(ap);
- goto fail;
- }
-
- if (v[0] == '\0') {
- /* return empty value strings as NULL */
- free(v);
- v = NULL;
- }
-
- free(*value);
- *value = v;
-
- p += n;
-
- r ++;
- break;
- }
- va_end(ap);
- }
-
- if (!key)
- p += strcspn(p, separator);
- }
-
-fail:
- free(contents);
- return r;
-}
-
-int load_env_file(
- const char *fname,
- char ***rl) {
-
- FILE *f;
- char **m = NULL;
- int r;
-
- assert(fname);
- assert(rl);
-
- if (!(f = fopen(fname, "re")))
- return -errno;
-
- while (!feof(f)) {
- char l[LINE_MAX], *p, *u;
- char **t;
-
- if (!fgets(l, sizeof(l), f)) {
- if (feof(f))
- break;
-
- r = -errno;
- goto finish;
- }
-
- p = strstrip(l);
-
- if (!*p)
- continue;
-
- if (strchr(COMMENTS, *p))
- continue;
-
- if (!(u = normalize_env_assignment(p))) {
- r = log_oom();
- goto finish;
- }
-
- t = strv_append(m, u);
- free(u);
-
- if (!t) {
- r = log_oom();
- goto finish;
- }
-
- strv_free(m);
- m = t;
- }
-
- r = 0;
-
- *rl = m;
- m = NULL;
-
-finish:
- if (f)
- fclose(f);
-
- strv_free(m);
-
- return r;
-}
-
-int write_env_file(const char *fname, char **l) {
- char **i, *p;
- FILE *f;
- int r;
-
- r = fopen_temporary(fname, &f, &p);
- if (r < 0)
- return r;
-
- fchmod_umask(fileno(f), 0644);
-
- errno = 0;
- STRV_FOREACH(i, l) {
- fputs(*i, f);
- fputc('\n', f);
- }
-
- fflush(f);
-
- if (ferror(f)) {
- if (errno != 0)
- r = -errno;
- else
- r = -EIO;
- } else {
- if (rename(p, fname) < 0)
- r = -errno;
- else
- r = 0;
- }
-
- if (r < 0)
- unlink(p);
-
- fclose(f);
- free(p);
-
- return r;
-}
-
-char *truncate_nl(char *s) {
- assert(s);
-
- s[strcspn(s, NEWLINE)] = 0;
- return s;
-}
-
-int get_process_comm(pid_t pid, char **name) {
- int r;
-
- assert(name);
-
- if (pid == 0)
- r = read_one_line_file("/proc/self/comm", name);
- else {
- char *p;
- if (asprintf(&p, "/proc/%lu/comm", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- r = read_one_line_file(p, name);
- free(p);
- }
-
- return r;
-}
-
-int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
- char *r, *k;
- int c;
- bool space = false;
- size_t left;
- FILE *f;
-
- assert(max_length > 0);
- assert(line);
-
- if (pid == 0)
- f = fopen("/proc/self/cmdline", "re");
- else {
- char *p;
- if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- f = fopen(p, "re");
- free(p);
- }
-
- if (!f)
- return -errno;
-
- r = new(char, max_length);
- if (!r) {
- fclose(f);
- return -ENOMEM;
- }
-
- k = r;
- left = max_length;
- while ((c = getc(f)) != EOF) {
-
- if (isprint(c)) {
- if (space) {
- if (left <= 4)
- break;
-
- *(k++) = ' ';
- left--;
- space = false;
- }
-
- if (left <= 4)
- break;
-
- *(k++) = (char) c;
- left--;
- } else
- space = true;
- }
-
- if (left <= 4) {
- size_t n = MIN(left-1, 3U);
- memcpy(k, "...", n);
- k[n] = 0;
- } else
- *k = 0;
-
- fclose(f);
-
- /* Kernel threads have no argv[] */
- if (r[0] == 0) {
- char *t;
- int h;
-
- free(r);
-
- if (!comm_fallback)
- return -ENOENT;
-
- h = get_process_comm(pid, &t);
- if (h < 0)
- return h;
-
- r = strjoin("[", t, "]", NULL);
- free(t);
-
- if (!r)
- return -ENOMEM;
- }
-
- *line = r;
- return 0;
-}
-
-int is_kernel_thread(pid_t pid) {
- char *p;
- size_t count;
- char c;
- bool eof;
- FILE *f;
-
- if (pid == 0)
- return 0;
-
- if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- f = fopen(p, "re");
- free(p);
-
- if (!f)
- return -errno;
-
- count = fread(&c, 1, 1, f);
- eof = feof(f);
- fclose(f);
-
- /* Kernel threads have an empty cmdline */
-
- if (count <= 0)
- return eof ? 1 : -errno;
-
- return 0;
-}
-
-int get_process_exe(pid_t pid, char **name) {
- int r;
-
- assert(name);
-
- if (pid == 0)
- r = readlink_malloc("/proc/self/exe", name);
- else {
- char *p;
- if (asprintf(&p, "/proc/%lu/exe", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- r = readlink_malloc(p, name);
- free(p);
- }
-
- return r;
-}
-
-static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
- char *p;
- FILE *f;
- int r;
-
- assert(uid);
-
- if (pid == 0)
- return getuid();
-
- if (asprintf(&p, "/proc/%lu/status", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- f = fopen(p, "re");
- free(p);
-
- if (!f)
- return -errno;
-
- while (!feof(f)) {
- char line[LINE_MAX], *l;
-
- if (!fgets(line, sizeof(line), f)) {
- if (feof(f))
- break;
-
- r = -errno;
- goto finish;
- }
-
- l = strstrip(line);
-
- if (startswith(l, field)) {
- l += strlen(field);
- l += strspn(l, WHITESPACE);
-
- l[strcspn(l, WHITESPACE)] = 0;
-
- r = parse_uid(l, uid);
- goto finish;
- }
- }
-
- r = -EIO;
-
-finish:
- fclose(f);
-
- return r;
-}
-
-int get_process_uid(pid_t pid, uid_t *uid) {
- return get_process_id(pid, "Uid:", uid);
-}
-
-int get_process_gid(pid_t pid, gid_t *gid) {
- return get_process_id(pid, "Gid:", gid);
-}
-
-char *strnappend(const char *s, const char *suffix, size_t b) {
- size_t a;
- char *r;
-
- if (!s && !suffix)
- return strdup("");
-
- if (!s)
- return strndup(suffix, b);
-
- if (!suffix)
- return strdup(s);
-
- assert(s);
- assert(suffix);
-
- a = strlen(s);
- if (b > ((size_t) -1) - a)
- return NULL;
-
- r = new(char, a+b+1);
- if (!r)
- return NULL;
-
- memcpy(r, s, a);
- memcpy(r+a, suffix, b);
- r[a+b] = 0;
-
- return r;
-}
-
-char *strappend(const char *s, const char *suffix) {
- return strnappend(s, suffix, suffix ? strlen(suffix) : 0);
-}
-
-int readlink_malloc(const char *p, char **r) {
- size_t l = 100;
-
- assert(p);
- assert(r);
-
- for (;;) {
- char *c;
- ssize_t n;
-
- if (!(c = new(char, l)))
- return -ENOMEM;
-
- if ((n = readlink(p, c, l-1)) < 0) {
- int ret = -errno;
- free(c);
- return ret;
- }
-
- if ((size_t) n < l-1) {
- c[n] = 0;
- *r = c;
- return 0;
- }
-
- free(c);
- l *= 2;
- }
-}
-
-int readlink_and_make_absolute(const char *p, char **r) {
- char *target, *k;
- int j;
-
- assert(p);
- assert(r);
-
- if ((j = readlink_malloc(p, &target)) < 0)
- return j;
-
- k = file_in_same_dir(p, target);
- free(target);
-
- if (!k)
- return -ENOMEM;
-
- *r = k;
- return 0;
-}
-
-int readlink_and_canonicalize(const char *p, char **r) {
- char *t, *s;
- int j;
-
- assert(p);
- assert(r);
-
- j = readlink_and_make_absolute(p, &t);
- if (j < 0)
- return j;
-
- s = canonicalize_file_name(t);
- if (s) {
- free(t);
- *r = s;
- } else
- *r = t;
-
- path_kill_slashes(*r);
-
- return 0;
-}
-
-int reset_all_signal_handlers(void) {
- int sig;
-
- for (sig = 1; sig < _NSIG; sig++) {
- struct sigaction sa;
-
- if (sig == SIGKILL || sig == SIGSTOP)
- continue;
-
- zero(sa);
- sa.sa_handler = SIG_DFL;
- sa.sa_flags = SA_RESTART;
-
- /* On Linux the first two RT signals are reserved by
- * glibc, and sigaction() will return EINVAL for them. */
- if ((sigaction(sig, &sa, NULL) < 0))
- if (errno != EINVAL)
- return -errno;
- }
-
- return 0;
-}
-
-char *strstrip(char *s) {
- char *e;
-
- /* Drops trailing whitespace. Modifies the string in
- * place. Returns pointer to first non-space character */
-
- s += strspn(s, WHITESPACE);
-
- for (e = strchr(s, 0); e > s; e --)
- if (!strchr(WHITESPACE, e[-1]))
- break;
-
- *e = 0;
-
- return s;
-}
-
-char *delete_chars(char *s, const char *bad) {
- char *f, *t;
-
- /* Drops all whitespace, regardless where in the string */
-
- for (f = s, t = s; *f; f++) {
- if (strchr(bad, *f))
- continue;
-
- *(t++) = *f;
- }
-
- *t = 0;
-
- return s;
-}
-
-bool in_charset(const char *s, const char* charset) {
- const char *i;
-
- assert(s);
- assert(charset);
-
- for (i = s; *i; i++)
- if (!strchr(charset, *i))
- return false;
-
- return true;
-}
-
-char *file_in_same_dir(const char *path, const char *filename) {
- char *e, *r;
- size_t k;
-
- assert(path);
- assert(filename);
-
- /* This removes the last component of path and appends
- * filename, unless the latter is absolute anyway or the
- * former isn't */
-
- if (path_is_absolute(filename))
- return strdup(filename);
-
- if (!(e = strrchr(path, '/')))
- return strdup(filename);
-
- k = strlen(filename);
- if (!(r = new(char, e-path+1+k+1)))
- return NULL;
-
- memcpy(r, path, e-path+1);
- memcpy(r+(e-path)+1, filename, k+1);
-
- return r;
-}
-
-int rmdir_parents(const char *path, const char *stop) {
- size_t l;
- int r = 0;
-
- assert(path);
- assert(stop);
-
- l = strlen(path);
-
- /* Skip trailing slashes */
- while (l > 0 && path[l-1] == '/')
- l--;
-
- while (l > 0) {
- char *t;
-
- /* Skip last component */
- while (l > 0 && path[l-1] != '/')
- l--;
-
- /* Skip trailing slashes */
- while (l > 0 && path[l-1] == '/')
- l--;
-
- if (l <= 0)
- break;
-
- if (!(t = strndup(path, l)))
- return -ENOMEM;
-
- if (path_startswith(stop, t)) {
- free(t);
- return 0;
- }
-
- r = rmdir(t);
- free(t);
-
- if (r < 0)
- if (errno != ENOENT)
- return -errno;
- }
-
- return 0;
-}
-
-
-char hexchar(int x) {
- static const char table[16] = "0123456789abcdef";
-
- return table[x & 15];
-}
-
-int unhexchar(char c) {
-
- if (c >= '0' && c <= '9')
- return c - '0';
-
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
-
- if (c >= 'A' && c <= 'F')
- return c - 'A' + 10;
-
- return -1;
-}
-
-char octchar(int x) {
- return '0' + (x & 7);
-}
-
-int unoctchar(char c) {
-
- if (c >= '0' && c <= '7')
- return c - '0';
-
- return -1;
-}
-
-char decchar(int x) {
- return '0' + (x % 10);
-}
-
-int undecchar(char c) {
-
- if (c >= '0' && c <= '9')
- return c - '0';
-
- return -1;
-}
-
-char *cescape(const char *s) {
- char *r, *t;
- const char *f;
-
- assert(s);
-
- /* Does C style string escaping. */
-
- r = new(char, strlen(s)*4 + 1);
- if (!r)
- return NULL;
-
- for (f = s, t = r; *f; f++)
-
- switch (*f) {
-
- case '\a':
- *(t++) = '\\';
- *(t++) = 'a';
- break;
- case '\b':
- *(t++) = '\\';
- *(t++) = 'b';
- break;
- case '\f':
- *(t++) = '\\';
- *(t++) = 'f';
- break;
- case '\n':
- *(t++) = '\\';
- *(t++) = 'n';
- break;
- case '\r':
- *(t++) = '\\';
- *(t++) = 'r';
- break;
- case '\t':
- *(t++) = '\\';
- *(t++) = 't';
- break;
- case '\v':
- *(t++) = '\\';
- *(t++) = 'v';
- break;
- case '\\':
- *(t++) = '\\';
- *(t++) = '\\';
- break;
- case '"':
- *(t++) = '\\';
- *(t++) = '"';
- break;
- case '\'':
- *(t++) = '\\';
- *(t++) = '\'';
- break;
-
- default:
- /* For special chars we prefer octal over
- * hexadecimal encoding, simply because glib's
- * g_strescape() does the same */
- if ((*f < ' ') || (*f >= 127)) {
- *(t++) = '\\';
- *(t++) = octchar((unsigned char) *f >> 6);
- *(t++) = octchar((unsigned char) *f >> 3);
- *(t++) = octchar((unsigned char) *f);
- } else
- *(t++) = *f;
- break;
- }
-
- *t = 0;
-
- return r;
-}
-
-char *cunescape_length_with_prefix(const char *s, size_t length, const char *prefix) {
- char *r, *t;
- const char *f;
- size_t pl;
-
- assert(s);
-
- /* Undoes C style string escaping, and optionally prefixes it. */
-
- pl = prefix ? strlen(prefix) : 0;
-
- r = new(char, pl+length+1);
- if (!r)
- return r;
-
- if (prefix)
- memcpy(r, prefix, pl);
-
- for (f = s, t = r + pl; f < s + length; f++) {
-
- if (*f != '\\') {
- *(t++) = *f;
- continue;
- }
-
- f++;
-
- switch (*f) {
-
- case 'a':
- *(t++) = '\a';
- break;
- case 'b':
- *(t++) = '\b';
- break;
- case 'f':
- *(t++) = '\f';
- break;
- case 'n':
- *(t++) = '\n';
- break;
- case 'r':
- *(t++) = '\r';
- break;
- case 't':
- *(t++) = '\t';
- break;
- case 'v':
- *(t++) = '\v';
- break;
- case '\\':
- *(t++) = '\\';
- break;
- case '"':
- *(t++) = '"';
- break;
- case '\'':
- *(t++) = '\'';
- break;
-
- case 's':
- /* This is an extension of the XDG syntax files */
- *(t++) = ' ';
- break;
-
- case 'x': {
- /* hexadecimal encoding */
- int a, b;
-
- a = unhexchar(f[1]);
- b = unhexchar(f[2]);
-
- if (a < 0 || b < 0) {
- /* Invalid escape code, let's take it literal then */
- *(t++) = '\\';
- *(t++) = 'x';
- } else {
- *(t++) = (char) ((a << 4) | b);
- f += 2;
- }
-
- break;
- }
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7': {
- /* octal encoding */
- int a, b, c;
-
- a = unoctchar(f[0]);
- b = unoctchar(f[1]);
- c = unoctchar(f[2]);
-
- if (a < 0 || b < 0 || c < 0) {
- /* Invalid escape code, let's take it literal then */
- *(t++) = '\\';
- *(t++) = f[0];
- } else {
- *(t++) = (char) ((a << 6) | (b << 3) | c);
- f += 2;
- }
-
- break;
- }
-
- case 0:
- /* premature end of string.*/
- *(t++) = '\\';
- goto finish;
-
- default:
- /* Invalid escape code, let's take it literal then */
- *(t++) = '\\';
- *(t++) = *f;
- break;
- }
- }
-
-finish:
- *t = 0;
- return r;
-}
-
-char *cunescape_length(const char *s, size_t length) {
- return cunescape_length_with_prefix(s, length, NULL);
-}
-
-char *cunescape(const char *s) {
- assert(s);
-
- return cunescape_length(s, strlen(s));
-}
-
-char *xescape(const char *s, const char *bad) {
- char *r, *t;
- const char *f;
-
- /* Escapes all chars in bad, in addition to \ and all special
- * chars, in \xFF style escaping. May be reversed with
- * cunescape. */
-
- r = new(char, strlen(s) * 4 + 1);
- if (!r)
- return NULL;
-
- for (f = s, t = r; *f; f++) {
-
- if ((*f < ' ') || (*f >= 127) ||
- (*f == '\\') || strchr(bad, *f)) {
- *(t++) = '\\';
- *(t++) = 'x';
- *(t++) = hexchar(*f >> 4);
- *(t++) = hexchar(*f);
- } else
- *(t++) = *f;
- }
-
- *t = 0;
-
- return r;
-}
-
-char *bus_path_escape(const char *s) {
- char *r, *t;
- const char *f;
-
- assert(s);
-
- /* Escapes all chars that D-Bus' object path cannot deal
- * with. Can be reverse with bus_path_unescape() */
-
- if (!(r = new(char, strlen(s)*3+1)))
- return NULL;
-
- for (f = s, t = r; *f; f++) {
-
- if (!(*f >= 'A' && *f <= 'Z') &&
- !(*f >= 'a' && *f <= 'z') &&
- !(*f >= '0' && *f <= '9')) {
- *(t++) = '_';
- *(t++) = hexchar(*f >> 4);
- *(t++) = hexchar(*f);
- } else
- *(t++) = *f;
- }
-
- *t = 0;
-
- return r;
-}
-
-char *bus_path_unescape(const char *f) {
- char *r, *t;
-
- assert(f);
-
- if (!(r = strdup(f)))
- return NULL;
-
- for (t = r; *f; f++) {
-
- if (*f == '_') {
- int a, b;
-
- if ((a = unhexchar(f[1])) < 0 ||
- (b = unhexchar(f[2])) < 0) {
- /* Invalid escape code, let's take it literal then */
- *(t++) = '_';
- } else {
- *(t++) = (char) ((a << 4) | b);
- f += 2;
- }
- } else
- *(t++) = *f;
- }
-
- *t = 0;
-
- return r;
-}
-
-char *ascii_strlower(char *t) {
- char *p;
-
- assert(t);
-
- for (p = t; *p; p++)
- if (*p >= 'A' && *p <= 'Z')
- *p = *p - 'A' + 'a';
-
- return t;
-}
-
-static bool ignore_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, ".swp");
-}
-
-bool ignore_file(const char *filename) {
- assert(filename);
-
- if (endswith(filename, "~"))
- return false;
-
- return ignore_file_allow_backup(filename);
-}
-
-int fd_nonblock(int fd, bool nonblock) {
- int flags;
-
- assert(fd >= 0);
-
- if ((flags = fcntl(fd, F_GETFL, 0)) < 0)
- return -errno;
-
- if (nonblock)
- flags |= O_NONBLOCK;
- else
- flags &= ~O_NONBLOCK;
-
- if (fcntl(fd, F_SETFL, flags) < 0)
- return -errno;
-
- return 0;
-}
-
-int fd_cloexec(int fd, bool cloexec) {
- int flags;
-
- assert(fd >= 0);
-
- if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
- return -errno;
-
- if (cloexec)
- flags |= FD_CLOEXEC;
- else
- flags &= ~FD_CLOEXEC;
-
- if (fcntl(fd, F_SETFD, flags) < 0)
- return -errno;
-
- return 0;
-}
-
-static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
- unsigned i;
-
- assert(n_fdset == 0 || fdset);
-
- for (i = 0; i < n_fdset; i++)
- if (fdset[i] == fd)
- return true;
-
- return false;
-}
-
-int close_all_fds(const int except[], unsigned n_except) {
- DIR *d;
- struct dirent *de;
- int r = 0;
-
- assert(n_except == 0 || except);
-
- d = opendir("/proc/self/fd");
- if (!d) {
- int fd;
- struct rlimit rl;
-
- /* When /proc isn't available (for example in chroots)
- * the fallback is brute forcing through the fd
- * table */
-
- assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
- for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
-
- if (fd_in_set(fd, except, n_except))
- continue;
-
- if (close_nointr(fd) < 0)
- if (errno != EBADF && r == 0)
- r = -errno;
- }
-
- return r;
- }
-
- while ((de = readdir(d))) {
- int fd = -1;
-
- if (ignore_file(de->d_name))
- continue;
-
- if (safe_atoi(de->d_name, &fd) < 0)
- /* Let's better ignore this, just in case */
- continue;
-
- if (fd < 3)
- continue;
-
- if (fd == dirfd(d))
- continue;
-
- if (fd_in_set(fd, except, n_except))
- continue;
-
- if (close_nointr(fd) < 0) {
- /* Valgrind has its own FD and doesn't want to have it closed */
- if (errno != EBADF && r == 0)
- r = -errno;
- }
- }
-
- closedir(d);
- return r;
-}
-
-bool chars_intersect(const char *a, const char *b) {
- const char *p;
-
- /* Returns true if any of the chars in a are in b. */
- for (p = a; *p; p++)
- if (strchr(b, *p))
- return true;
-
- return false;
-}
-
-char *format_timestamp(char *buf, size_t l, usec_t t) {
- struct tm tm;
- time_t sec;
-
- assert(buf);
- assert(l > 0);
-
- if (t <= 0)
- return NULL;
-
- sec = (time_t) (t / USEC_PER_SEC);
-
- if (strftime(buf, l, "%a, %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm)) <= 0)
- return NULL;
-
- return buf;
-}
-
-char *format_timestamp_pretty(char *buf, size_t l, usec_t t) {
- usec_t n, d;
-
- n = now(CLOCK_REALTIME);
-
- if (t <= 0 || t > n || t + USEC_PER_DAY*7 <= t)
- return NULL;
-
- d = n - t;
-
- if (d >= USEC_PER_YEAR)
- snprintf(buf, l, "%llu years and %llu months ago",
- (unsigned long long) (d / USEC_PER_YEAR),
- (unsigned long long) ((d % USEC_PER_YEAR) / USEC_PER_MONTH));
- else if (d >= USEC_PER_MONTH)
- snprintf(buf, l, "%llu months and %llu days ago",
- (unsigned long long) (d / USEC_PER_MONTH),
- (unsigned long long) ((d % USEC_PER_MONTH) / USEC_PER_DAY));
- else if (d >= USEC_PER_WEEK)
- snprintf(buf, l, "%llu weeks and %llu days ago",
- (unsigned long long) (d / USEC_PER_WEEK),
- (unsigned long long) ((d % USEC_PER_WEEK) / USEC_PER_DAY));
- else if (d >= 2*USEC_PER_DAY)
- snprintf(buf, l, "%llu days ago", (unsigned long long) (d / USEC_PER_DAY));
- else if (d >= 25*USEC_PER_HOUR)
- snprintf(buf, l, "1 day and %lluh ago",
- (unsigned long long) ((d - USEC_PER_DAY) / USEC_PER_HOUR));
- else if (d >= 6*USEC_PER_HOUR)
- snprintf(buf, l, "%lluh ago",
- (unsigned long long) (d / USEC_PER_HOUR));
- else if (d >= USEC_PER_HOUR)
- snprintf(buf, l, "%lluh %llumin ago",
- (unsigned long long) (d / USEC_PER_HOUR),
- (unsigned long long) ((d % USEC_PER_HOUR) / USEC_PER_MINUTE));
- else if (d >= 5*USEC_PER_MINUTE)
- snprintf(buf, l, "%llumin ago",
- (unsigned long long) (d / USEC_PER_MINUTE));
- else if (d >= USEC_PER_MINUTE)
- snprintf(buf, l, "%llumin %llus ago",
- (unsigned long long) (d / USEC_PER_MINUTE),
- (unsigned long long) ((d % USEC_PER_MINUTE) / USEC_PER_SEC));
- else if (d >= USEC_PER_SEC)
- snprintf(buf, l, "%llus ago",
- (unsigned long long) (d / USEC_PER_SEC));
- else if (d >= USEC_PER_MSEC)
- snprintf(buf, l, "%llums ago",
- (unsigned long long) (d / USEC_PER_MSEC));
- else if (d > 0)
- snprintf(buf, l, "%lluus ago",
- (unsigned long long) d);
- else
- snprintf(buf, l, "now");
-
- buf[l-1] = 0;
- return buf;
-}
-
-char *format_timespan(char *buf, size_t l, usec_t t) {
- static const struct {
- const char *suffix;
- usec_t usec;
- } table[] = {
- { "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;
- char *p = buf;
-
- assert(buf);
- assert(l > 0);
-
- if (t == (usec_t) -1)
- return NULL;
-
- if (t == 0) {
- snprintf(p, l, "0");
- p[l-1] = 0;
- return p;
- }
-
- /* The result of this function can be parsed with parse_usec */
-
- for (i = 0; i < ELEMENTSOF(table); i++) {
- int k;
- size_t n;
-
- if (t < table[i].usec)
- continue;
-
- if (l <= 1)
- break;
-
- k = snprintf(p, l, "%s%llu%s", p > buf ? " " : "", (unsigned long long) (t / table[i].usec), table[i].suffix);
- n = MIN((size_t) k, l);
-
- l -= n;
- p += n;
-
- t %= table[i].usec;
- }
-
- *p = 0;
-
- return buf;
-}
-
-bool fstype_is_network(const char *fstype) {
- static const char table[] =
- "cifs\0"
- "smbfs\0"
- "ncpfs\0"
- "nfs\0"
- "nfs4\0"
- "gfs\0"
- "gfs2\0";
-
- return nulstr_contains(table, fstype);
-}
-
-int chvt(int vt) {
- _cleanup_close_ int fd;
-
- fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- if (vt < 0) {
- int tiocl[2] = {
- TIOCL_GETKMSGREDIRECT,
- 0
- };
-
- if (ioctl(fd, TIOCLINUX, tiocl) < 0)
- return -errno;
-
- vt = tiocl[0] <= 0 ? 1 : tiocl[0];
- }
-
- if (ioctl(fd, VT_ACTIVATE, vt) < 0)
- return -errno;
-
- return 0;
-}
-
-int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
- struct termios old_termios, new_termios;
- char c;
- char line[LINE_MAX];
-
- assert(f);
- assert(ret);
-
- if (tcgetattr(fileno(f), &old_termios) >= 0) {
- new_termios = old_termios;
-
- new_termios.c_lflag &= ~ICANON;
- new_termios.c_cc[VMIN] = 1;
- new_termios.c_cc[VTIME] = 0;
-
- if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
- size_t k;
-
- if (t != (usec_t) -1) {
- if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) {
- tcsetattr(fileno(f), TCSADRAIN, &old_termios);
- return -ETIMEDOUT;
- }
- }
-
- k = fread(&c, 1, 1, f);
-
- tcsetattr(fileno(f), TCSADRAIN, &old_termios);
-
- if (k <= 0)
- return -EIO;
-
- if (need_nl)
- *need_nl = c != '\n';
-
- *ret = c;
- return 0;
- }
- }
-
- if (t != (usec_t) -1)
- if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0)
- return -ETIMEDOUT;
-
- if (!fgets(line, sizeof(line), f))
- return -EIO;
-
- truncate_nl(line);
-
- if (strlen(line) != 1)
- return -EBADMSG;
-
- if (need_nl)
- *need_nl = false;
-
- *ret = line[0];
- return 0;
-}
-
-int ask(char *ret, const char *replies, const char *text, ...) {
-
- assert(ret);
- assert(replies);
- assert(text);
-
- for (;;) {
- va_list ap;
- char c;
- int r;
- bool need_nl = true;
-
- if (on_tty())
- fputs(ANSI_HIGHLIGHT_ON, stdout);
-
- va_start(ap, text);
- vprintf(text, ap);
- va_end(ap);
-
- if (on_tty())
- fputs(ANSI_HIGHLIGHT_OFF, stdout);
-
- fflush(stdout);
-
- r = read_one_char(stdin, &c, (usec_t) -1, &need_nl);
- if (r < 0) {
-
- if (r == -EBADMSG) {
- puts("Bad input, please try again.");
- continue;
- }
-
- putchar('\n');
- return r;
- }
-
- if (need_nl)
- putchar('\n');
-
- if (strchr(replies, c)) {
- *ret = c;
- return 0;
- }
-
- puts("Read unexpected character, please try again.");
- }
-}
-
-int reset_terminal_fd(int fd, bool switch_to_text) {
- struct termios termios;
- int r = 0;
-
- /* Set terminal to some sane defaults */
-
- assert(fd >= 0);
-
- /* We leave locked terminal attributes untouched, so that
- * Plymouth may set whatever it wants to set, and we don't
- * interfere with that. */
-
- /* Disable exclusive mode, just in case */
- ioctl(fd, TIOCNXCL);
-
- /* Switch to text mode */
- if (switch_to_text)
- ioctl(fd, KDSETMODE, KD_TEXT);
-
- /* Enable console unicode mode */
- ioctl(fd, KDSKBMODE, K_UNICODE);
-
- if (tcgetattr(fd, &termios) < 0) {
- r = -errno;
- goto finish;
- }
-
- /* We only reset the stuff that matters to the software. How
- * hardware is set up we don't touch assuming that somebody
- * else will do that for us */
-
- termios.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | IUCLC);
- termios.c_iflag |= ICRNL | IMAXBEL | IUTF8;
- termios.c_oflag |= ONLCR;
- termios.c_cflag |= CREAD;
- termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOPRT | ECHOKE;
-
- termios.c_cc[VINTR] = 03; /* ^C */
- termios.c_cc[VQUIT] = 034; /* ^\ */
- termios.c_cc[VERASE] = 0177;
- termios.c_cc[VKILL] = 025; /* ^X */
- termios.c_cc[VEOF] = 04; /* ^D */
- termios.c_cc[VSTART] = 021; /* ^Q */
- termios.c_cc[VSTOP] = 023; /* ^S */
- termios.c_cc[VSUSP] = 032; /* ^Z */
- termios.c_cc[VLNEXT] = 026; /* ^V */
- termios.c_cc[VWERASE] = 027; /* ^W */
- termios.c_cc[VREPRINT] = 022; /* ^R */
- termios.c_cc[VEOL] = 0;
- termios.c_cc[VEOL2] = 0;
-
- termios.c_cc[VTIME] = 0;
- termios.c_cc[VMIN] = 1;
-
- if (tcsetattr(fd, TCSANOW, &termios) < 0)
- r = -errno;
-
-finish:
- /* Just in case, flush all crap out */
- tcflush(fd, TCIOFLUSH);
-
- return r;
-}
-
-int reset_terminal(const char *name) {
- int fd, r;
-
- fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return fd;
-
- r = reset_terminal_fd(fd, true);
- close_nointr_nofail(fd);
-
- return r;
-}
-
-int open_terminal(const char *name, int mode) {
- int fd, r;
- unsigned c = 0;
-
- /*
- * If a TTY is in the process of being closed opening it might
- * cause EIO. This is horribly awful, but unlikely to be
- * changed in the kernel. Hence we work around this problem by
- * retrying a couple of times.
- *
- * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245
- */
-
- for (;;) {
- fd = open(name, mode);
- if (fd >= 0)
- break;
-
- if (errno != EIO)
- return -errno;
-
- /* Max 1s in total */
- if (c >= 20)
- return -errno;
-
- usleep(50 * USEC_PER_MSEC);
- c++;
- }
-
- if (fd < 0)
- return -errno;
-
- r = isatty(fd);
- if (r < 0) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- if (!r) {
- close_nointr_nofail(fd);
- return -ENOTTY;
- }
-
- return fd;
-}
-
-int flush_fd(int fd) {
- struct pollfd pollfd;
-
- zero(pollfd);
- pollfd.fd = fd;
- pollfd.events = POLLIN;
-
- for (;;) {
- char buf[LINE_MAX];
- ssize_t l;
- int r;
-
- if ((r = poll(&pollfd, 1, 0)) < 0) {
-
- if (errno == EINTR)
- continue;
-
- return -errno;
- }
-
- if (r == 0)
- return 0;
-
- if ((l = read(fd, buf, sizeof(buf))) < 0) {
-
- if (errno == EINTR)
- continue;
-
- if (errno == EAGAIN)
- return 0;
-
- return -errno;
- }
-
- if (l <= 0)
- return 0;
- }
-}
-
-int acquire_terminal(
- const char *name,
- bool fail,
- bool force,
- bool ignore_tiocstty_eperm,
- usec_t timeout) {
-
- int fd = -1, notify = -1, r = 0, wd = -1;
- usec_t ts = 0;
- struct sigaction sa_old, sa_new;
-
- assert(name);
-
- /* We use inotify to be notified when the tty is closed. We
- * create the watch before checking if we can actually acquire
- * it, so that we don't lose any event.
- *
- * Note: strictly speaking this actually watches for the
- * device being closed, it does *not* really watch whether a
- * tty loses its controlling process. However, unless some
- * rogue process uses TIOCNOTTY on /dev/tty *after* closing
- * its tty otherwise this will not become a problem. As long
- * as the administrator makes sure not configure any service
- * on the same tty as an untrusted user this should not be a
- * problem. (Which he probably should not do anyway.) */
-
- if (timeout != (usec_t) -1)
- ts = now(CLOCK_MONOTONIC);
-
- if (!fail && !force) {
- notify = inotify_init1(IN_CLOEXEC | (timeout != (usec_t) -1 ? IN_NONBLOCK : 0));
- if (notify < 0) {
- r = -errno;
- goto fail;
- }
-
- wd = inotify_add_watch(notify, name, IN_CLOSE);
- if (wd < 0) {
- r = -errno;
- goto fail;
- }
- }
-
- for (;;) {
- if (notify >= 0) {
- r = flush_fd(notify);
- if (r < 0)
- goto fail;
- }
-
- /* We pass here O_NOCTTY only so that we can check the return
- * value TIOCSCTTY and have a reliable way to figure out if we
- * successfully became the controlling process of the tty */
- fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return fd;
-
- /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
- * if we already own the tty. */
- zero(sa_new);
- sa_new.sa_handler = SIG_IGN;
- sa_new.sa_flags = SA_RESTART;
- assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
-
- /* First, try to get the tty */
- if (ioctl(fd, TIOCSCTTY, force) < 0)
- r = -errno;
-
- assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
-
- /* Sometimes it makes sense to ignore TIOCSCTTY
- * returning EPERM, i.e. when very likely we already
- * are have this controlling terminal. */
- if (r < 0 && r == -EPERM && ignore_tiocstty_eperm)
- r = 0;
-
- if (r < 0 && (force || fail || r != -EPERM)) {
- goto fail;
- }
-
- if (r >= 0)
- break;
-
- assert(!fail);
- assert(!force);
- assert(notify >= 0);
-
- for (;;) {
- uint8_t inotify_buffer[sizeof(struct inotify_event) + FILENAME_MAX];
- ssize_t l;
- struct inotify_event *e;
-
- if (timeout != (usec_t) -1) {
- usec_t n;
-
- n = now(CLOCK_MONOTONIC);
- if (ts + timeout < n) {
- r = -ETIMEDOUT;
- goto fail;
- }
-
- r = fd_wait_for_event(fd, POLLIN, ts + timeout - n);
- if (r < 0)
- goto fail;
-
- if (r == 0) {
- r = -ETIMEDOUT;
- goto fail;
- }
- }
-
- l = read(notify, inotify_buffer, sizeof(inotify_buffer));
- if (l < 0) {
-
- if (errno == EINTR || errno == EAGAIN)
- continue;
-
- r = -errno;
- goto fail;
- }
-
- e = (struct inotify_event*) inotify_buffer;
-
- while (l > 0) {
- size_t step;
-
- if (e->wd != wd || !(e->mask & IN_CLOSE)) {
- r = -EIO;
- goto fail;
- }
-
- step = sizeof(struct inotify_event) + e->len;
- assert(step <= (size_t) l);
-
- e = (struct inotify_event*) ((uint8_t*) e + step);
- l -= step;
- }
-
- break;
- }
-
- /* We close the tty fd here since if the old session
- * ended our handle will be dead. It's important that
- * we do this after sleeping, so that we don't enter
- * an endless loop. */
- close_nointr_nofail(fd);
- }
-
- if (notify >= 0)
- close_nointr_nofail(notify);
-
- r = reset_terminal_fd(fd, true);
- if (r < 0)
- log_warning("Failed to reset terminal: %s", strerror(-r));
-
- return fd;
-
-fail:
- if (fd >= 0)
- close_nointr_nofail(fd);
-
- if (notify >= 0)
- close_nointr_nofail(notify);
-
- return r;
-}
-
-int release_terminal(void) {
- int r = 0, fd;
- struct sigaction sa_old, sa_new;
-
- if ((fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY|O_CLOEXEC)) < 0)
- return -errno;
-
- /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
- * by our own TIOCNOTTY */
-
- zero(sa_new);
- sa_new.sa_handler = SIG_IGN;
- sa_new.sa_flags = SA_RESTART;
- assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
-
- if (ioctl(fd, TIOCNOTTY) < 0)
- r = -errno;
-
- assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
-
- close_nointr_nofail(fd);
- return r;
-}
-
-int sigaction_many(const struct sigaction *sa, ...) {
- va_list ap;
- int r = 0, sig;
-
- va_start(ap, sa);
- while ((sig = va_arg(ap, int)) > 0)
- if (sigaction(sig, sa, NULL) < 0)
- r = -errno;
- va_end(ap);
-
- return r;
-}
-
-int ignore_signals(int sig, ...) {
- struct sigaction sa;
- va_list ap;
- int r = 0;
-
- zero(sa);
- sa.sa_handler = SIG_IGN;
- sa.sa_flags = SA_RESTART;
-
- if (sigaction(sig, &sa, NULL) < 0)
- r = -errno;
-
- va_start(ap, sig);
- while ((sig = va_arg(ap, int)) > 0)
- if (sigaction(sig, &sa, NULL) < 0)
- r = -errno;
- va_end(ap);
-
- return r;
-}
-
-int default_signals(int sig, ...) {
- struct sigaction sa;
- va_list ap;
- int r = 0;
-
- zero(sa);
- sa.sa_handler = SIG_DFL;
- sa.sa_flags = SA_RESTART;
-
- if (sigaction(sig, &sa, NULL) < 0)
- r = -errno;
-
- va_start(ap, sig);
- while ((sig = va_arg(ap, int)) > 0)
- if (sigaction(sig, &sa, NULL) < 0)
- r = -errno;
- va_end(ap);
-
- return r;
-}
-
-int close_pipe(int p[]) {
- int a = 0, b = 0;
-
- assert(p);
-
- if (p[0] >= 0) {
- a = close_nointr(p[0]);
- p[0] = -1;
- }
-
- if (p[1] >= 0) {
- b = close_nointr(p[1]);
- p[1] = -1;
- }
-
- return a < 0 ? a : b;
-}
-
-ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
- uint8_t *p;
- ssize_t n = 0;
-
- assert(fd >= 0);
- assert(buf);
-
- p = buf;
-
- while (nbytes > 0) {
- ssize_t k;
-
- if ((k = read(fd, p, nbytes)) <= 0) {
-
- if (k < 0 && errno == EINTR)
- continue;
-
- if (k < 0 && errno == EAGAIN && do_poll) {
- struct pollfd pollfd;
-
- zero(pollfd);
- pollfd.fd = fd;
- pollfd.events = POLLIN;
-
- if (poll(&pollfd, 1, -1) < 0) {
- if (errno == EINTR)
- continue;
-
- return n > 0 ? n : -errno;
- }
-
- if (pollfd.revents != POLLIN)
- return n > 0 ? n : -EIO;
-
- continue;
- }
-
- return n > 0 ? n : (k < 0 ? -errno : 0);
- }
-
- p += k;
- nbytes -= k;
- n += k;
- }
-
- return n;
-}
-
-ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
- const uint8_t *p;
- ssize_t n = 0;
-
- assert(fd >= 0);
- assert(buf);
-
- p = buf;
-
- while (nbytes > 0) {
- ssize_t k;
-
- k = write(fd, p, nbytes);
- if (k <= 0) {
-
- if (k < 0 && errno == EINTR)
- continue;
-
- if (k < 0 && errno == EAGAIN && do_poll) {
- struct pollfd pollfd;
-
- zero(pollfd);
- pollfd.fd = fd;
- pollfd.events = POLLOUT;
-
- if (poll(&pollfd, 1, -1) < 0) {
- if (errno == EINTR)
- continue;
-
- return n > 0 ? n : -errno;
- }
-
- if (pollfd.revents != POLLOUT)
- return n > 0 ? n : -EIO;
-
- continue;
- }
-
- return n > 0 ? n : (k < 0 ? -errno : 0);
- }
-
- p += k;
- nbytes -= k;
- n += k;
- }
-
- return n;
-}
-
-int parse_usec(const char *t, usec_t *usec) {
- 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 },
- { "minutes", USEC_PER_MINUTE },
- { "minute", USEC_PER_MINUTE },
- { "min", USEC_PER_MINUTE },
- { "months", USEC_PER_MONTH },
- { "month", 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 },
- { "", USEC_PER_SEC }, /* default is sec */
- };
-
- const char *p;
- usec_t r = 0;
-
- assert(t);
- assert(usec);
-
- p = t;
- do {
- long long l;
- char *e;
- unsigned i;
-
- errno = 0;
- l = strtoll(p, &e, 10);
-
- if (errno != 0)
- return -errno;
-
- if (l < 0)
- return -ERANGE;
-
- if (e == p)
- return -EINVAL;
-
- e += strspn(e, WHITESPACE);
-
- for (i = 0; i < ELEMENTSOF(table); i++)
- if (startswith(e, table[i].suffix)) {
- r += (usec_t) l * table[i].usec;
- p = e + strlen(table[i].suffix);
- break;
- }
-
- if (i >= ELEMENTSOF(table))
- return -EINVAL;
-
- } while (*p != 0);
-
- *usec = r;
-
- return 0;
-}
-
-int parse_nsec(const char *t, nsec_t *nsec) {
- static const struct {
- const char *suffix;
- nsec_t nsec;
- } table[] = {
- { "seconds", NSEC_PER_SEC },
- { "second", NSEC_PER_SEC },
- { "sec", NSEC_PER_SEC },
- { "s", NSEC_PER_SEC },
- { "minutes", NSEC_PER_MINUTE },
- { "minute", NSEC_PER_MINUTE },
- { "min", NSEC_PER_MINUTE },
- { "months", NSEC_PER_MONTH },
- { "month", NSEC_PER_MONTH },
- { "msec", NSEC_PER_MSEC },
- { "ms", NSEC_PER_MSEC },
- { "m", NSEC_PER_MINUTE },
- { "hours", NSEC_PER_HOUR },
- { "hour", NSEC_PER_HOUR },
- { "hr", NSEC_PER_HOUR },
- { "h", NSEC_PER_HOUR },
- { "days", NSEC_PER_DAY },
- { "day", NSEC_PER_DAY },
- { "d", NSEC_PER_DAY },
- { "weeks", NSEC_PER_WEEK },
- { "week", NSEC_PER_WEEK },
- { "w", NSEC_PER_WEEK },
- { "years", NSEC_PER_YEAR },
- { "year", NSEC_PER_YEAR },
- { "y", NSEC_PER_YEAR },
- { "usec", NSEC_PER_USEC },
- { "us", NSEC_PER_USEC },
- { "nsec", 1ULL },
- { "ns", 1ULL },
- { "", 1ULL }, /* default is nsec */
- };
-
- const char *p;
- nsec_t r = 0;
-
- assert(t);
- assert(nsec);
-
- p = t;
- do {
- long long l;
- char *e;
- unsigned i;
-
- errno = 0;
- l = strtoll(p, &e, 10);
-
- if (errno != 0)
- return -errno;
-
- if (l < 0)
- return -ERANGE;
-
- if (e == p)
- return -EINVAL;
-
- e += strspn(e, WHITESPACE);
-
- for (i = 0; i < ELEMENTSOF(table); i++)
- if (startswith(e, table[i].suffix)) {
- r += (nsec_t) l * table[i].nsec;
- p = e + strlen(table[i].suffix);
- break;
- }
-
- if (i >= ELEMENTSOF(table))
- return -EINVAL;
-
- } while (*p != 0);
-
- *nsec = r;
-
- return 0;
-}
-
-int parse_bytes(const char *t, off_t *bytes) {
- static const struct {
- const char *suffix;
- off_t factor;
- } table[] = {
- { "B", 1 },
- { "K", 1024ULL },
- { "M", 1024ULL*1024ULL },
- { "G", 1024ULL*1024ULL*1024ULL },
- { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
- { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
- { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
- { "", 1 },
- };
-
- const char *p;
- off_t r = 0;
-
- assert(t);
- assert(bytes);
-
- p = t;
- do {
- long long l;
- char *e;
- unsigned i;
-
- errno = 0;
- l = strtoll(p, &e, 10);
-
- if (errno != 0)
- return -errno;
-
- if (l < 0)
- return -ERANGE;
-
- if (e == p)
- return -EINVAL;
-
- e += strspn(e, WHITESPACE);
-
- for (i = 0; i < ELEMENTSOF(table); i++)
- if (startswith(e, table[i].suffix)) {
- r += (off_t) l * table[i].factor;
- p = e + strlen(table[i].suffix);
- break;
- }
-
- if (i >= ELEMENTSOF(table))
- return -EINVAL;
-
- } while (*p != 0);
-
- *bytes = r;
-
- return 0;
-}
-
-int make_stdio(int fd) {
- int r, s, t;
-
- assert(fd >= 0);
-
- r = dup3(fd, STDIN_FILENO, 0);
- s = dup3(fd, STDOUT_FILENO, 0);
- t = dup3(fd, STDERR_FILENO, 0);
-
- if (fd >= 3)
- close_nointr_nofail(fd);
-
- if (r < 0 || s < 0 || t < 0)
- return -errno;
-
- /* We rely here that the new fd has O_CLOEXEC not set */
-
- return 0;
-}
-
-int make_null_stdio(void) {
- int null_fd;
-
- null_fd = open("/dev/null", O_RDWR|O_NOCTTY);
- if (null_fd < 0)
- return -errno;
-
- return make_stdio(null_fd);
-}
-
-bool is_device_path(const char *path) {
-
- /* Returns true on paths that refer to a device, either in
- * sysfs or in /dev */
-
- return
- path_startswith(path, "/dev/") ||
- path_startswith(path, "/sys/");
-}
-
-int dir_is_empty(const char *path) {
- _cleanup_closedir_ DIR *d;
- int r;
-
- d = opendir(path);
- if (!d)
- return -errno;
-
- for (;;) {
- struct dirent *de;
- union dirent_storage buf;
-
- r = readdir_r(d, &buf.de, &de);
- if (r > 0)
- return -r;
-
- if (!de)
- return 1;
-
- if (!ignore_file(de->d_name))
- return 0;
- }
-}
-
-unsigned long long random_ull(void) {
- _cleanup_close_ int fd;
- uint64_t ull;
- ssize_t r;
-
- fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0)
- goto fallback;
-
- r = loop_read(fd, &ull, sizeof(ull), true);
- if (r != sizeof(ull))
- goto fallback;
-
- return ull;
-
-fallback:
- return random() * RAND_MAX + random();
-}
-
-void rename_process(const char name[8]) {
- assert(name);
-
- /* This is a like a poor man's setproctitle(). It changes the
- * comm field, argv[0], and also the glibc's internally used
- * name of the process. For the first one a limit of 16 chars
- * applies, to the second one usually one of 10 (i.e. length
- * of "/sbin/init"), to the third one one of 7 (i.e. length of
- * "systemd"). If you pass a longer string it will be
- * truncated */
-
- prctl(PR_SET_NAME, name);
-
- if (program_invocation_name)
- strncpy(program_invocation_name, name, strlen(program_invocation_name));
-
- if (saved_argc > 0) {
- int i;
-
- if (saved_argv[0])
- strncpy(saved_argv[0], name, strlen(saved_argv[0]));
-
- for (i = 1; i < saved_argc; i++) {
- if (!saved_argv[i])
- break;
-
- memset(saved_argv[i], 0, strlen(saved_argv[i]));
- }
- }
-}
-
-void sigset_add_many(sigset_t *ss, ...) {
- va_list ap;
- int sig;
-
- assert(ss);
-
- va_start(ap, ss);
- while ((sig = va_arg(ap, int)) > 0)
- assert_se(sigaddset(ss, sig) == 0);
- va_end(ap);
-}
-
-char* gethostname_malloc(void) {
- struct utsname u;
-
- assert_se(uname(&u) >= 0);
-
- if (!isempty(u.nodename) && !streq(u.nodename, "(none)"))
- return strdup(u.nodename);
-
- return strdup(u.sysname);
-}
-
-bool hostname_is_set(void) {
- struct utsname u;
-
- assert_se(uname(&u) >= 0);
-
- return !isempty(u.nodename) && !streq(u.nodename, "(none)");
-}
-
-static char *lookup_uid(uid_t uid) {
- long bufsize;
- char *name;
- _cleanup_free_ char *buf = NULL;
- struct passwd pwbuf, *pw = NULL;
-
- /* Shortcut things to avoid NSS lookups */
- if (uid == 0)
- return strdup("root");
-
- bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
- if (bufsize <= 0)
- bufsize = 4096;
-
- buf = malloc(bufsize);
- if (!buf)
- return NULL;
-
- if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw)
- return strdup(pw->pw_name);
-
- if (asprintf(&name, "%lu", (unsigned long) uid) < 0)
- return NULL;
-
- return name;
-}
-
-char* getlogname_malloc(void) {
- uid_t uid;
- struct stat st;
-
- if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
- uid = st.st_uid;
- else
- uid = getuid();
-
- return lookup_uid(uid);
-}
-
-char *getusername_malloc(void) {
- const char *e;
-
- e = getenv("USER");
- if (e)
- return strdup(e);
-
- return lookup_uid(getuid());
-}
-
-int getttyname_malloc(int fd, char **r) {
- char path[PATH_MAX], *c;
- int k;
-
- assert(r);
-
- k = ttyname_r(fd, path, sizeof(path));
- if (k != 0)
- return -k;
-
- char_array_0(path);
-
- c = strdup(startswith(path, "/dev/") ? path + 5 : path);
- if (!c)
- return -ENOMEM;
-
- *r = c;
- return 0;
-}
-
-int getttyname_harder(int fd, char **r) {
- int k;
- char *s;
-
- k = getttyname_malloc(fd, &s);
- if (k < 0)
- return k;
-
- if (streq(s, "tty")) {
- free(s);
- return get_ctty(0, NULL, r);
- }
-
- *r = s;
- return 0;
-}
-
-int get_ctty_devnr(pid_t pid, dev_t *d) {
- int k;
- char line[LINE_MAX], *p, *fn;
- unsigned long ttynr;
- FILE *f;
-
- if (asprintf(&fn, "/proc/%lu/stat", (unsigned long) (pid <= 0 ? getpid() : pid)) < 0)
- return -ENOMEM;
-
- f = fopen(fn, "re");
- free(fn);
- if (!f)
- return -errno;
-
- if (!fgets(line, sizeof(line), f)) {
- k = feof(f) ? -EIO : -errno;
- fclose(f);
- return k;
- }
-
- fclose(f);
-
- p = strrchr(line, ')');
- if (!p)
- return -EIO;
-
- p++;
-
- if (sscanf(p, " "
- "%*c " /* state */
- "%*d " /* ppid */
- "%*d " /* pgrp */
- "%*d " /* session */
- "%lu ", /* ttynr */
- &ttynr) != 1)
- return -EIO;
-
- *d = (dev_t) ttynr;
- return 0;
-}
-
-int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
- int k;
- char fn[PATH_MAX], *s, *b, *p;
- dev_t devnr;
-
- assert(r);
-
- k = get_ctty_devnr(pid, &devnr);
- if (k < 0)
- return k;
-
- snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr));
- char_array_0(fn);
-
- if ((k = readlink_malloc(fn, &s)) < 0) {
-
- if (k != -ENOENT)
- return k;
-
- /* This is an ugly hack */
- if (major(devnr) == 136) {
- if (asprintf(&b, "pts/%lu", (unsigned long) minor(devnr)) < 0)
- return -ENOMEM;
-
- *r = b;
- if (_devnr)
- *_devnr = devnr;
-
- return 0;
- }
-
- /* Probably something like the ptys which have no
- * symlink in /dev/char. Let's return something
- * vaguely useful. */
-
- if (!(b = strdup(fn + 5)))
- return -ENOMEM;
-
- *r = b;
- if (_devnr)
- *_devnr = devnr;
-
- return 0;
- }
-
- if (startswith(s, "/dev/"))
- p = s + 5;
- else if (startswith(s, "../"))
- p = s + 3;
- else
- p = s;
-
- b = strdup(p);
- free(s);
-
- if (!b)
- return -ENOMEM;
-
- *r = b;
- if (_devnr)
- *_devnr = devnr;
-
- return 0;
-}
-
-int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
- DIR *d;
- int ret = 0;
-
- assert(fd >= 0);
-
- /* This returns the first error we run into, but nevertheless
- * tries to go on. This closes the passed fd. */
-
- d = fdopendir(fd);
- if (!d) {
- close_nointr_nofail(fd);
-
- return errno == ENOENT ? 0 : -errno;
- }
-
- for (;;) {
- struct dirent *de;
- union dirent_storage buf;
- bool is_dir, keep_around;
- struct stat st;
- int r;
-
- r = readdir_r(d, &buf.de, &de);
- if (r != 0 && ret == 0) {
- ret = -r;
- break;
- }
-
- if (!de)
- break;
-
- if (streq(de->d_name, ".") || streq(de->d_name, ".."))
- continue;
-
- if (de->d_type == DT_UNKNOWN ||
- honour_sticky ||
- (de->d_type == DT_DIR && root_dev)) {
- if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
- if (ret == 0 && errno != ENOENT)
- ret = -errno;
- continue;
- }
-
- is_dir = S_ISDIR(st.st_mode);
- keep_around =
- honour_sticky &&
- (st.st_uid == 0 || st.st_uid == getuid()) &&
- (st.st_mode & S_ISVTX);
- } else {
- is_dir = de->d_type == DT_DIR;
- keep_around = false;
- }
-
- if (is_dir) {
- int subdir_fd;
-
- /* if root_dev is set, remove subdirectories only, if device is same as dir */
- if (root_dev && st.st_dev != root_dev->st_dev)
- continue;
-
- subdir_fd = openat(fd, de->d_name,
- O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
- if (subdir_fd < 0) {
- if (ret == 0 && errno != ENOENT)
- ret = -errno;
- continue;
- }
-
- r = rm_rf_children_dangerous(subdir_fd, only_dirs, honour_sticky, root_dev);
- if (r < 0 && ret == 0)
- ret = r;
-
- if (!keep_around)
- if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
- if (ret == 0 && errno != ENOENT)
- ret = -errno;
- }
-
- } else if (!only_dirs && !keep_around) {
-
- if (unlinkat(fd, de->d_name, 0) < 0) {
- if (ret == 0 && errno != ENOENT)
- ret = -errno;
- }
- }
- }
-
- closedir(d);
-
- return ret;
-}
-
-int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
- struct statfs s;
-
- assert(fd >= 0);
-
- if (fstatfs(fd, &s) < 0) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- /* We refuse to clean disk file systems with this call. This
- * is extra paranoia just to be sure we never ever remove
- * non-state data */
-
- if (s.f_type != TMPFS_MAGIC &&
- s.f_type != RAMFS_MAGIC) {
- log_error("Attempted to remove disk file system, and we can't allow that.");
- close_nointr_nofail(fd);
- return -EPERM;
- }
-
- return rm_rf_children_dangerous(fd, only_dirs, honour_sticky, root_dev);
-}
-
-static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bool honour_sticky, bool dangerous) {
- int fd, r;
- struct statfs s;
-
- assert(path);
-
- /* We refuse to clean the root file system with this
- * call. This is extra paranoia to never cause a really
- * seriously broken system. */
- if (path_equal(path, "/")) {
- log_error("Attempted to remove entire root file system, and we can't allow that.");
- return -EPERM;
- }
-
- fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
- if (fd < 0) {
-
- if (errno != ENOTDIR)
- return -errno;
-
- if (!dangerous) {
- if (statfs(path, &s) < 0)
- return -errno;
-
- if (s.f_type != TMPFS_MAGIC &&
- s.f_type != RAMFS_MAGIC) {
- log_error("Attempted to remove disk file system, and we can't allow that.");
- return -EPERM;
- }
- }
-
- if (delete_root && !only_dirs)
- if (unlink(path) < 0 && errno != ENOENT)
- return -errno;
-
- return 0;
- }
-
- if (!dangerous) {
- if (fstatfs(fd, &s) < 0) {
- close_nointr_nofail(fd);
- return -errno;
- }
-
- if (s.f_type != TMPFS_MAGIC &&
- s.f_type != RAMFS_MAGIC) {
- log_error("Attempted to remove disk file system, and we can't allow that.");
- close_nointr_nofail(fd);
- return -EPERM;
- }
- }
-
- r = rm_rf_children_dangerous(fd, only_dirs, honour_sticky, NULL);
- if (delete_root) {
-
- if (honour_sticky && file_is_priv_sticky(path) > 0)
- return r;
-
- if (rmdir(path) < 0 && errno != ENOENT) {
- if (r == 0)
- r = -errno;
- }
- }
-
- return r;
-}
-
-int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
- return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, false);
-}
-
-int rm_rf_dangerous(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
- return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, true);
-}
-
-int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
- assert(path);
-
- /* 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_t) -1)
- if (chmod(path, mode) < 0)
- return -errno;
-
- if (uid != (uid_t) -1 || gid != (gid_t) -1)
- if (chown(path, uid, gid) < 0)
- return -errno;
-
- return 0;
-}
-
-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 (fchmod(fd, mode) < 0)
- return -errno;
-
- if (fchown(fd, uid, gid) < 0)
- return -errno;
-
- return 0;
-}
-
-cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
- cpu_set_t *r;
- unsigned n = 1024;
-
- /* Allocates the cpuset in the right size */
-
- for (;;) {
- if (!(r = CPU_ALLOC(n)))
- return NULL;
-
- if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
- CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
-
- if (ncpus)
- *ncpus = n;
-
- return r;
- }
-
- CPU_FREE(r);
-
- if (errno != EINVAL)
- return NULL;
-
- n *= 2;
- }
-}
-
-int status_vprintf(const char *status, bool ellipse, const char *format, va_list ap) {
- static const char status_indent[] = " "; /* "[" STATUS "] " */
- _cleanup_free_ char *s = NULL;
- _cleanup_close_ int fd = -1;
- struct iovec iovec[5];
- int n = 0;
-
- assert(format);
-
- /* This is independent of logging, as status messages are
- * optional and go exclusively to the console. */
-
- if (vasprintf(&s, format, ap) < 0)
- return log_oom();
-
- fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return fd;
-
- if (ellipse) {
- char *e;
- size_t emax, sl;
- int c;
-
- c = fd_columns(fd);
- if (c <= 0)
- c = 80;
-
- sl = status ? sizeof(status_indent)-1 : 0;
-
- emax = c - sl - 1;
- if (emax < 3)
- emax = 3;
-
- e = ellipsize(s, emax, 75);
- if (e) {
- free(s);
- s = e;
- }
- }
-
- zero(iovec);
-
- if (status) {
- if (!isempty(status)) {
- IOVEC_SET_STRING(iovec[n++], "[");
- IOVEC_SET_STRING(iovec[n++], status);
- IOVEC_SET_STRING(iovec[n++], "] ");
- } else
- IOVEC_SET_STRING(iovec[n++], status_indent);
- }
-
- IOVEC_SET_STRING(iovec[n++], s);
- IOVEC_SET_STRING(iovec[n++], "\n");
-
- if (writev(fd, iovec, n) < 0)
- return -errno;
-
- return 0;
-}
-
-int status_printf(const char *status, bool ellipse, const char *format, ...) {
- va_list ap;
- int r;
-
- assert(format);
-
- va_start(ap, format);
- r = status_vprintf(status, ellipse, format, ap);
- va_end(ap);
-
- return r;
-}
-
-int status_welcome(void) {
- int r;
- _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
-
- r = parse_env_file("/etc/os-release", NEWLINE,
- "PRETTY_NAME", &pretty_name,
- "ANSI_COLOR", &ansi_color,
- NULL);
- if (r < 0 && r != -ENOENT)
- log_warning("Failed to read /etc/os-release: %s", strerror(-r));
-
- return status_printf(NULL, false,
- "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
- isempty(ansi_color) ? "1" : ansi_color,
- isempty(pretty_name) ? "Linux" : pretty_name);
-}
-
-char *replace_env(const char *format, char **env) {
- enum {
- WORD,
- CURLY,
- VARIABLE
- } state = WORD;
-
- const char *e, *word = format;
- char *r = NULL, *k;
-
- assert(format);
-
- for (e = format; *e; e ++) {
-
- switch (state) {
-
- case WORD:
- if (*e == '$')
- state = CURLY;
- break;
-
- case CURLY:
- if (*e == '{') {
- if (!(k = strnappend(r, word, e-word-1)))
- goto fail;
-
- free(r);
- r = k;
-
- word = e-1;
- state = VARIABLE;
-
- } else if (*e == '$') {
- if (!(k = strnappend(r, word, e-word)))
- goto fail;
-
- free(r);
- r = k;
-
- word = e+1;
- state = WORD;
- } else
- state = WORD;
- break;
-
- case VARIABLE:
- if (*e == '}') {
- const char *t;
-
- if (!(t = strv_env_get_with_length(env, word+2, e-word-2)))
- t = "";
-
- if (!(k = strappend(r, t)))
- goto fail;
-
- free(r);
- r = k;
-
- word = e+1;
- state = WORD;
- }
- break;
- }
- }
-
- if (!(k = strnappend(r, word, e-word)))
- goto fail;
-
- free(r);
- return k;
-
-fail:
- free(r);
- return NULL;
-}
-
-char **replace_env_argv(char **argv, char **env) {
- char **r, **i;
- unsigned k = 0, l = 0;
-
- l = strv_length(argv);
-
- if (!(r = new(char*, l+1)))
- return NULL;
-
- STRV_FOREACH(i, argv) {
-
- /* If $FOO appears as single word, replace it by the split up variable */
- if ((*i)[0] == '$' && (*i)[1] != '{') {
- char *e;
- char **w, **m;
- unsigned q;
-
- if ((e = strv_env_get(env, *i+1))) {
-
- if (!(m = strv_split_quoted(e))) {
- r[k] = NULL;
- strv_free(r);
- return NULL;
- }
- } else
- m = NULL;
-
- q = strv_length(m);
- l = l + q - 1;
-
- if (!(w = realloc(r, sizeof(char*) * (l+1)))) {
- r[k] = NULL;
- strv_free(r);
- strv_free(m);
- return NULL;
- }
-
- r = w;
- if (m) {
- memcpy(r + k, m, q * sizeof(char*));
- free(m);
- }
-
- k += q;
- continue;
- }
-
- /* If ${FOO} appears as part of a word, replace it by the variable as-is */
- if (!(r[k++] = replace_env(*i, env))) {
- strv_free(r);
- return NULL;
- }
- }
-
- r[k] = NULL;
- return r;
-}
-
-int fd_columns(int fd) {
- struct winsize ws;
- zero(ws);
-
- if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
- return -errno;
-
- if (ws.ws_col <= 0)
- return -EIO;
-
- return ws.ws_col;
-}
-
-unsigned columns(void) {
- const char *e;
- unsigned c;
-
- if (_likely_(cached_columns > 0))
- return cached_columns;
-
- c = 0;
- e = getenv("COLUMNS");
- if (e)
- safe_atou(e, &c);
-
- if (c <= 0)
- c = fd_columns(STDOUT_FILENO);
-
- if (c <= 0)
- c = 80;
-
- cached_columns = c;
- return c;
-}
-
-int fd_lines(int fd) {
- struct winsize ws;
- zero(ws);
-
- if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
- return -errno;
-
- if (ws.ws_row <= 0)
- return -EIO;
-
- return ws.ws_row;
-}
-
-unsigned lines(void) {
- const char *e;
- unsigned l;
-
- if (_likely_(cached_lines > 0))
- return cached_lines;
-
- l = 0;
- e = getenv("LINES");
- if (e)
- safe_atou(e, &l);
-
- if (l <= 0)
- l = fd_lines(STDOUT_FILENO);
-
- if (l <= 0)
- l = 24;
-
- cached_lines = l;
- return cached_lines;
-}
-
-/* intended to be used as a SIGWINCH sighandler */
-void columns_lines_cache_reset(int signum) {
- cached_columns = 0;
- cached_lines = 0;
-}
-
-bool on_tty(void) {
- static int cached_on_tty = -1;
-
- if (_unlikely_(cached_on_tty < 0))
- cached_on_tty = isatty(STDOUT_FILENO) > 0;
-
- return cached_on_tty;
-}
-
-int running_in_chroot(void) {
- struct stat a, b;
-
- zero(a);
- zero(b);
-
- /* Only works as root */
-
- if (stat("/proc/1/root", &a) < 0)
- return -errno;
-
- if (stat("/", &b) < 0)
- return -errno;
-
- return
- a.st_dev != b.st_dev ||
- a.st_ino != b.st_ino;
-}
-
-char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
- size_t x;
- char *r;
-
- assert(s);
- assert(percent <= 100);
- assert(new_length >= 3);
-
- if (old_length <= 3 || old_length <= new_length)
- return strndup(s, old_length);
-
- r = new0(char, new_length+1);
- if (!r)
- return r;
-
- x = (new_length * percent) / 100;
-
- if (x > new_length - 3)
- x = new_length - 3;
-
- memcpy(r, s, x);
- r[x] = '.';
- r[x+1] = '.';
- r[x+2] = '.';
- memcpy(r + x + 3,
- s + old_length - (new_length - x - 3),
- new_length - x - 3);
-
- return r;
-}
-
-char *ellipsize(const char *s, size_t length, unsigned percent) {
- return ellipsize_mem(s, strlen(s), length, percent);
-}
-
-int touch(const char *path) {
- int fd;
-
- assert(path);
-
- /* This just opens the file for writing, ensuring it
- * exists. It doesn't call utimensat() the way /usr/bin/touch
- * does it. */
-
- fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644);
- if (fd < 0)
- return -errno;
-
- close_nointr_nofail(fd);
- return 0;
-}
-
-char *unquote(const char *s, const char* quotes) {
- size_t l;
- assert(s);
-
- /* This is rather stupid, simply removes the heading and
- * trailing quotes if there is one. Doesn't care about
- * escaping or anything. We should make this smarter one
- * day...*/
-
- l = strlen(s);
- if (l < 2)
- return strdup(s);
-
- if (strchr(quotes, s[0]) && s[l-1] == s[0])
- return strndup(s+1, l-2);
-
- return strdup(s);
-}
-
-char *normalize_env_assignment(const char *s) {
- _cleanup_free_ char *name = NULL, *value = NULL, *p = NULL;
- char *eq, *r;
-
- eq = strchr(s, '=');
- if (!eq) {
- char *t;
-
- r = strdup(s);
- if (!r)
- return NULL;
-
- t = strstrip(r);
- if (t == r)
- return r;
-
- memmove(r, t, strlen(t) + 1);
- return r;
- }
-
- name = strndup(s, eq - s);
- if (!name)
- return NULL;
-
- p = strdup(eq + 1);
- if (!p)
- return NULL;
-
- value = unquote(strstrip(p), QUOTES);
- if (!value)
- return NULL;
-
- if (asprintf(&r, "%s=%s", strstrip(name), value) < 0)
- r = NULL;
-
- return r;
-}
-
-int wait_for_terminate(pid_t pid, siginfo_t *status) {
- siginfo_t dummy;
-
- assert(pid >= 1);
-
- if (!status)
- status = &dummy;
-
- for (;;) {
- zero(*status);
-
- if (waitid(P_PID, pid, status, WEXITED) < 0) {
-
- if (errno == EINTR)
- continue;
-
- return -errno;
- }
-
- return 0;
- }
-}
-
-int wait_for_terminate_and_warn(const char *name, pid_t pid) {
- int r;
- siginfo_t status;
-
- assert(name);
- assert(pid > 1);
-
- r = wait_for_terminate(pid, &status);
- if (r < 0) {
- log_warning("Failed to wait for %s: %s", name, strerror(-r));
- return r;
- }
-
- if (status.si_code == CLD_EXITED) {
- if (status.si_status != 0) {
- log_warning("%s failed with error code %i.", name, status.si_status);
- return status.si_status;
- }
-
- log_debug("%s succeeded.", name);
- return 0;
-
- } else if (status.si_code == CLD_KILLED ||
- status.si_code == CLD_DUMPED) {
-
- log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
- return -EPROTO;
- }
-
- log_warning("%s failed due to unknown reason.", name);
- return -EPROTO;
-}
-
-_noreturn_ void freeze(void) {
-
- /* Make sure nobody waits for us on a socket anymore */
- close_all_fds(NULL, 0);
-
- sync();
-
- for (;;)
- pause();
-}
-
-bool null_or_empty(struct stat *st) {
- assert(st);
-
- if (S_ISREG(st->st_mode) && st->st_size <= 0)
- return true;
-
- if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
- return true;
-
- return false;
-}
-
-int null_or_empty_path(const char *fn) {
- struct stat st;
-
- assert(fn);
-
- if (stat(fn, &st) < 0)
- return -errno;
-
- return null_or_empty(&st);
-}
-
-DIR *xopendirat(int fd, const char *name, int flags) {
- int nfd;
- DIR *d;
-
- nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags);
- if (nfd < 0)
- return NULL;
-
- d = fdopendir(nfd);
- if (!d) {
- close_nointr_nofail(nfd);
- return NULL;
- }
-
- return d;
-}
-
-int signal_from_string_try_harder(const char *s) {
- int signo;
- assert(s);
-
- signo = signal_from_string(s);
- if (signo <= 0)
- if (startswith(s, "SIG"))
- return signal_from_string(s+3);
-
- return signo;
-}
-
-void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t) {
-
- assert(f);
- assert(name);
- assert(t);
-
- if (!dual_timestamp_is_set(t))
- return;
-
- fprintf(f, "%s=%llu %llu\n",
- name,
- (unsigned long long) t->realtime,
- (unsigned long long) t->monotonic);
-}
-
-void dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
- unsigned long long a, b;
-
- assert(value);
- assert(t);
-
- if (sscanf(value, "%lli %llu", &a, &b) != 2)
- log_debug("Failed to parse finish timestamp value %s", value);
- else {
- t->realtime = a;
- t->monotonic = b;
- }
-}
-
-static char *tag_to_udev_node(const char *tagvalue, const char *by) {
- char *dn, *t, *u;
- int r;
-
- /* FIXME: to follow udev's logic 100% we need to leave valid
- * UTF8 chars unescaped */
-
- u = unquote(tagvalue, "\"\'");
- if (u == NULL)
- return NULL;
-
- t = xescape(u, "/ ");
- free(u);
-
- if (t == NULL)
- return NULL;
-
- r = asprintf(&dn, "/dev/disk/by-%s/%s", by, t);
- free(t);
-
- if (r < 0)
- return NULL;
-
- return dn;
-}
-
-char *fstab_node_to_udev_node(const char *p) {
- assert(p);
-
- if (startswith(p, "LABEL="))
- return tag_to_udev_node(p+6, "label");
-
- if (startswith(p, "UUID="))
- return tag_to_udev_node(p+5, "uuid");
-
- if (startswith(p, "PARTUUID="))
- return tag_to_udev_node(p+9, "partuuid");
-
- if (startswith(p, "PARTLABEL="))
- return tag_to_udev_node(p+10, "partlabel");
-
- return strdup(p);
-}
-
-bool tty_is_vc(const char *tty) {
- assert(tty);
-
- if (startswith(tty, "/dev/"))
- tty += 5;
-
- return vtnr_from_tty(tty) >= 0;
-}
-
-bool tty_is_console(const char *tty) {
- assert(tty);
-
- if (startswith(tty, "/dev/"))
- tty += 5;
-
- return streq(tty, "console");
-}
-
-int vtnr_from_tty(const char *tty) {
- int i, r;
-
- assert(tty);
-
- if (startswith(tty, "/dev/"))
- tty += 5;
-
- if (!startswith(tty, "tty") )
- return -EINVAL;
-
- if (tty[3] < '0' || tty[3] > '9')
- return -EINVAL;
-
- r = safe_atoi(tty+3, &i);
- if (r < 0)
- return r;
-
- if (i < 0 || i > 63)
- return -EINVAL;
-
- return i;
-}
-
-bool tty_is_vc_resolve(const char *tty) {
- char *active = NULL;
- bool b;
-
- assert(tty);
-
- if (startswith(tty, "/dev/"))
- tty += 5;
-
- /* Resolve where /dev/console is pointing to, if /sys is
- * actually ours (i.e. not read-only-mounted which is a sign
- * for container setups) */
- if (streq(tty, "console") && path_is_read_only_fs("/sys") <= 0)
- if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
- /* If multiple log outputs are configured the
- * last one is what /dev/console points to */
- tty = strrchr(active, ' ');
- if (tty)
- tty++;
- else
- tty = active;
- }
-
- b = tty_is_vc(tty);
- free(active);
-
- return b;
-}
-
-const char *default_term_for_tty(const char *tty) {
- assert(tty);
-
- return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt102";
-}
-
-bool dirent_is_file(const struct dirent *de) {
- assert(de);
-
- if (ignore_file(de->d_name))
- return false;
-
- if (de->d_type != DT_REG &&
- de->d_type != DT_LNK &&
- de->d_type != DT_UNKNOWN)
- return false;
-
- return true;
-}
-
-bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
- assert(de);
-
- if (de->d_type != DT_REG &&
- de->d_type != DT_LNK &&
- de->d_type != DT_UNKNOWN)
- return false;
-
- if (ignore_file_allow_backup(de->d_name))
- return false;
-
- return endswith(de->d_name, suffix);
-}
-
-int execute_command(const char *command, char *const argv[])
-{
-
- pid_t pid;
- int status;
-
- if ((status = access(command, X_OK)) != 0)
- return status;
-
- if ((pid = fork()) < 0) {
- log_error("Failed to fork: %m");
- return pid;
- }
-
- if (pid == 0) {
-
- execv(command, argv);
-
- log_error("Failed to execute %s: %m", command);
- _exit(EXIT_FAILURE);
- }
- else while (1)
- {
- siginfo_t si;
-
- int r = waitid(P_PID, pid, &si, WEXITED);
-
- if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
- if (si.si_code == CLD_EXITED)
- log_error("%s exited with exit status %i.", command, si.si_status);
- else
- log_error("%s terminated by signal %s.", command, signal_to_string(si.si_status));
- } else
- log_debug("%s exited successfully.", command);
-
- return si.si_status;
-
- }
-}
-
-void execute_directory(const char *directory, DIR *d, char *argv[]) {
- DIR *_d = NULL;
- struct dirent *de;
- Hashmap *pids = NULL;
-
- assert(directory);
-
- /* Executes all binaries in a directory in parallel and waits
- * until all they all finished. */
-
- if (!d) {
- if (!(_d = opendir(directory))) {
-
- if (errno == ENOENT)
- return;
-
- log_error("Failed to enumerate directory %s: %m", directory);
- return;
- }
-
- d = _d;
- }
-
- if (!(pids = hashmap_new(trivial_hash_func, trivial_compare_func))) {
- log_error("Failed to allocate set.");
- goto finish;
- }
-
- while ((de = readdir(d))) {
- char *path;
- pid_t pid;
- int k;
-
- if (!dirent_is_file(de))
- continue;
-
- if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) {
- log_oom();
- continue;
- }
-
- if ((pid = fork()) < 0) {
- log_error("Failed to fork: %m");
- free(path);
- continue;
- }
-
- if (pid == 0) {
- char *_argv[2];
- /* Child */
-
- if (!argv) {
- _argv[0] = path;
- _argv[1] = NULL;
- argv = _argv;
- } else
- argv[0] = path;
-
- execv(path, argv);
-
- log_error("Failed to execute %s: %m", path);
- _exit(EXIT_FAILURE);
- }
-
- log_debug("Spawned %s as %lu", path, (unsigned long) pid);
-
- if ((k = hashmap_put(pids, UINT_TO_PTR(pid), path)) < 0) {
- log_error("Failed to add PID to set: %s", strerror(-k));
- free(path);
- }
- }
-
- while (!hashmap_isempty(pids)) {
- pid_t pid = PTR_TO_UINT(hashmap_first_key(pids));
- siginfo_t si;
- char *path;
-
- zero(si);
- if (waitid(P_PID, pid, &si, WEXITED) < 0) {
-
- if (errno == EINTR)
- continue;
-
- log_error("waitid() failed: %m");
- goto finish;
- }
-
- if ((path = hashmap_remove(pids, UINT_TO_PTR(si.si_pid)))) {
- if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
- if (si.si_code == CLD_EXITED)
- log_error("%s exited with exit status %i.", path, si.si_status);
- else
- log_error("%s terminated by signal %s.", path, signal_to_string(si.si_status));
- } else
- log_debug("%s exited successfully.", path);
-
- free(path);
- }
- }
-
-finish:
- if (_d)
- closedir(_d);
-
- if (pids)
- hashmap_free_free(pids);
-}
-
-int kill_and_sigcont(pid_t pid, int sig) {
- int r;
-
- r = kill(pid, sig) < 0 ? -errno : 0;
-
- if (r >= 0)
- kill(pid, SIGCONT);
-
- return r;
-}
-
-bool nulstr_contains(const char*nulstr, const char *needle) {
- const char *i;
-
- if (!nulstr)
- return false;
-
- NULSTR_FOREACH(i, nulstr)
- if (streq(i, needle))
- return true;
-
- return false;
-}
-
-bool plymouth_running(void) {
- return access("/run/plymouth/pid", F_OK) >= 0;
-}
-
-char* strshorten(char *s, size_t l) {
- assert(s);
-
- if (l < strlen(s))
- s[l] = 0;
-
- return s;
-}
-
-static bool hostname_valid_char(char c) {
- return
- (c >= 'a' && c <= 'z') ||
- (c >= 'A' && c <= 'Z') ||
- (c >= '0' && c <= '9') ||
- c == '-' ||
- c == '_' ||
- c == '.';
-}
-
-bool hostname_is_valid(const char *s) {
- const char *p;
-
- if (isempty(s))
- return false;
-
- for (p = s; *p; p++)
- if (!hostname_valid_char(*p))
- return false;
-
- if (p-s > HOST_NAME_MAX)
- return false;
-
- return true;
-}
-
-char* hostname_cleanup(char *s) {
- char *p, *d;
-
- for (p = s, d = s; *p; p++)
- if ((*p >= 'a' && *p <= 'z') ||
- (*p >= 'A' && *p <= 'Z') ||
- (*p >= '0' && *p <= '9') ||
- *p == '-' ||
- *p == '_' ||
- *p == '.')
- *(d++) = *p;
-
- *d = 0;
-
- strshorten(s, HOST_NAME_MAX);
- return s;
-}
-
-int pipe_eof(int fd) {
- struct pollfd pollfd;
- int r;
-
- zero(pollfd);
- pollfd.fd = fd;
- pollfd.events = POLLIN|POLLHUP;
-
- r = poll(&pollfd, 1, 0);
- if (r < 0)
- return -errno;
-
- if (r == 0)
- return 0;
-
- return pollfd.revents & POLLHUP;
-}
-
-int fd_wait_for_event(int fd, int event, usec_t t) {
- struct pollfd pollfd;
- int r;
-
- zero(pollfd);
- pollfd.fd = fd;
- pollfd.events = event;
-
- r = poll(&pollfd, 1, t == (usec_t) -1 ? -1 : (int) (t / USEC_PER_MSEC));
- if (r < 0)
- return -errno;
-
- if (r == 0)
- return 0;
-
- return pollfd.revents;
-}
-
-int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
- FILE *f;
- char *t;
- const char *fn;
- size_t k;
- int fd;
-
- assert(path);
- assert(_f);
- assert(_temp_path);
-
- t = new(char, strlen(path) + 1 + 6 + 1);
- if (!t)
- return -ENOMEM;
-
- fn = path_get_file_name(path);
- k = fn-path;
- memcpy(t, path, k);
- t[k] = '.';
- stpcpy(stpcpy(t+k+1, fn), "XXXXXX");
-
- fd = mkostemp(t, O_WRONLY|O_CLOEXEC);
- if (fd < 0) {
- free(t);
- return -errno;
- }
-
- f = fdopen(fd, "we");
- if (!f) {
- unlink(t);
- free(t);
- return -errno;
- }
-
- *_f = f;
- *_temp_path = t;
-
- return 0;
-}
-
-int terminal_vhangup_fd(int fd) {
- assert(fd >= 0);
-
- if (ioctl(fd, TIOCVHANGUP) < 0)
- return -errno;
-
- return 0;
-}
-
-int terminal_vhangup(const char *name) {
- int fd, r;
-
- fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return fd;
-
- r = terminal_vhangup_fd(fd);
- close_nointr_nofail(fd);
-
- return r;
-}
-
-int vt_disallocate(const char *name) {
- int fd, r;
- unsigned u;
-
- /* Deallocate the VT if possible. If not possible
- * (i.e. because it is the active one), at least clear it
- * entirely (including the scrollback buffer) */
-
- if (!startswith(name, "/dev/"))
- return -EINVAL;
-
- if (!tty_is_vc(name)) {
- /* So this is not a VT. I guess we cannot deallocate
- * it then. But let's at least clear the screen */
-
- fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return fd;
-
- loop_write(fd,
- "\033[r" /* clear scrolling region */
- "\033[H" /* move home */
- "\033[2J", /* clear screen */
- 10, false);
- close_nointr_nofail(fd);
-
- return 0;
- }
-
- if (!startswith(name, "/dev/tty"))
- return -EINVAL;
-
- r = safe_atou(name+8, &u);
- if (r < 0)
- return r;
-
- if (u <= 0)
- return -EINVAL;
-
- /* Try to deallocate */
- fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return fd;
-
- r = ioctl(fd, VT_DISALLOCATE, u);
- close_nointr_nofail(fd);
-
- if (r >= 0)
- return 0;
-
- if (errno != EBUSY)
- return -errno;
-
- /* Couldn't deallocate, so let's clear it fully with
- * scrollback */
- fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return fd;
-
- loop_write(fd,
- "\033[r" /* clear scrolling region */
- "\033[H" /* move home */
- "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
- 10, false);
- close_nointr_nofail(fd);
-
- return 0;
-}
-
-int copy_file(const char *from, const char *to) {
- int r, fdf, fdt;
-
- assert(from);
- assert(to);
-
- fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fdf < 0)
- return -errno;
-
- fdt = open(to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY, 0644);
- if (fdt < 0) {
- close_nointr_nofail(fdf);
- return -errno;
- }
-
- for (;;) {
- char buf[PIPE_BUF];
- ssize_t n, k;
-
- n = read(fdf, buf, sizeof(buf));
- if (n < 0) {
- r = -errno;
-
- close_nointr_nofail(fdf);
- close_nointr(fdt);
- unlink(to);
-
- return r;
- }
-
- if (n == 0)
- break;
-
- errno = 0;
- k = loop_write(fdt, buf, n, false);
- if (n != k) {
- r = k < 0 ? k : (errno ? -errno : -EIO);
-
- close_nointr_nofail(fdf);
- close_nointr(fdt);
-
- unlink(to);
- return r;
- }
- }
-
- close_nointr_nofail(fdf);
- r = close_nointr(fdt);
-
- if (r < 0) {
- unlink(to);
- return r;
- }
-
- return 0;
-}
-
-int symlink_atomic(const char *from, const char *to) {
- char *x;
- _cleanup_free_ char *t;
- const char *fn;
- size_t k;
- unsigned long long ull;
- unsigned i;
- int r;
-
- assert(from);
- assert(to);
-
- t = new(char, strlen(to) + 1 + 16 + 1);
- if (!t)
- return -ENOMEM;
-
- fn = path_get_file_name(to);
- k = fn-to;
- memcpy(t, to, k);
- t[k] = '.';
- x = stpcpy(t+k+1, fn);
-
- ull = random_ull();
- for (i = 0; i < 16; i++) {
- *(x++) = hexchar(ull & 0xF);
- ull >>= 4;
- }
-
- *x = 0;
-
- if (symlink(from, t) < 0)
- return -errno;
-
- if (rename(t, to) < 0) {
- r = -errno;
- unlink(t);
- return r;
- }
-
- return 0;
-}
-
-bool display_is_local(const char *display) {
- assert(display);
-
- return
- display[0] == ':' &&
- display[1] >= '0' &&
- display[1] <= '9';
-}
-
-int socket_from_display(const char *display, char **path) {
- size_t k;
- char *f, *c;
-
- assert(display);
- assert(path);
-
- if (!display_is_local(display))
- return -EINVAL;
-
- k = strspn(display+1, "0123456789");
-
- f = new(char, sizeof("/tmp/.X11-unix/X") + k);
- if (!f)
- return -ENOMEM;
-
- c = stpcpy(f, "/tmp/.X11-unix/X");
- memcpy(c, display+1, k);
- c[k] = 0;
-
- *path = f;
-
- return 0;
-}
-
-int get_user_creds(
- const char **username,
- uid_t *uid, gid_t *gid,
- const char **home,
- const char **shell) {
-
- struct passwd *p;
- uid_t u;
-
- assert(username);
- assert(*username);
-
- /* We enforce some special rules for uid=0: in order to avoid
- * NSS lookups for root we hardcode its data. */
-
- if (streq(*username, "root") || streq(*username, "0")) {
- *username = "root";
-
- if (uid)
- *uid = 0;
-
- if (gid)
- *gid = 0;
-
- if (home)
- *home = "/root";
-
- if (shell)
- *shell = "/bin/sh";
-
- return 0;
- }
-
- if (parse_uid(*username, &u) >= 0) {
- errno = 0;
- p = getpwuid(u);
-
- /* If there are multiple users with the same id, make
- * sure to leave $USER to the configured value instead
- * of the first occurrence in the database. However if
- * the uid was configured by a numeric uid, then let's
- * pick the real username from /etc/passwd. */
- if (p)
- *username = p->pw_name;
- } else {
- errno = 0;
- p = getpwnam(*username);
- }
-
- if (!p)
- return errno != 0 ? -errno : -ESRCH;
-
- if (uid)
- *uid = p->pw_uid;
-
- if (gid)
- *gid = p->pw_gid;
-
- if (home)
- *home = p->pw_dir;
-
- if (shell)
- *shell = p->pw_shell;
-
- return 0;
-}
-
-int get_group_creds(const char **groupname, gid_t *gid) {
- struct group *g;
- gid_t id;
-
- assert(groupname);
-
- /* We enforce some special rules for gid=0: in order to avoid
- * NSS lookups for root we hardcode its data. */
-
- if (streq(*groupname, "root") || streq(*groupname, "0")) {
- *groupname = "root";
-
- if (gid)
- *gid = 0;
-
- return 0;
- }
-
- if (parse_gid(*groupname, &id) >= 0) {
- errno = 0;
- g = getgrgid(id);
-
- if (g)
- *groupname = g->gr_name;
- } else {
- errno = 0;
- g = getgrnam(*groupname);
- }
-
- if (!g)
- return errno != 0 ? -errno : -ESRCH;
-
- if (gid)
- *gid = g->gr_gid;
-
- return 0;
-}
-
-int in_group(const char *name) {
- gid_t gid, *gids;
- int ngroups_max, r, i;
-
- r = get_group_creds(&name, &gid);
- if (r < 0)
- return r;
-
- if (getgid() == gid)
- return 1;
-
- if (getegid() == gid)
- return 1;
-
- ngroups_max = sysconf(_SC_NGROUPS_MAX);
- assert(ngroups_max > 0);
-
- gids = alloca(sizeof(gid_t) * ngroups_max);
-
- r = getgroups(ngroups_max, gids);
- if (r < 0)
- return -errno;
-
- for (i = 0; i < r; i++)
- if (gids[i] == gid)
- return 1;
-
- return 0;
-}
-
-int glob_exists(const char *path) {
- glob_t g;
- int r, k;
-
- assert(path);
-
- zero(g);
- errno = 0;
- k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
-
- if (k == GLOB_NOMATCH)
- r = 0;
- else if (k == GLOB_NOSPACE)
- r = -ENOMEM;
- else if (k == 0)
- r = !strv_isempty(g.gl_pathv);
- else
- r = errno ? -errno : -EIO;
-
- globfree(&g);
-
- return r;
-}
-
-int dirent_ensure_type(DIR *d, struct dirent *de) {
- struct stat st;
-
- assert(d);
- assert(de);
-
- if (de->d_type != DT_UNKNOWN)
- return 0;
-
- if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
- return -errno;
-
- de->d_type =
- S_ISREG(st.st_mode) ? DT_REG :
- S_ISDIR(st.st_mode) ? DT_DIR :
- S_ISLNK(st.st_mode) ? DT_LNK :
- S_ISFIFO(st.st_mode) ? DT_FIFO :
- S_ISSOCK(st.st_mode) ? DT_SOCK :
- S_ISCHR(st.st_mode) ? DT_CHR :
- S_ISBLK(st.st_mode) ? DT_BLK :
- DT_UNKNOWN;
-
- return 0;
-}
-
-int in_search_path(const char *path, char **search) {
- char **i, *parent;
- int r;
-
- r = path_get_parent(path, &parent);
- if (r < 0)
- return r;
-
- r = 0;
-
- STRV_FOREACH(i, search) {
- if (path_equal(parent, *i)) {
- r = 1;
- break;
- }
- }
-
- free(parent);
-
- return r;
-}
-
-int get_files_in_directory(const char *path, char ***list) {
- DIR *d;
- int r = 0;
- unsigned n = 0;
- char **l = NULL;
-
- assert(path);
-
- /* Returns all files in a directory in *list, and the number
- * of files as return value. If list is NULL returns only the
- * number */
-
- d = opendir(path);
- if (!d)
- return -errno;
-
- for (;;) {
- struct dirent *de;
- union dirent_storage buf;
- int k;
-
- k = readdir_r(d, &buf.de, &de);
- if (k != 0) {
- r = -k;
- goto finish;
- }
-
- if (!de)
- break;
-
- dirent_ensure_type(d, de);
-
- if (!dirent_is_file(de))
- continue;
-
- if (list) {
- if ((unsigned) r >= n) {
- char **t;
-
- n = MAX(16, 2*r);
- t = realloc(l, sizeof(char*) * n);
- if (!t) {
- r = -ENOMEM;
- goto finish;
- }
-
- l = t;
- }
-
- assert((unsigned) r < n);
-
- l[r] = strdup(de->d_name);
- if (!l[r]) {
- r = -ENOMEM;
- goto finish;
- }
-
- l[++r] = NULL;
- } else
- r++;
- }
-
-finish:
- if (d)
- closedir(d);
-
- if (r >= 0) {
- if (list)
- *list = l;
- } else
- strv_free(l);
-
- return r;
-}
-
-char *strjoin(const char *x, ...) {
- va_list ap;
- size_t l;
- char *r, *p;
-
- va_start(ap, x);
-
- if (x) {
- l = strlen(x);
-
- for (;;) {
- const char *t;
- size_t n;
-
- t = va_arg(ap, const char *);
- if (!t)
- break;
-
- n = strlen(t);
- if (n > ((size_t) -1) - l) {
- va_end(ap);
- return NULL;
- }
-
- l += n;
- }
- } else
- l = 0;
-
- va_end(ap);
-
- r = new(char, l+1);
- if (!r)
- return NULL;
-
- if (x) {
- p = stpcpy(r, x);
-
- va_start(ap, x);
-
- for (;;) {
- const char *t;
-
- t = va_arg(ap, const char *);
- if (!t)
- break;
-
- p = stpcpy(p, t);
- }
-
- va_end(ap);
- } else
- r[0] = 0;
-
- return r;
-}
-
-bool is_main_thread(void) {
- static __thread int cached = 0;
-
- if (_unlikely_(cached == 0))
- cached = getpid() == gettid() ? 1 : -1;
-
- return cached > 0;
-}
-
-int block_get_whole_disk(dev_t d, dev_t *ret) {
- char *p, *s;
- int r;
- unsigned n, m;
-
- assert(ret);
-
- /* If it has a queue this is good enough for us */
- if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
- return -ENOMEM;
-
- r = access(p, F_OK);
- free(p);
-
- if (r >= 0) {
- *ret = d;
- return 0;
- }
-
- /* If it is a partition find the originating device */
- if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
- return -ENOMEM;
-
- r = access(p, F_OK);
- free(p);
-
- if (r < 0)
- return -ENOENT;
-
- /* Get parent dev_t */
- if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
- return -ENOMEM;
-
- r = read_one_line_file(p, &s);
- free(p);
-
- if (r < 0)
- return r;
-
- r = sscanf(s, "%u:%u", &m, &n);
- free(s);
-
- if (r != 2)
- return -EINVAL;
-
- /* Only return this if it is really good enough for us. */
- if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
- return -ENOMEM;
-
- r = access(p, F_OK);
- free(p);
-
- if (r >= 0) {
- *ret = makedev(m, n);
- return 0;
- }
-
- return -ENOENT;
-}
-
-int file_is_priv_sticky(const char *p) {
- struct stat st;
-
- assert(p);
-
- if (lstat(p, &st) < 0)
- return -errno;
-
- return
- (st.st_uid == 0 || st.st_uid == getuid()) &&
- (st.st_mode & S_ISVTX);
-}
-
-static const char *const ioprio_class_table[] = {
- [IOPRIO_CLASS_NONE] = "none",
- [IOPRIO_CLASS_RT] = "realtime",
- [IOPRIO_CLASS_BE] = "best-effort",
- [IOPRIO_CLASS_IDLE] = "idle"
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
-
-static const char *const sigchld_code_table[] = {
- [CLD_EXITED] = "exited",
- [CLD_KILLED] = "killed",
- [CLD_DUMPED] = "dumped",
- [CLD_TRAPPED] = "trapped",
- [CLD_STOPPED] = "stopped",
- [CLD_CONTINUED] = "continued",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
-
-static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
- [LOG_FAC(LOG_KERN)] = "kern",
- [LOG_FAC(LOG_USER)] = "user",
- [LOG_FAC(LOG_MAIL)] = "mail",
- [LOG_FAC(LOG_DAEMON)] = "daemon",
- [LOG_FAC(LOG_AUTH)] = "auth",
- [LOG_FAC(LOG_SYSLOG)] = "syslog",
- [LOG_FAC(LOG_LPR)] = "lpr",
- [LOG_FAC(LOG_NEWS)] = "news",
- [LOG_FAC(LOG_UUCP)] = "uucp",
- [LOG_FAC(LOG_CRON)] = "cron",
- [LOG_FAC(LOG_AUTHPRIV)] = "authpriv",
- [LOG_FAC(LOG_FTP)] = "ftp",
- [LOG_FAC(LOG_LOCAL0)] = "local0",
- [LOG_FAC(LOG_LOCAL1)] = "local1",
- [LOG_FAC(LOG_LOCAL2)] = "local2",
- [LOG_FAC(LOG_LOCAL3)] = "local3",
- [LOG_FAC(LOG_LOCAL4)] = "local4",
- [LOG_FAC(LOG_LOCAL5)] = "local5",
- [LOG_FAC(LOG_LOCAL6)] = "local6",
- [LOG_FAC(LOG_LOCAL7)] = "local7"
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
-
-static const char *const log_level_table[] = {
- [LOG_EMERG] = "emerg",
- [LOG_ALERT] = "alert",
- [LOG_CRIT] = "crit",
- [LOG_ERR] = "err",
- [LOG_WARNING] = "warning",
- [LOG_NOTICE] = "notice",
- [LOG_INFO] = "info",
- [LOG_DEBUG] = "debug"
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
-
-static const char* const sched_policy_table[] = {
- [SCHED_OTHER] = "other",
- [SCHED_BATCH] = "batch",
- [SCHED_IDLE] = "idle",
- [SCHED_FIFO] = "fifo",
- [SCHED_RR] = "rr"
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
-
-static const char* const rlimit_table[] = {
- [RLIMIT_CPU] = "LimitCPU",
- [RLIMIT_FSIZE] = "LimitFSIZE",
- [RLIMIT_DATA] = "LimitDATA",
- [RLIMIT_STACK] = "LimitSTACK",
- [RLIMIT_CORE] = "LimitCORE",
- [RLIMIT_RSS] = "LimitRSS",
- [RLIMIT_NOFILE] = "LimitNOFILE",
- [RLIMIT_AS] = "LimitAS",
- [RLIMIT_NPROC] = "LimitNPROC",
- [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
- [RLIMIT_LOCKS] = "LimitLOCKS",
- [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
- [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
- [RLIMIT_NICE] = "LimitNICE",
- [RLIMIT_RTPRIO] = "LimitRTPRIO",
- [RLIMIT_RTTIME] = "LimitRTTIME"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
-
-static const char* const ip_tos_table[] = {
- [IPTOS_LOWDELAY] = "low-delay",
- [IPTOS_THROUGHPUT] = "throughput",
- [IPTOS_RELIABILITY] = "reliability",
- [IPTOS_LOWCOST] = "low-cost",
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
-
-static const char *const __signal_table[] = {
- [SIGHUP] = "HUP",
- [SIGINT] = "INT",
- [SIGQUIT] = "QUIT",
- [SIGILL] = "ILL",
- [SIGTRAP] = "TRAP",
- [SIGABRT] = "ABRT",
- [SIGBUS] = "BUS",
- [SIGFPE] = "FPE",
- [SIGKILL] = "KILL",
- [SIGUSR1] = "USR1",
- [SIGSEGV] = "SEGV",
- [SIGUSR2] = "USR2",
- [SIGPIPE] = "PIPE",
- [SIGALRM] = "ALRM",
- [SIGTERM] = "TERM",
-#ifdef SIGSTKFLT
- [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
-#endif
- [SIGCHLD] = "CHLD",
- [SIGCONT] = "CONT",
- [SIGSTOP] = "STOP",
- [SIGTSTP] = "TSTP",
- [SIGTTIN] = "TTIN",
- [SIGTTOU] = "TTOU",
- [SIGURG] = "URG",
- [SIGXCPU] = "XCPU",
- [SIGXFSZ] = "XFSZ",
- [SIGVTALRM] = "VTALRM",
- [SIGPROF] = "PROF",
- [SIGWINCH] = "WINCH",
- [SIGIO] = "IO",
- [SIGPWR] = "PWR",
- [SIGSYS] = "SYS"
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
-
-const char *signal_to_string(int signo) {
- static __thread char buf[12];
- const char *name;
-
- name = __signal_to_string(signo);
- if (name)
- return name;
-
- if (signo >= SIGRTMIN && signo <= SIGRTMAX)
- snprintf(buf, sizeof(buf) - 1, "RTMIN+%d", signo - SIGRTMIN);
- else
- snprintf(buf, sizeof(buf) - 1, "%d", signo);
- char_array_0(buf);
- return buf;
-}
-
-int signal_from_string(const char *s) {
- int signo;
- int offset = 0;
- unsigned u;
-
- signo = __signal_from_string(s);
- if (signo > 0)
- return signo;
-
- if (startswith(s, "RTMIN+")) {
- s += 6;
- offset = SIGRTMIN;
- }
- if (safe_atou(s, &u) >= 0) {
- signo = (int) u + offset;
- if (signo > 0 && signo < _NSIG)
- return signo;
- }
- return -1;
-}
-
-bool kexec_loaded(void) {
- bool loaded = false;
- char *s;
-
- if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
- if (s[0] == '1')
- loaded = true;
- free(s);
- }
- return loaded;
-}
-
-int strdup_or_null(const char *a, char **b) {
- char *c;
-
- assert(b);
-
- if (!a) {
- *b = NULL;
- return 0;
- }
-
- c = strdup(a);
- if (!c)
- return -ENOMEM;
-
- *b = c;
- return 0;
-}
-
-int prot_from_flags(int flags) {
-
- switch (flags & O_ACCMODE) {
-
- case O_RDONLY:
- return PROT_READ;
-
- case O_WRONLY:
- return PROT_WRITE;
-
- case O_RDWR:
- return PROT_READ|PROT_WRITE;
-
- default:
- return -EINVAL;
- }
-}
-
-char *format_bytes(char *buf, size_t l, off_t t) {
- unsigned i;
-
- static const struct {
- const char *suffix;
- off_t factor;
- } table[] = {
- { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
- { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
- { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
- { "G", 1024ULL*1024ULL*1024ULL },
- { "M", 1024ULL*1024ULL },
- { "K", 1024ULL },
- };
-
- for (i = 0; i < ELEMENTSOF(table); i++) {
-
- if (t >= table[i].factor) {
- snprintf(buf, l,
- "%llu.%llu%s",
- (unsigned long long) (t / table[i].factor),
- (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
- table[i].suffix);
-
- goto finish;
- }
- }
-
- snprintf(buf, l, "%lluB", (unsigned long long) t);
-
-finish:
- buf[l-1] = 0;
- return buf;
-
-}
-
-void* memdup(const void *p, size_t l) {
- void *r;
-
- assert(p);
-
- r = malloc(l);
- if (!r)
- return NULL;
-
- memcpy(r, p, l);
- return r;
-}
-
-int fd_inc_sndbuf(int fd, size_t n) {
- int r, value;
- socklen_t l = sizeof(value);
-
- r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
- if (r >= 0 &&
- l == sizeof(value) &&
- (size_t) value >= n*2)
- return 0;
-
- value = (int) n;
- r = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value));
- if (r < 0)
- return -errno;
-
- return 1;
-}
-
-int fd_inc_rcvbuf(int fd, size_t n) {
- int r, value;
- socklen_t l = sizeof(value);
-
- r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
- if (r >= 0 &&
- l == sizeof(value) &&
- (size_t) value >= n*2)
- return 0;
-
- value = (int) n;
- r = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value));
- if (r < 0)
- return -errno;
-
- return 1;
-}
-
-int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
- pid_t parent_pid, agent_pid;
- int fd;
- bool stdout_is_tty, stderr_is_tty;
- unsigned n, i;
- va_list ap;
- char **l;
-
- assert(pid);
- assert(path);
-
- parent_pid = getpid();
-
- /* Spawns a temporary TTY agent, making sure it goes away when
- * we go away */
-
- agent_pid = fork();
- if (agent_pid < 0)
- return -errno;
-
- if (agent_pid != 0) {
- *pid = agent_pid;
- return 0;
- }
-
- /* In the child:
- *
- * Make sure the agent goes away when the parent dies */
- if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
- _exit(EXIT_FAILURE);
-
- /* Check whether our parent died before we were able
- * to set the death signal */
- if (getppid() != parent_pid)
- _exit(EXIT_SUCCESS);
-
- /* Don't leak fds to the agent */
- close_all_fds(except, n_except);
-
- stdout_is_tty = isatty(STDOUT_FILENO);
- stderr_is_tty = isatty(STDERR_FILENO);
-
- if (!stdout_is_tty || !stderr_is_tty) {
- /* Detach from stdout/stderr. and reopen
- * /dev/tty for them. This is important to
- * ensure that when systemctl is started via
- * popen() or a similar call that expects to
- * read EOF we actually do generate EOF and
- * not delay this indefinitely by because we
- * keep an unused copy of stdin around. */
- fd = open("/dev/tty", O_WRONLY);
- if (fd < 0) {
- log_error("Failed to open /dev/tty: %m");
- _exit(EXIT_FAILURE);
- }
-
- if (!stdout_is_tty)
- dup2(fd, STDOUT_FILENO);
-
- if (!stderr_is_tty)
- dup2(fd, STDERR_FILENO);
-
- if (fd > 2)
- close(fd);
- }
-
- /* Count arguments */
- va_start(ap, path);
- for (n = 0; va_arg(ap, char*); n++)
- ;
- va_end(ap);
-
- /* Allocate strv */
- l = alloca(sizeof(char *) * (n + 1));
-
- /* Fill in arguments */
- va_start(ap, path);
- for (i = 0; i <= n; i++)
- l[i] = va_arg(ap, char*);
- va_end(ap);
-
- execv(path, l);
- _exit(EXIT_FAILURE);
-}
-
-int setrlimit_closest(int resource, const struct rlimit *rlim) {
- struct rlimit highest, fixed;
-
- assert(rlim);
-
- if (setrlimit(resource, rlim) >= 0)
- return 0;
-
- if (errno != EPERM)
- return -errno;
-
- /* So we failed to set the desired setrlimit, then let's try
- * to get as close as we can */
- assert_se(getrlimit(resource, &highest) == 0);
-
- fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
- fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
-
- if (setrlimit(resource, &fixed) < 0)
- return -errno;
-
- return 0;
-}
-
-int getenv_for_pid(pid_t pid, const char *field, char **_value) {
- char path[sizeof("/proc/")-1+10+sizeof("/environ")], *value = NULL;
- int r;
- FILE *f;
- bool done = false;
- size_t l;
-
- assert(field);
- assert(_value);
-
- if (pid == 0)
- pid = getpid();
-
- snprintf(path, sizeof(path), "/proc/%lu/environ", (unsigned long) pid);
- char_array_0(path);
-
- f = fopen(path, "re");
- if (!f)
- return -errno;
-
- l = strlen(field);
- r = 0;
-
- do {
- char line[LINE_MAX];
- unsigned i;
-
- for (i = 0; i < sizeof(line)-1; i++) {
- int c;
-
- c = getc(f);
- if (_unlikely_(c == EOF)) {
- done = true;
- break;
- } else if (c == 0)
- break;
-
- line[i] = c;
- }
- line[i] = 0;
-
- if (memcmp(line, field, l) == 0 && line[l] == '=') {
- value = strdup(line + l + 1);
- if (!value) {
- r = -ENOMEM;
- break;
- }
-
- r = 1;
- break;
- }
-
- } while (!done);
-
- fclose(f);
-
- if (r >= 0)
- *_value = value;
-
- return r;
-}
-
-int can_sleep(const char *type) {
- char *w, *state;
- size_t l, k;
- int r;
- _cleanup_free_ char *p = NULL;
-
- assert(type);
-
- r = read_one_line_file("/sys/power/state", &p);
- if (r < 0)
- return r == -ENOENT ? 0 : r;
-
- k = strlen(type);
- FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state)
- if (l == k && memcmp(w, type, l) == 0)
- return true;
-
- return false;
-}
-
-int can_sleep_disk(const char *type) {
- char *w, *state;
- size_t l, k;
- int r;
- _cleanup_free_ char *p = NULL;
-
- assert(type);
-
- r = read_one_line_file("/sys/power/disk", &p);
- if (r < 0)
- return r == -ENOENT ? 0 : r;
-
- k = strlen(type);
- FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state) {
- if (l == k && memcmp(w, type, l) == 0)
- return true;
-
- if (l == k + 2 && w[0] == '[' && memcmp(w + 1, type, l - 2) == 0 && w[l-1] == ']')
- return true;
- }
-
- return false;
-}
-
-bool is_valid_documentation_url(const char *url) {
- assert(url);
-
- if (startswith(url, "http://") && url[7])
- return true;
-
- if (startswith(url, "https://") && url[8])
- return true;
-
- if (startswith(url, "file:") && url[5])
- return true;
-
- if (startswith(url, "info:") && url[5])
- return true;
-
- if (startswith(url, "man:") && url[4])
- return true;
-
- return false;
-}
-
-bool in_initrd(void) {
- static __thread int saved = -1;
- struct statfs s;
-
- if (saved >= 0)
- return saved;
-
- /* We make two checks here:
- *
- * 1. the flag file /etc/initrd-release must exist
- * 2. the root file system must be a memory file system
- *
- * The second check is extra paranoia, since misdetecting an
- * initrd can have bad bad consequences due the initrd
- * emptying when transititioning to the main systemd.
- */
-
- saved = access("/etc/initrd-release", F_OK) >= 0 &&
- statfs("/", &s) >= 0 &&
- (s.f_type == TMPFS_MAGIC || s.f_type == RAMFS_MAGIC);
-
- return saved;
-}
-
-void warn_melody(void) {
- _cleanup_close_ int fd = -1;
-
- fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0)
- return;
-
- /* Yeah, this is synchronous. Kinda sucks. But well... */
-
- ioctl(fd, KIOCSOUND, (int)(1193180/440));
- usleep(125*USEC_PER_MSEC);
-
- ioctl(fd, KIOCSOUND, (int)(1193180/220));
- usleep(125*USEC_PER_MSEC);
-
- ioctl(fd, KIOCSOUND, (int)(1193180/220));
- usleep(125*USEC_PER_MSEC);
-
- ioctl(fd, KIOCSOUND, 0);
-}
-
-int make_console_stdio(void) {
- int fd, r;
-
- /* Make /dev/console the controlling terminal and stdin/stdout/stderr */
-
- fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1);
- if (fd < 0) {
- log_error("Failed to acquire terminal: %s", strerror(-fd));
- return fd;
- }
-
- r = make_stdio(fd);
- if (r < 0) {
- log_error("Failed to duplicate terminal fd: %s", strerror(-r));
- return r;
- }
-
- return 0;
-}
-
-int get_home_dir(char **_h) {
- char *h;
- const char *e;
- uid_t u;
- struct passwd *p;
-
- assert(_h);
-
- /* Take the user specified one */
- e = getenv("HOME");
- if (e) {
- h = strdup(e);
- if (!h)
- return -ENOMEM;
-
- *_h = h;
- return 0;
- }
-
- /* Hardcode home directory for root to avoid NSS */
- u = getuid();
- if (u == 0) {
- h = strdup("/root");
- if (!h)
- return -ENOMEM;
-
- *_h = h;
- return 0;
- }
-
- /* Check the database... */
- errno = 0;
- p = getpwuid(u);
- if (!p)
- return errno ? -errno : -ESRCH;
-
- if (!path_is_absolute(p->pw_dir))
- return -EINVAL;
-
- h = strdup(p->pw_dir);
- if (!h)
- return -ENOMEM;
-
- *_h = h;
- return 0;
-}
-
-int get_shell(char **_sh) {
- char *sh;
- const char *e;
- uid_t u;
- struct passwd *p;
-
- assert(_sh);
-
- /* Take the user specified one */
- e = getenv("SHELL");
- if (e) {
- sh = strdup(e);
- if (!sh)
- return -ENOMEM;
-
- *_sh = sh;
- return 0;
- }
-
- /* Hardcode home directory for root to avoid NSS */
- u = getuid();
- if (u == 0) {
- sh = strdup("/bin/sh");
- if (!sh)
- return -ENOMEM;
-
- *_sh = sh;
- return 0;
- }
-
- /* Check the database... */
- errno = 0;
- p = getpwuid(u);
- if (!p)
- return errno ? -errno : -ESRCH;
-
- if (!path_is_absolute(p->pw_shell))
- return -EINVAL;
-
- sh = strdup(p->pw_shell);
- if (!sh)
- return -ENOMEM;
-
- *_sh = sh;
- return 0;
-}
-
-void freep(void *p) {
- free(*(void**) p);
-}
-
-void fclosep(FILE **f) {
- if (*f)
- fclose(*f);
-}
-
-void closep(int *fd) {
- if (*fd >= 0)
- close_nointr_nofail(*fd);
-}
-
-void closedirp(DIR **d) {
- if (*d)
- closedir(*d);
-}
-
-void umaskp(mode_t *u) {
- umask(*u);
-}
-
-bool filename_is_safe(const char *p) {
-
- if (isempty(p))
- return false;
-
- if (strchr(p, '/'))
- return false;
-
- if (streq(p, "."))
- return false;
-
- if (streq(p, ".."))
- return false;
-
- if (strlen(p) > FILENAME_MAX)
- return false;
-
- return true;
-}
-
-bool string_is_safe(const char *p) {
- const char *t;
-
- assert(p);
-
- for (t = p; *t; t++) {
- if (*t > 0 && *t < ' ')
- return false;
-
- if (strchr("\\\"\'", *t))
- return false;
- }
-
- return true;
-}
-
-int parse_timestamp(const char *t, usec_t *usec) {
- const char *k;
- struct tm tm, copy;
- time_t x;
- usec_t plus = 0, minus = 0, ret;
- int r;
-
- /*
- * Allowed syntaxes:
- *
- * 2012-09-22 16:34:22
- * 2012-09-22 16:34 (seconds will be set to 0)
- * 2012-09-22 (time will be set to 00:00:00)
- * 16:34:22 (date will be set to today)
- * 16:34 (date will be set to today, seconds to 0)
- * now
- * yesterday (time is set to 00:00:00)
- * today (time is set to 00:00:00)
- * tomorrow (time is set to 00:00:00)
- * +5min
- * -5days
- *
- */
-
- assert(t);
- assert(usec);
-
- x = time(NULL);
- assert_se(localtime_r(&x, &tm));
-
- if (streq(t, "now"))
- goto finish;
-
- else if (streq(t, "today")) {
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
-
- } else if (streq(t, "yesterday")) {
- tm.tm_mday --;
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
-
- } else if (streq(t, "tomorrow")) {
- tm.tm_mday ++;
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
-
- } else if (t[0] == '+') {
-
- r = parse_usec(t+1, &plus);
- if (r < 0)
- return r;
-
- goto finish;
- } else if (t[0] == '-') {
-
- r = parse_usec(t+1, &minus);
- if (r < 0)
- return r;
-
- goto finish;
- }
-
- copy = tm;
- k = strptime(t, "%y-%m-%d %H:%M:%S", &tm);
- if (k && *k == 0)
- goto finish;
-
- tm = copy;
- k = strptime(t, "%Y-%m-%d %H:%M:%S", &tm);
- if (k && *k == 0)
- goto finish;
-
- tm = copy;
- k = strptime(t, "%y-%m-%d %H:%M", &tm);
- if (k && *k == 0) {
- tm.tm_sec = 0;
- goto finish;
- }
-
- tm = copy;
- k = strptime(t, "%Y-%m-%d %H:%M", &tm);
- if (k && *k == 0) {
- tm.tm_sec = 0;
- goto finish;
- }
-
- tm = copy;
- k = strptime(t, "%y-%m-%d", &tm);
- if (k && *k == 0) {
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
- }
-
- tm = copy;
- k = strptime(t, "%Y-%m-%d", &tm);
- if (k && *k == 0) {
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto finish;
- }
-
- tm = copy;
- k = strptime(t, "%H:%M:%S", &tm);
- if (k && *k == 0)
- goto finish;
-
- tm = copy;
- k = strptime(t, "%H:%M", &tm);
- if (k && *k == 0) {
- tm.tm_sec = 0;
- goto finish;
- }
-
- return -EINVAL;
-
-finish:
- x = mktime(&tm);
- if (x == (time_t) -1)
- return -EINVAL;
-
- ret = (usec_t) x * USEC_PER_SEC;
-
- ret += plus;
- if (ret > minus)
- ret -= minus;
- else
- ret = 0;
-
- *usec = ret;
-
- return 0;
-}
-
-/* hey glibc, APIs with callbacks without a user pointer are so useless */
-void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
- int (*compar) (const void *, const void *, void *), void *arg) {
- size_t l, u, idx;
- const void *p;
- int comparison;
-
- l = 0;
- u = nmemb;
- while (l < u) {
- idx = (l + u) / 2;
- p = (void *)(((const char *) base) + (idx * size));
- comparison = compar(key, p, arg);
- if (comparison < 0)
- u = idx;
- else if (comparison > 0)
- l = idx + 1;
- else
- return (void *)p;
- }
- return NULL;
-}
-
-bool is_locale_utf8(void) {
- const char *set;
- static int cached_answer = -1;
-
- if (cached_answer >= 0)
- goto out;
-
- if (!setlocale(LC_ALL, "")) {
- cached_answer = true;
- goto out;
- }
-
- set = nl_langinfo(CODESET);
- if (!set) {
- cached_answer = true;
- goto out;
- }
-
- cached_answer = streq(set, "UTF-8");
-out:
- return (bool)cached_answer;
-}
-
-const char *draw_special_char(DrawSpecialChar ch) {
- static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = {
- /* UTF-8 */ {
- [DRAW_TREE_VERT] = "\342\224\202 ", /* │ */
- [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
- [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
- [DRAW_TRIANGULAR_BULLET] = "\342\200\243 ", /* ‣ */
- },
- /* ASCII fallback */ {
- [DRAW_TREE_VERT] = "| ",
- [DRAW_TREE_BRANCH] = "|-",
- [DRAW_TREE_RIGHT] = "`-",
- [DRAW_TRIANGULAR_BULLET] = "> ",
- }
- };
-
- return draw_table[!is_locale_utf8()][ch];
-}
-
-char *strreplace(const char *text, const char *old_string, const char *new_string) {
- const char *f;
- char *t, *r;
- size_t l, old_len, new_len;
-
- assert(text);
- assert(old_string);
- assert(new_string);
-
- old_len = strlen(old_string);
- new_len = strlen(new_string);
-
- l = strlen(text);
- r = new(char, l+1);
- if (!r)
- return NULL;
-
- f = text;
- t = r;
- while (*f) {
- char *a;
- size_t d, nl;
-
- if (!startswith(f, old_string)) {
- *(t++) = *(f++);
- continue;
- }
-
- d = t - r;
- nl = l - old_len + new_len;
- a = realloc(r, nl + 1);
- if (!a)
- goto oom;
-
- l = nl;
- r = a;
- t = r + d;
-
- t = stpcpy(t, new_string);
- f += old_len;
- }
-
- *t = 0;
- return r;
-
-oom:
- free(r);
- return NULL;
-}
diff --git a/src/udev/util.h b/src/udev/util.h
deleted file mode 100644
index b9230e38bc..0000000000
--- a/src/udev/util.h
+++ /dev/null
@@ -1,616 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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.
-
- 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 systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <inttypes.h>
-#include <time.h>
-#include <sys/time.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <signal.h>
-#include <sched.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <sys/resource.h>
-#include <stddef.h>
-
-#include "macro.h"
-
-typedef uint64_t usec_t;
-typedef uint64_t nsec_t;
-
-typedef struct dual_timestamp {
- usec_t realtime;
- usec_t monotonic;
-} dual_timestamp;
-
-union dirent_storage {
- struct dirent de;
- uint8_t storage[offsetof(struct dirent, d_name) +
- ((NAME_MAX + 1 + sizeof(long)) & ~(sizeof(long) - 1))];
-};
-
-#define MSEC_PER_SEC 1000ULL
-#define USEC_PER_SEC 1000000ULL
-#define USEC_PER_MSEC 1000ULL
-#define NSEC_PER_SEC 1000000000ULL
-#define NSEC_PER_MSEC 1000000ULL
-#define NSEC_PER_USEC 1000ULL
-
-#define USEC_PER_MINUTE (60ULL*USEC_PER_SEC)
-#define NSEC_PER_MINUTE (60ULL*NSEC_PER_SEC)
-#define USEC_PER_HOUR (60ULL*USEC_PER_MINUTE)
-#define NSEC_PER_HOUR (60ULL*NSEC_PER_MINUTE)
-#define USEC_PER_DAY (24ULL*USEC_PER_HOUR)
-#define NSEC_PER_DAY (24ULL*NSEC_PER_HOUR)
-#define USEC_PER_WEEK (7ULL*USEC_PER_DAY)
-#define NSEC_PER_WEEK (7ULL*NSEC_PER_DAY)
-#define USEC_PER_MONTH (2629800ULL*USEC_PER_SEC)
-#define NSEC_PER_MONTH (2629800ULL*NSEC_PER_SEC)
-#define USEC_PER_YEAR (31557600ULL*USEC_PER_SEC)
-#define NSEC_PER_YEAR (31557600ULL*NSEC_PER_SEC)
-
-/* What is interpreted as whitespace? */
-#define WHITESPACE " \t\n\r"
-#define NEWLINE "\n\r"
-#define QUOTES "\"\'"
-#define COMMENTS "#;\n"
-
-#define FORMAT_TIMESTAMP_MAX (5+11+9+4+1)
-#define FORMAT_TIMESTAMP_PRETTY_MAX 256
-#define FORMAT_TIMESPAN_MAX 64
-#define FORMAT_BYTES_MAX 8
-
-#define ANSI_HIGHLIGHT_ON "\x1B[1;39m"
-#define ANSI_HIGHLIGHT_RED_ON "\x1B[1;31m"
-#define ANSI_HIGHLIGHT_GREEN_ON "\x1B[1;32m"
-#define ANSI_HIGHLIGHT_YELLOW_ON "\x1B[1;33m"
-#define ANSI_HIGHLIGHT_OFF "\x1B[0m"
-
-bool is_efiboot(void);
-
-usec_t now(clockid_t clock);
-
-dual_timestamp* dual_timestamp_get(dual_timestamp *ts);
-dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u);
-
-#define dual_timestamp_is_set(ts) ((ts)->realtime > 0)
-
-usec_t timespec_load(const struct timespec *ts);
-struct timespec *timespec_store(struct timespec *ts, usec_t u);
-
-usec_t timeval_load(const struct timeval *tv);
-struct timeval *timeval_store(struct timeval *tv, usec_t u);
-
-size_t page_size(void);
-#define PAGE_ALIGN(l) ALIGN_TO((l), page_size())
-
-#define streq(a,b) (strcmp((a),(b)) == 0)
-#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
-
-bool streq_ptr(const char *a, const char *b);
-
-#define new(t, n) ((t*) malloc_multiply(sizeof(t), (n)))
-
-#define new0(t, n) ((t*) calloc((n), sizeof(t)))
-
-#define newa(t, n) ((t*) alloca(sizeof(t)*(n)))
-
-#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
-
-#define malloc0(n) (calloc((n), 1))
-
-static inline const char* yes_no(bool b) {
- return b ? "yes" : "no";
-}
-
-static inline const char* strempty(const char *s) {
- return s ? s : "";
-}
-
-static inline const char* strnull(const char *s) {
- return s ? s : "(null)";
-}
-
-static inline const char *strna(const char *s) {
- return s ? s : "n/a";
-}
-
-static inline bool isempty(const char *p) {
- return !p || !p[0];
-}
-
-char *endswith(const char *s, const char *postfix);
-char *startswith(const char *s, const char *prefix);
-char *startswith_no_case(const char *s, const char *prefix);
-
-bool first_word(const char *s, const char *word);
-
-int close_nointr(int fd);
-void close_nointr_nofail(int fd);
-void close_many(const int fds[], unsigned n_fd);
-
-int parse_boolean(const char *v);
-int parse_usec(const char *t, usec_t *usec);
-int parse_nsec(const char *t, nsec_t *nsec);
-int parse_bytes(const char *t, off_t *bytes);
-int parse_pid(const char *s, pid_t* ret_pid);
-int parse_uid(const char *s, uid_t* ret_uid);
-#define parse_gid(s, ret_uid) parse_uid(s, ret_uid)
-
-int safe_atou(const char *s, unsigned *ret_u);
-int safe_atoi(const char *s, int *ret_i);
-
-int safe_atollu(const char *s, unsigned long long *ret_u);
-int safe_atolli(const char *s, long long int *ret_i);
-
-#if __WORDSIZE == 32
-static inline int safe_atolu(const char *s, unsigned long *ret_u) {
- assert_cc(sizeof(unsigned long) == sizeof(unsigned));
- return safe_atou(s, (unsigned*) ret_u);
-}
-static inline int safe_atoli(const char *s, long int *ret_u) {
- assert_cc(sizeof(long int) == sizeof(int));
- return safe_atoi(s, (int*) ret_u);
-}
-#else
-static inline int safe_atolu(const char *s, unsigned long *ret_u) {
- assert_cc(sizeof(unsigned long) == sizeof(unsigned long long));
- return safe_atollu(s, (unsigned long long*) ret_u);
-}
-static inline int safe_atoli(const char *s, long int *ret_u) {
- assert_cc(sizeof(long int) == sizeof(long long int));
- return safe_atolli(s, (long long int*) ret_u);
-}
-#endif
-
-static inline int safe_atou32(const char *s, uint32_t *ret_u) {
- assert_cc(sizeof(uint32_t) == sizeof(unsigned));
- return safe_atou(s, (unsigned*) ret_u);
-}
-
-static inline int safe_atoi32(const char *s, int32_t *ret_i) {
- assert_cc(sizeof(int32_t) == sizeof(int));
- return safe_atoi(s, (int*) ret_i);
-}
-
-static inline int safe_atou64(const char *s, uint64_t *ret_u) {
- assert_cc(sizeof(uint64_t) == sizeof(unsigned long long));
- return safe_atollu(s, (unsigned long long*) ret_u);
-}
-
-static inline int safe_atoi64(const char *s, int64_t *ret_i) {
- assert_cc(sizeof(int64_t) == sizeof(long long int));
- return safe_atolli(s, (long long int*) ret_i);
-}
-
-char *split(const char *c, size_t *l, const char *separator, char **state);
-char *split_quoted(const char *c, size_t *l, char **state);
-
-#define FOREACH_WORD(word, length, s, state) \
- for ((state) = NULL, (word) = split((s), &(length), WHITESPACE, &(state)); (word); (word) = split((s), &(length), WHITESPACE, &(state)))
-
-#define FOREACH_WORD_SEPARATOR(word, length, s, separator, state) \
- for ((state) = NULL, (word) = split((s), &(length), (separator), &(state)); (word); (word) = split((s), &(length), (separator), &(state)))
-
-#define FOREACH_WORD_QUOTED(word, length, s, state) \
- for ((state) = NULL, (word) = split_quoted((s), &(length), &(state)); (word); (word) = split_quoted((s), &(length), &(state)))
-
-pid_t get_parent_of_pid(pid_t pid, pid_t *ppid);
-int get_starttime_of_pid(pid_t pid, unsigned long long *st);
-
-int write_one_line_file(const char *fn, const char *line);
-int write_one_line_file_atomic(const char *fn, const char *line);
-int read_one_line_file(const char *fn, char **line);
-int read_full_file(const char *fn, char **contents, size_t *size);
-
-int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
-int load_env_file(const char *fname, char ***l);
-int write_env_file(const char *fname, char **l);
-
-char *strappend(const char *s, const char *suffix);
-char *strnappend(const char *s, const char *suffix, size_t length);
-
-char *replace_env(const char *format, char **env);
-char **replace_env_argv(char **argv, char **env);
-
-int readlink_malloc(const char *p, char **r);
-int readlink_and_make_absolute(const char *p, char **r);
-int readlink_and_canonicalize(const char *p, char **r);
-
-int reset_all_signal_handlers(void);
-
-char *strstrip(char *s);
-char *delete_chars(char *s, const char *bad);
-char *truncate_nl(char *s);
-
-char *file_in_same_dir(const char *path, const char *filename);
-
-int rmdir_parents(const char *path, const char *stop);
-
-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);
-int get_process_uid(pid_t pid, uid_t *uid);
-int get_process_gid(pid_t pid, gid_t *gid);
-
-char hexchar(int x);
-int unhexchar(char c);
-char octchar(int x);
-int unoctchar(char c);
-char decchar(int x);
-int undecchar(char c);
-
-char *cescape(const char *s);
-char *cunescape(const char *s);
-char *cunescape_length(const char *s, size_t length);
-char *cunescape_length_with_prefix(const char *s, size_t length, const char *prefix);
-
-char *xescape(const char *s, const char *bad);
-
-char *bus_path_escape(const char *s);
-char *bus_path_unescape(const char *s);
-
-char *ascii_strlower(char *path);
-
-bool dirent_is_file(const struct dirent *de);
-bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix);
-
-bool ignore_file(const char *filename);
-
-bool chars_intersect(const char *a, const char *b);
-
-char *format_timestamp(char *buf, size_t l, usec_t t);
-char *format_timestamp_pretty(char *buf, size_t l, usec_t t);
-char *format_timespan(char *buf, size_t l, usec_t t);
-
-int make_stdio(int fd);
-int make_null_stdio(void);
-int make_console_stdio(void);
-
-unsigned long long random_ull(void);
-
-/* For basic lookup tables with strictly enumerated entries */
-#define __DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \
- scope const char *name##_to_string(type i) { \
- if (i < 0 || i >= (type) ELEMENTSOF(name##_table)) \
- return NULL; \
- return name##_table[i]; \
- } \
- scope type name##_from_string(const char *s) { \
- type i; \
- assert(s); \
- for (i = 0; i < (type)ELEMENTSOF(name##_table); i++) \
- if (name##_table[i] && \
- streq(name##_table[i], s)) \
- return i; \
- return (type) -1; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
-
-#define DEFINE_STRING_TABLE_LOOKUP(name,type) __DEFINE_STRING_TABLE_LOOKUP(name,type,)
-#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) __DEFINE_STRING_TABLE_LOOKUP(name,type,static)
-
-/* For string conversions where numbers are also acceptable */
-#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \
- int name##_to_string_alloc(type i, char **str) { \
- char *s; \
- int r; \
- if (i < 0 || i > max) \
- return -ERANGE; \
- if (i < (type) ELEMENTSOF(name##_table)) { \
- s = strdup(name##_table[i]); \
- if (!s) \
- return log_oom(); \
- } else { \
- r = asprintf(&s, "%u", i); \
- if (r < 0) \
- return log_oom(); \
- } \
- *str = s; \
- return 0; \
- } \
- type name##_from_string(const char *s) { \
- type i; \
- unsigned u = 0; \
- assert(s); \
- for (i = 0; i < (type)ELEMENTSOF(name##_table); i++) \
- if (name##_table[i] && \
- streq(name##_table[i], s)) \
- return i; \
- if (safe_atou(s, &u) >= 0 && u <= max) \
- return (type) u; \
- return (type) -1; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
-
-int fd_nonblock(int fd, bool nonblock);
-int fd_cloexec(int fd, bool cloexec);
-
-int close_all_fds(const int except[], unsigned n_except);
-
-bool fstype_is_network(const char *fstype);
-
-int chvt(int vt);
-
-int read_one_char(FILE *f, char *ret, usec_t timeout, bool *need_nl);
-int ask(char *ret, const char *replies, const char *text, ...);
-
-int reset_terminal_fd(int fd, bool switch_to_text);
-int reset_terminal(const char *name);
-
-int open_terminal(const char *name, int mode);
-int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocstty_eperm, usec_t timeout);
-int release_terminal(void);
-
-int flush_fd(int fd);
-
-int ignore_signals(int sig, ...);
-int default_signals(int sig, ...);
-int sigaction_many(const struct sigaction *sa, ...);
-
-int close_pipe(int p[]);
-int fopen_temporary(const char *path, FILE **_f, char **_temp_path);
-
-ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll);
-ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll);
-
-bool is_device_path(const char *path);
-
-int dir_is_empty(const char *path);
-
-void rename_process(const char name[8]);
-
-void sigset_add_many(sigset_t *ss, ...);
-
-bool hostname_is_set(void);
-
-char* gethostname_malloc(void);
-char* getlogname_malloc(void);
-char* getusername_malloc(void);
-
-int getttyname_malloc(int fd, char **r);
-int getttyname_harder(int fd, char **r);
-
-int get_ctty_devnr(pid_t pid, dev_t *d);
-int get_ctty(pid_t, dev_t *_devnr, char **r);
-
-int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
-int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid);
-
-int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev);
-int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev);
-int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky);
-int rm_rf_dangerous(const char *path, bool only_dirs, bool delete_root, bool honour_sticky);
-
-int pipe_eof(int fd);
-
-cpu_set_t* cpu_set_malloc(unsigned *ncpus);
-
-int status_vprintf(const char *status, bool ellipse, const char *format, va_list ap);
-int status_printf(const char *status, bool ellipse, const char *format, ...);
-int status_welcome(void);
-
-int fd_columns(int fd);
-unsigned columns(void);
-int fd_lines(int fd);
-unsigned lines(void);
-void columns_lines_cache_reset(int _unused_ signum);
-
-bool on_tty(void);
-
-int running_in_chroot(void);
-
-char *ellipsize(const char *s, size_t length, unsigned percent);
-char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent);
-
-int touch(const char *path);
-
-char *unquote(const char *s, const char *quotes);
-char *normalize_env_assignment(const char *s);
-
-int wait_for_terminate(pid_t pid, siginfo_t *status);
-int wait_for_terminate_and_warn(const char *name, pid_t pid);
-
-_noreturn_ void freeze(void);
-
-bool null_or_empty(struct stat *st);
-int null_or_empty_path(const char *fn);
-
-DIR *xopendirat(int dirfd, const char *name, int flags);
-
-void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t);
-void dual_timestamp_deserialize(const char *value, dual_timestamp *t);
-
-char *fstab_node_to_udev_node(const char *p);
-
-bool tty_is_vc(const char *tty);
-bool tty_is_vc_resolve(const char *tty);
-bool tty_is_console(const char *tty);
-int vtnr_from_tty(const char *tty);
-const char *default_term_for_tty(const char *tty);
-
-int execute_command(const char *command, char *const argv[]);
-void execute_directory(const char *directory, DIR *_d, char *argv[]);
-
-int kill_and_sigcont(pid_t pid, int sig);
-
-bool nulstr_contains(const char*nulstr, const char *needle);
-
-bool plymouth_running(void);
-
-bool hostname_is_valid(const char *s);
-char* hostname_cleanup(char *s);
-
-char* strshorten(char *s, size_t l);
-
-int terminal_vhangup_fd(int fd);
-int terminal_vhangup(const char *name);
-
-int vt_disallocate(const char *name);
-
-int copy_file(const char *from, const char *to);
-
-int symlink_atomic(const char *from, const char *to);
-
-int fchmod_umask(int fd, mode_t mode);
-
-bool display_is_local(const char *display);
-int socket_from_display(const char *display, char **path);
-
-int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home, const char **shell);
-int get_group_creds(const char **groupname, gid_t *gid);
-
-int in_group(const char *name);
-
-int glob_exists(const char *path);
-
-int dirent_ensure_type(DIR *d, struct dirent *de);
-
-int in_search_path(const char *path, char **search);
-int get_files_in_directory(const char *path, char ***list);
-
-char *strjoin(const char *x, ...) _sentinel_;
-
-bool is_main_thread(void);
-
-bool in_charset(const char *s, const char* charset);
-
-int block_get_whole_disk(dev_t d, dev_t *ret);
-
-int file_is_priv_sticky(const char *p);
-
-int strdup_or_null(const char *a, char **b);
-
-#define NULSTR_FOREACH(i, l) \
- for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
-
-#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))
-
-int ioprio_class_to_string_alloc(int i, char **s);
-int ioprio_class_from_string(const char *s);
-
-const char *sigchld_code_to_string(int i);
-int sigchld_code_from_string(const char *s);
-
-int log_facility_unshifted_to_string_alloc(int i, char **s);
-int log_facility_unshifted_from_string(const char *s);
-
-int log_level_to_string_alloc(int i, char **s);
-int log_level_from_string(const char *s);
-
-int sched_policy_to_string_alloc(int i, char **s);
-int sched_policy_from_string(const char *s);
-
-const char *rlimit_to_string(int i);
-int rlimit_from_string(const char *s);
-
-int ip_tos_to_string_alloc(int i, char **s);
-int ip_tos_from_string(const char *s);
-
-const char *signal_to_string(int i);
-int signal_from_string(const char *s);
-
-int signal_from_string_try_harder(const char *s);
-
-extern int saved_argc;
-extern char **saved_argv;
-
-bool kexec_loaded(void);
-
-int prot_from_flags(int flags);
-
-char *format_bytes(char *buf, size_t l, off_t t);
-
-int fd_wait_for_event(int fd, int event, usec_t timeout);
-
-void* memdup(const void *p, size_t l) _malloc_;
-
-int is_kernel_thread(pid_t pid);
-
-int fd_inc_sndbuf(int fd, size_t n);
-int fd_inc_rcvbuf(int fd, size_t n);
-
-int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...);
-
-int setrlimit_closest(int resource, const struct rlimit *rlim);
-
-int getenv_for_pid(pid_t pid, const char *field, char **_value);
-
-int can_sleep(const char *type);
-int can_sleep_disk(const char *type);
-
-bool is_valid_documentation_url(const char *url);
-
-bool in_initrd(void);
-
-void warn_melody(void);
-
-int get_shell(char **ret);
-int get_home_dir(char **ret);
-
-void freep(void *p);
-void fclosep(FILE **f);
-void closep(int *fd);
-void closedirp(DIR **d);
-void umaskp(mode_t *u);
-
-_malloc_ static inline void *malloc_multiply(size_t a, size_t b) {
- if (_unlikely_(b == 0 || a > ((size_t) -1) / b))
- return NULL;
-
- return malloc(a * b);
-}
-
-_malloc_ static inline void *memdup_multiply(const void *p, size_t a, size_t b) {
- if (_unlikely_(b == 0 || a > ((size_t) -1) / b))
- return NULL;
-
- return memdup(p, a * b);
-}
-
-bool filename_is_safe(const char *p);
-bool string_is_safe(const char *p);
-
-int parse_timestamp(const char *t, usec_t *usec);
-
-void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
- int (*compar) (const void *, const void *, void *),
- void *arg);
-
-bool is_locale_utf8(void);
-
-typedef enum DrawSpecialChar {
- DRAW_TREE_VERT,
- DRAW_TREE_BRANCH,
- DRAW_TREE_RIGHT,
- DRAW_TRIANGULAR_BULLET,
- _DRAW_SPECIAL_CHAR_MAX
-} DrawSpecialChar;
-const char *draw_special_char(DrawSpecialChar ch);
-
-char *strreplace(const char *text, const char *old_string, const char *new_string);