summaryrefslogtreecommitdiff
path: root/src/basic
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2017-05-10 18:16:16 -0400
committerLuke Shumaker <lukeshu@lukeshu.com>2017-05-10 18:16:16 -0400
commit225690a604e73a7f90859370cc5201b599b0e823 (patch)
tree00b9057ac2064b387efc6f07b5cff231300c9418 /src/basic
parentff6514f056098c885323e8629d6ac6d113796f35 (diff)
./tools/notsd-move
Diffstat (limited to 'src/basic')
-rw-r--r--src/basic/.gitignore16
l---------src/basic/Makefile1
-rw-r--r--src/basic/MurmurHash2.c86
-rw-r--r--src/basic/MurmurHash2.h33
-rw-r--r--src/basic/af-list.c56
-rw-r--r--src/basic/af-list.h41
-rw-r--r--src/basic/alloc-util.c83
-rw-r--r--src/basic/alloc-util.h119
-rw-r--r--src/basic/architecture.c189
-rw-r--r--src/basic/architecture.h211
-rw-r--r--src/basic/arphrd-list.c56
-rw-r--r--src/basic/arphrd-list.h25
-rw-r--r--src/basic/async.c94
-rw-r--r--src/basic/async.h25
-rw-r--r--src/basic/audit-util.c107
-rw-r--r--src/basic/audit-util.h31
-rw-r--r--src/basic/barrier.c415
-rw-r--r--src/basic/barrier.h91
-rw-r--r--src/basic/bitmap.c235
-rw-r--r--src/basic/bitmap.h49
-rw-r--r--src/basic/blkid-util.h31
-rw-r--r--src/basic/btrfs-ctree.h96
-rw-r--r--src/basic/btrfs-util.c2075
-rw-r--r--src/basic/btrfs-util.h131
-rw-r--r--src/basic/build.h155
-rw-r--r--src/basic/bus-label.c98
-rw-r--r--src/basic/bus-label.h31
-rw-r--r--src/basic/calendarspec.c1166
-rw-r--r--src/basic/calendarspec.h59
-rw-r--r--src/basic/cap-list.c66
-rw-r--r--src/basic/cap-list.h24
-rw-r--r--src/basic/capability-util.c363
-rw-r--r--src/basic/capability-util.h57
-rw-r--r--src/basic/cgroup-util.c2541
-rw-r--r--src/basic/cgroup-util.h260
-rw-r--r--src/basic/chattr-util.c107
-rw-r--r--src/basic/chattr-util.h26
-rw-r--r--src/basic/clock-util.c165
-rw-r--r--src/basic/clock-util.h29
-rw-r--r--src/basic/conf-files.c166
-rw-r--r--src/basic/conf-files.h25
-rw-r--r--src/basic/copy.c603
-rw-r--r--src/basic/copy.h36
-rw-r--r--src/basic/cpu-set-util.c114
-rw-r--r--src/basic/cpu-set-util.h32
-rw-r--r--src/basic/def.h90
-rw-r--r--src/basic/device-nodes.c80
-rw-r--r--src/basic/device-nodes.h26
-rw-r--r--src/basic/dirent-util.c74
-rw-r--r--src/basic/dirent-util.h52
-rw-r--r--src/basic/env-util.c623
-rw-r--r--src/basic/env-util.h51
-rw-r--r--src/basic/errno-list.c57
-rw-r--r--src/basic/errno-list.h25
-rw-r--r--src/basic/escape.c502
-rw-r--r--src/basic/escape.h54
-rw-r--r--src/basic/ether-addr-util.c125
-rw-r--r--src/basic/ether-addr-util.h39
-rw-r--r--src/basic/exit-status.c223
-rw-r--r--src/basic/exit-status.h110
-rw-r--r--src/basic/extract-word.c298
-rw-r--r--src/basic/extract-word.h35
-rw-r--r--src/basic/fd-util.c380
-rw-r--r--src/basic/fd-util.h80
-rw-r--r--src/basic/fileio-label.c68
-rw-r--r--src/basic/fileio-label.h30
-rw-r--r--src/basic/fileio.c1411
-rw-r--r--src/basic/fileio.h90
-rw-r--r--src/basic/formats-util.h79
-rw-r--r--src/basic/fs-util.c782
-rw-r--r--src/basic/fs-util.h81
-rw-r--r--src/basic/glob-util.c70
-rw-r--r--src/basic/glob-util.h36
-rw-r--r--src/basic/gunicode.c112
-rw-r--r--src/basic/gunicode.h30
-rw-r--r--src/basic/hash-funcs.c81
-rw-r--r--src/basic/hash-funcs.h65
-rw-r--r--src/basic/hashmap.c1828
-rw-r--r--src/basic/hashmap.h372
-rw-r--r--src/basic/hexdecoct.c754
-rw-r--r--src/basic/hexdecoct.h56
-rw-r--r--src/basic/hostname-util.c251
-rw-r--r--src/basic/hostname-util.h41
-rw-r--r--src/basic/in-addr-util.c449
-rw-r--r--src/basic/in-addr-util.h64
-rw-r--r--src/basic/io-util.c269
-rw-r--r--src/basic/io-util.h95
-rw-r--r--src/basic/ioprio.h55
-rw-r--r--src/basic/label.c82
-rw-r--r--src/basic/label.h28
-rw-r--r--src/basic/list.h184
-rw-r--r--src/basic/locale-util.c322
-rw-r--r--src/basic/locale-util.h73
-rw-r--r--src/basic/lockfile-util.c153
-rw-r--r--src/basic/lockfile-util.h39
-rw-r--r--src/basic/log.c1177
-rw-r--r--src/basic/log.h253
-rw-r--r--src/basic/login-util.c31
-rw-r--r--src/basic/login-util.h29
-rw-r--r--src/basic/macro.h415
-rw-r--r--src/basic/memfd-util.c174
-rw-r--r--src/basic/memfd-util.h36
-rw-r--r--src/basic/mempool.c104
-rw-r--r--src/basic/mempool.h47
-rw-r--r--src/basic/missing.h1081
-rw-r--r--src/basic/missing_syscall.h300
-rw-r--r--src/basic/mkdir-label.c38
-rw-r--r--src/basic/mkdir.c128
-rw-r--r--src/basic/mkdir.h38
-rw-r--r--src/basic/mount-util.c689
-rw-r--r--src/basic/mount-util.h63
-rw-r--r--src/basic/nss-util.h199
-rw-r--r--src/basic/ordered-set.c64
-rw-r--r--src/basic/ordered-set.h74
-rw-r--r--src/basic/parse-util.c576
-rw-r--r--src/basic/parse-util.h112
-rw-r--r--src/basic/path-util.c897
-rw-r--r--src/basic/path-util.h130
-rw-r--r--src/basic/prioq.c318
-rw-r--r--src/basic/prioq.h43
-rw-r--r--src/basic/proc-cmdline.c191
-rw-r--r--src/basic/proc-cmdline.h29
-rw-r--r--src/basic/process-util.c860
-rw-r--r--src/basic/process-util.h110
-rw-r--r--src/basic/random-util.c133
-rw-r--r--src/basic/random-util.h39
-rw-r--r--src/basic/ratelimit.c56
-rw-r--r--src/basic/ratelimit.h58
-rw-r--r--src/basic/raw-clone.h81
-rw-r--r--src/basic/refcnt.h34
-rw-r--r--src/basic/replace-var.c111
-rw-r--r--src/basic/replace-var.h22
-rw-r--r--src/basic/rlimit-util.c321
-rw-r--r--src/basic/rlimit-util.h36
-rw-r--r--src/basic/rm-rf.c242
-rw-r--r--src/basic/rm-rf.h41
-rw-r--r--src/basic/securebits.h45
-rw-r--r--src/basic/selinux-util.c485
-rw-r--r--src/basic/selinux-util.h51
-rw-r--r--src/basic/set.h138
-rw-r--r--src/basic/sigbus.c152
-rw-r--r--src/basic/sigbus.h25
-rw-r--r--src/basic/signal-util.c278
-rw-r--r--src/basic/signal-util.h56
-rw-r--r--src/basic/siphash24.c193
-rw-r--r--src/basic/siphash24.h23
-rw-r--r--src/basic/smack-util.c241
-rw-r--r--src/basic/smack-util.h54
-rw-r--r--src/basic/socket-label.c170
-rw-r--r--src/basic/socket-util.c1079
-rw-r--r--src/basic/socket-util.h158
-rw-r--r--src/basic/sparse-endian.h91
-rw-r--r--src/basic/special.h122
-rw-r--r--src/basic/stat-util.c218
-rw-r--r--src/basic/stat-util.h69
-rw-r--r--src/basic/stdio-util.h76
-rw-r--r--src/basic/strbuf.c204
-rw-r--r--src/basic/strbuf.h54
-rw-r--r--src/basic/string-table.c34
-rw-r--r--src/basic/string-table.h119
-rw-r--r--src/basic/string-util.c868
-rw-r--r--src/basic/string-util.h201
-rw-r--r--src/basic/strv.c940
-rw-r--r--src/basic/strv.h182
-rw-r--r--src/basic/strxcpyx.c100
-rw-r--r--src/basic/strxcpyx.h31
-rw-r--r--src/basic/syslog-util.c114
-rw-r--r--src/basic/syslog-util.h32
-rw-r--r--src/basic/terminal-util.c1224
-rw-r--r--src/basic/terminal-util.h119
-rw-r--r--src/basic/time-util.c1327
-rw-r--r--src/basic/time-util.h181
-rw-r--r--src/basic/umask-util.h46
-rw-r--r--src/basic/unaligned.h129
-rw-r--r--src/basic/unit-name.c1049
-rw-r--r--src/basic/unit-name.h367
-rw-r--r--src/basic/user-util.c636
-rw-r--r--src/basic/user-util.h90
-rw-r--r--src/basic/utf8.c409
-rw-r--r--src/basic/utf8.h60
-rw-r--r--src/basic/util.c876
-rw-r--r--src/basic/util.h196
-rw-r--r--src/basic/verbs.c101
-rw-r--r--src/basic/verbs.h33
-rw-r--r--src/basic/virt.c595
-rw-r--r--src/basic/virt.h74
-rw-r--r--src/basic/web-util.c76
-rw-r--r--src/basic/web-util.h30
-rw-r--r--src/basic/xattr-util.c200
-rw-r--r--src/basic/xattr-util.h37
-rw-r--r--src/basic/xml.c255
-rw-r--r--src/basic/xml.h32
192 files changed, 0 insertions, 45518 deletions
diff --git a/src/basic/.gitignore b/src/basic/.gitignore
deleted file mode 100644
index e22411e484..0000000000
--- a/src/basic/.gitignore
+++ /dev/null
@@ -1,16 +0,0 @@
-/cap-from-name.gperf
-/cap-from-name.h
-/cap-list.txt
-/cap-to-name.h
-/errno-from-name.gperf
-/errno-from-name.h
-/errno-list.txt
-/errno-to-name.h
-/af-from-name.gperf
-/af-from-name.h
-/af-list.txt
-/af-to-name.h
-/arphrd-from-name.gperf
-/arphrd-from-name.h
-/arphrd-list.txt
-/arphrd-to-name.h
diff --git a/src/basic/Makefile b/src/basic/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/basic/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/basic/MurmurHash2.c b/src/basic/MurmurHash2.c
deleted file mode 100644
index 9020793930..0000000000
--- a/src/basic/MurmurHash2.c
+++ /dev/null
@@ -1,86 +0,0 @@
-//-----------------------------------------------------------------------------
-// MurmurHash2 was written by Austin Appleby, and is placed in the public
-// domain. The author hereby disclaims copyright to this source code.
-
-// Note - This code makes a few assumptions about how your machine behaves -
-
-// 1. We can read a 4-byte value from any address without crashing
-// 2. sizeof(int) == 4
-
-// And it has a few limitations -
-
-// 1. It will not work incrementally.
-// 2. It will not produce the same results on little-endian and big-endian
-// machines.
-
-#include "MurmurHash2.h"
-
-//-----------------------------------------------------------------------------
-// Platform-specific functions and macros
-
-// Microsoft Visual Studio
-
-#if defined(_MSC_VER)
-
-#define BIG_CONSTANT(x) (x)
-
-// Other compilers
-
-#else // defined(_MSC_VER)
-
-#define BIG_CONSTANT(x) (x##LLU)
-
-#endif // !defined(_MSC_VER)
-
-//-----------------------------------------------------------------------------
-
-uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed )
-{
- // 'm' and 'r' are mixing constants generated offline.
- // They're not really 'magic', they just happen to work well.
-
- const uint32_t m = 0x5bd1e995;
- const int r = 24;
-
- // Initialize the hash to a 'random' value
-
- uint32_t h = seed ^ len;
-
- // Mix 4 bytes at a time into the hash
-
- const unsigned char * data = (const unsigned char *)key;
-
- while (len >= 4)
- {
- uint32_t k = *(uint32_t*)data;
-
- k *= m;
- k ^= k >> r;
- k *= m;
-
- h *= m;
- h ^= k;
-
- data += 4;
- len -= 4;
- }
-
- // Handle the last few bytes of the input array
-
- switch(len)
- {
- case 3: h ^= data[2] << 16;
- case 2: h ^= data[1] << 8;
- case 1: h ^= data[0];
- h *= m;
- };
-
- // Do a few final mixes of the hash to ensure the last few
- // bytes are well-incorporated.
-
- h ^= h >> 13;
- h *= m;
- h ^= h >> 15;
-
- return h;
-}
diff --git a/src/basic/MurmurHash2.h b/src/basic/MurmurHash2.h
deleted file mode 100644
index 93362dd485..0000000000
--- a/src/basic/MurmurHash2.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//-----------------------------------------------------------------------------
-// MurmurHash2 was written by Austin Appleby, and is placed in the public
-// domain. The author hereby disclaims copyright to this source code.
-
-#ifndef _MURMURHASH2_H_
-#define _MURMURHASH2_H_
-
-//-----------------------------------------------------------------------------
-// Platform-specific functions and macros
-
-// Microsoft Visual Studio
-
-#if defined(_MSC_VER)
-
-typedef unsigned char uint8_t;
-typedef unsigned long uint32_t;
-typedef unsigned __int64 uint64_t;
-
-// Other compilers
-
-#else // defined(_MSC_VER)
-
-#include <stdint.h>
-
-#endif // !defined(_MSC_VER)
-
-//-----------------------------------------------------------------------------
-
-uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed );
-
-//-----------------------------------------------------------------------------
-
-#endif // _MURMURHASH2_H_
diff --git a/src/basic/af-list.c b/src/basic/af-list.c
deleted file mode 100644
index 4b291d177b..0000000000
--- a/src/basic/af-list.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 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 <string.h>
-#include <sys/socket.h>
-
-#include "af-list.h"
-#include "macro.h"
-
-static const struct af_name* lookup_af(register const char *str, register GPERF_LEN_TYPE len);
-
-#include "af-from-name.h"
-#include "af-to-name.h"
-
-const char *af_to_name(int id) {
-
- if (id <= 0)
- return NULL;
-
- if (id >= (int) ELEMENTSOF(af_names))
- return NULL;
-
- return af_names[id];
-}
-
-int af_from_name(const char *name) {
- const struct af_name *sc;
-
- assert(name);
-
- sc = lookup_af(name, strlen(name));
- if (!sc)
- return AF_UNSPEC;
-
- return sc->id;
-}
-
-int af_max(void) {
- return ELEMENTSOF(af_names);
-}
diff --git a/src/basic/af-list.h b/src/basic/af-list.h
deleted file mode 100644
index 6a4cc03839..0000000000
--- a/src/basic/af-list.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 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 "string-util.h"
-
-const char *af_to_name(int id);
-int af_from_name(const char *name);
-
-static inline const char* af_to_name_short(int id) {
- const char *f;
-
- if (id == AF_UNSPEC)
- return "*";
-
- f = af_to_name(id);
- if (!f)
- return "unknown";
-
- assert(startswith(f, "AF_"));
- return f + 3;
-}
-
-int af_max(void);
diff --git a/src/basic/alloc-util.c b/src/basic/alloc-util.c
deleted file mode 100644
index b540dcddf5..0000000000
--- a/src/basic/alloc-util.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/***
- 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 <stdint.h>
-#include <string.h>
-
-#include "alloc-util.h"
-#include "macro.h"
-#include "util.h"
-
-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;
-}
-
-void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
- size_t a, newalloc;
- void *q;
-
- assert(p);
- assert(allocated);
-
- if (*allocated >= need)
- return *p;
-
- newalloc = MAX(need * 2, 64u / size);
- a = newalloc * size;
-
- /* check for overflows */
- if (a < size * need)
- return NULL;
-
- q = realloc(*p, a);
- if (!q)
- return NULL;
-
- *p = q;
- *allocated = newalloc;
- return q;
-}
-
-void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
- size_t prev;
- uint8_t *q;
-
- assert(p);
- assert(allocated);
-
- prev = *allocated;
-
- q = greedy_realloc(p, allocated, need, size);
- if (!q)
- return NULL;
-
- if (*allocated > prev)
- memzero(q + prev * size, (*allocated - prev) * size);
-
- return q;
-}
diff --git a/src/basic/alloc-util.h b/src/basic/alloc-util.h
deleted file mode 100644
index a44dd473c1..0000000000
--- a/src/basic/alloc-util.h
+++ /dev/null
@@ -1,119 +0,0 @@
-#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 <alloca.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "macro.h"
-
-#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 newa0(t, n) ((t*) alloca0(sizeof(t)*(n)))
-
-#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
-
-#define malloc0(n) (calloc(1, (n)))
-
-static inline void *mfree(void *memory) {
- free(memory);
- return NULL;
-}
-
-#define free_and_replace(a, b) \
- ({ \
- free(a); \
- (a) = (b); \
- (b) = NULL; \
- 0; \
- })
-
-void* memdup(const void *p, size_t l) _alloc_(2);
-
-static inline void freep(void *p) {
- free(*(void**) p);
-}
-
-#define _cleanup_free_ _cleanup_(freep)
-
-static inline bool size_multiply_overflow(size_t size, size_t need) {
- return _unlikely_(need != 0 && size > (SIZE_MAX / need));
-}
-
-_malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t size, size_t need) {
- if (size_multiply_overflow(size, need))
- return NULL;
-
- return malloc(size * need);
-}
-
-_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t size, size_t need) {
- if (size_multiply_overflow(size, need))
- return NULL;
-
- return realloc(p, size * need);
-}
-
-_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) {
- if (size_multiply_overflow(size, need))
- return NULL;
-
- return memdup(p, size * need);
-}
-
-void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size);
-void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
-
-#define GREEDY_REALLOC(array, allocated, need) \
- greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0]))
-
-#define GREEDY_REALLOC0(array, allocated, need) \
- greedy_realloc0((void**) &(array), &(allocated), (need), sizeof((array)[0]))
-
-#define alloca0(n) \
- ({ \
- char *_new_; \
- size_t _len_ = n; \
- _new_ = alloca(_len_); \
- (void *) memset(_new_, 0, _len_); \
- })
-
-/* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */
-#define alloca_align(size, align) \
- ({ \
- void *_ptr_; \
- size_t _mask_ = (align) - 1; \
- _ptr_ = alloca((size) + _mask_); \
- (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \
- })
-
-#define alloca0_align(size, align) \
- ({ \
- void *_new_; \
- size_t _size_ = (size); \
- _new_ = alloca_align(_size_, (align)); \
- (void*)memset(_new_, 0, _size_); \
- })
diff --git a/src/basic/architecture.c b/src/basic/architecture.c
deleted file mode 100644
index b74dc0db78..0000000000
--- a/src/basic/architecture.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 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/utsname.h>
-
-#include "architecture.h"
-#include "macro.h"
-#include "string-table.h"
-#include "string-util.h"
-
-int uname_architecture(void) {
-
- /* Return a sanitized enum identifying the architecture we are
- * running on. This is based on uname(), and the user may
- * hence control what this returns by using
- * personality(). This puts the user in control on systems
- * that can run binaries of multiple architectures.
- *
- * We do not translate the string returned by uname()
- * 1:1. Instead we try to clean it up and break down the
- * confusion on x86 and arm in particular.
- *
- * We do not try to distinguish CPUs not CPU features, but
- * actual architectures, i.e. that have genuinely different
- * code. */
-
- static const struct {
- const char *machine;
- int arch;
- } arch_map[] = {
-#if defined(__x86_64__) || defined(__i386__)
- { "x86_64", ARCHITECTURE_X86_64 },
- { "i686", ARCHITECTURE_X86 },
- { "i586", ARCHITECTURE_X86 },
- { "i486", ARCHITECTURE_X86 },
- { "i386", ARCHITECTURE_X86 },
-#elif defined(__powerpc__) || defined(__powerpc64__)
- { "ppc64", ARCHITECTURE_PPC64 },
- { "ppc64le", ARCHITECTURE_PPC64_LE },
- { "ppc", ARCHITECTURE_PPC },
- { "ppcle", ARCHITECTURE_PPC_LE },
-#elif defined(__ia64__)
- { "ia64", ARCHITECTURE_IA64 },
-#elif defined(__hppa__) || defined(__hppa64__)
- { "parisc64", ARCHITECTURE_PARISC64 },
- { "parisc", ARCHITECTURE_PARISC },
-#elif defined(__s390__) || defined(__s390x__)
- { "s390x", ARCHITECTURE_S390X },
- { "s390", ARCHITECTURE_S390 },
-#elif defined(__sparc__)
- { "sparc64", ARCHITECTURE_SPARC64 },
- { "sparc", ARCHITECTURE_SPARC },
-#elif defined(__mips__) || defined(__mips64__)
- { "mips64", ARCHITECTURE_MIPS64 },
- { "mips", ARCHITECTURE_MIPS },
-#elif defined(__alpha__)
- { "alpha" , ARCHITECTURE_ALPHA },
-#elif defined(__arm__) || defined(__aarch64__)
- { "aarch64", ARCHITECTURE_ARM64 },
- { "aarch64_be", ARCHITECTURE_ARM64_BE },
- { "armv4l", ARCHITECTURE_ARM },
- { "armv4b", ARCHITECTURE_ARM_BE },
- { "armv4tl", ARCHITECTURE_ARM },
- { "armv4tb", ARCHITECTURE_ARM_BE },
- { "armv5tl", ARCHITECTURE_ARM },
- { "armv5tb", ARCHITECTURE_ARM_BE },
- { "armv5tel", ARCHITECTURE_ARM },
- { "armv5teb" , ARCHITECTURE_ARM_BE },
- { "armv5tejl", ARCHITECTURE_ARM },
- { "armv5tejb", ARCHITECTURE_ARM_BE },
- { "armv6l", ARCHITECTURE_ARM },
- { "armv6b", ARCHITECTURE_ARM_BE },
- { "armv7l", ARCHITECTURE_ARM },
- { "armv7b", ARCHITECTURE_ARM_BE },
- { "armv7ml", ARCHITECTURE_ARM },
- { "armv7mb", ARCHITECTURE_ARM_BE },
- { "armv4l", ARCHITECTURE_ARM },
- { "armv4b", ARCHITECTURE_ARM_BE },
- { "armv4tl", ARCHITECTURE_ARM },
- { "armv4tb", ARCHITECTURE_ARM_BE },
- { "armv5tl", ARCHITECTURE_ARM },
- { "armv5tb", ARCHITECTURE_ARM_BE },
- { "armv5tel", ARCHITECTURE_ARM },
- { "armv5teb", ARCHITECTURE_ARM_BE },
- { "armv5tejl", ARCHITECTURE_ARM },
- { "armv5tejb", ARCHITECTURE_ARM_BE },
- { "armv6l", ARCHITECTURE_ARM },
- { "armv6b", ARCHITECTURE_ARM_BE },
- { "armv7l", ARCHITECTURE_ARM },
- { "armv7b", ARCHITECTURE_ARM_BE },
- { "armv7ml", ARCHITECTURE_ARM },
- { "armv7mb", ARCHITECTURE_ARM_BE },
- { "armv8l", ARCHITECTURE_ARM },
- { "armv8b", ARCHITECTURE_ARM_BE },
-#elif defined(__sh__) || defined(__sh64__)
- { "sh5", ARCHITECTURE_SH64 },
- { "sh2", ARCHITECTURE_SH },
- { "sh2a", ARCHITECTURE_SH },
- { "sh3", ARCHITECTURE_SH },
- { "sh4", ARCHITECTURE_SH },
- { "sh4a", ARCHITECTURE_SH },
-#elif defined(__m68k__)
- { "m68k", ARCHITECTURE_M68K },
-#elif defined(__tilegx__)
- { "tilegx", ARCHITECTURE_TILEGX },
-#elif defined(__cris__)
- { "crisv32", ARCHITECTURE_CRIS },
-#elif defined(__nios2__)
- { "nios2", ARCHITECTURE_NIOS2 },
-#elif defined(__riscv__)
- { "riscv32", ARCHITECTURE_RISCV32 },
- { "riscv64", ARCHITECTURE_RISCV64 },
-# if __SIZEOF_POINTER__ == 4
- { "riscv", ARCHITECTURE_RISCV32 },
-# elif __SIZEOF_POINTER__ == 8
- { "riscv", ARCHITECTURE_RISCV64 },
-# endif
-#else
-#error "Please register your architecture here!"
-#endif
- };
-
- static int cached = _ARCHITECTURE_INVALID;
- struct utsname u;
- unsigned i;
-
- if (cached != _ARCHITECTURE_INVALID)
- return cached;
-
- assert_se(uname(&u) >= 0);
-
- for (i = 0; i < ELEMENTSOF(arch_map); i++)
- if (streq(arch_map[i].machine, u.machine))
- return cached = arch_map[i].arch;
-
- assert_not_reached("Couldn't identify architecture. You need to patch systemd.");
- return _ARCHITECTURE_INVALID;
-}
-
-static const char *const architecture_table[_ARCHITECTURE_MAX] = {
- [ARCHITECTURE_X86] = "x86",
- [ARCHITECTURE_X86_64] = "x86-64",
- [ARCHITECTURE_PPC] = "ppc",
- [ARCHITECTURE_PPC_LE] = "ppc-le",
- [ARCHITECTURE_PPC64] = "ppc64",
- [ARCHITECTURE_PPC64_LE] = "ppc64-le",
- [ARCHITECTURE_IA64] = "ia64",
- [ARCHITECTURE_PARISC] = "parisc",
- [ARCHITECTURE_PARISC64] = "parisc64",
- [ARCHITECTURE_S390] = "s390",
- [ARCHITECTURE_S390X] = "s390x",
- [ARCHITECTURE_SPARC] = "sparc",
- [ARCHITECTURE_SPARC64] = "sparc64",
- [ARCHITECTURE_MIPS] = "mips",
- [ARCHITECTURE_MIPS_LE] = "mips-le",
- [ARCHITECTURE_MIPS64] = "mips64",
- [ARCHITECTURE_MIPS64_LE] = "mips64-le",
- [ARCHITECTURE_ALPHA] = "alpha",
- [ARCHITECTURE_ARM] = "arm",
- [ARCHITECTURE_ARM_BE] = "arm-be",
- [ARCHITECTURE_ARM64] = "arm64",
- [ARCHITECTURE_ARM64_BE] = "arm64-be",
- [ARCHITECTURE_SH] = "sh",
- [ARCHITECTURE_SH64] = "sh64",
- [ARCHITECTURE_M68K] = "m68k",
- [ARCHITECTURE_TILEGX] = "tilegx",
- [ARCHITECTURE_CRIS] = "cris",
- [ARCHITECTURE_NIOS2] = "nios2",
- [ARCHITECTURE_RISCV32] = "riscv32",
- [ARCHITECTURE_RISCV64] = "riscv64",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(architecture, int);
diff --git a/src/basic/architecture.h b/src/basic/architecture.h
deleted file mode 100644
index 5a77c31932..0000000000
--- a/src/basic/architecture.h
+++ /dev/null
@@ -1,211 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 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 <endian.h>
-
-#include "macro.h"
-#include "util.h"
-
-/* A cleaned up architecture definition. We don't want to get lost in
- * processor features, models, generations or even ABIs. Hence we
- * focus on general family, and distinguish word width and
- * endianness. */
-
-enum {
- ARCHITECTURE_X86 = 0,
- ARCHITECTURE_X86_64,
- ARCHITECTURE_PPC,
- ARCHITECTURE_PPC_LE,
- ARCHITECTURE_PPC64,
- ARCHITECTURE_PPC64_LE,
- ARCHITECTURE_IA64,
- ARCHITECTURE_PARISC,
- ARCHITECTURE_PARISC64,
- ARCHITECTURE_S390,
- ARCHITECTURE_S390X,
- ARCHITECTURE_SPARC,
- ARCHITECTURE_SPARC64,
- ARCHITECTURE_MIPS,
- ARCHITECTURE_MIPS_LE,
- ARCHITECTURE_MIPS64,
- ARCHITECTURE_MIPS64_LE,
- ARCHITECTURE_ALPHA,
- ARCHITECTURE_ARM,
- ARCHITECTURE_ARM_BE,
- ARCHITECTURE_ARM64,
- ARCHITECTURE_ARM64_BE,
- ARCHITECTURE_SH,
- ARCHITECTURE_SH64,
- ARCHITECTURE_M68K,
- ARCHITECTURE_TILEGX,
- ARCHITECTURE_CRIS,
- ARCHITECTURE_NIOS2,
- ARCHITECTURE_RISCV32,
- ARCHITECTURE_RISCV64,
- _ARCHITECTURE_MAX,
- _ARCHITECTURE_INVALID = -1
-};
-
-int uname_architecture(void);
-
-/*
- * LIB_ARCH_TUPLE should resolve to the local library path
- * architecture tuple systemd is built for, according to the Debian
- * tuple list:
- *
- * https://wiki.debian.org/Multiarch/Tuples
- *
- * This is used in library search paths that should understand
- * Debian's paths on all distributions.
- */
-
-#if defined(__x86_64__)
-# define native_architecture() ARCHITECTURE_X86_64
-# define LIB_ARCH_TUPLE "x86_64-linux-gnu"
-# define SECONDARY_ARCHITECTURE ARCHITECTURE_X86
-#elif defined(__i386__)
-# define native_architecture() ARCHITECTURE_X86
-# define LIB_ARCH_TUPLE "i386-linux-gnu"
-#elif defined(__powerpc64__)
-# if __BYTE_ORDER == __BIG_ENDIAN
-# define native_architecture() ARCHITECTURE_PPC64
-# define LIB_ARCH_TUPLE "ppc64-linux-gnu"
-# define SECONDARY_ARCHITECTURE ARCHITECTURE_PPC
-# else
-# define native_architecture() ARCHITECTURE_PPC64_LE
-# define LIB_ARCH_TUPLE "powerpc64le-linux-gnu"
-# define SECONDARY_ARCHITECTURE ARCHITECTURE_PPC_LE
-# endif
-#elif defined(__powerpc__)
-# if __BYTE_ORDER == __BIG_ENDIAN
-# define native_architecture() ARCHITECTURE_PPC
-# define LIB_ARCH_TUPLE "powerpc-linux-gnu"
-# else
-# define native_architecture() ARCHITECTURE_PPC_LE
-# error "Missing LIB_ARCH_TUPLE for PPCLE"
-# endif
-#elif defined(__ia64__)
-# define native_architecture() ARCHITECTURE_IA64
-# define LIB_ARCH_TUPLE "ia64-linux-gnu"
-#elif defined(__hppa64__)
-# define native_architecture() ARCHITECTURE_PARISC64
-# error "Missing LIB_ARCH_TUPLE for HPPA64"
-#elif defined(__hppa__)
-# define native_architecture() ARCHITECTURE_PARISC
-# define LIB_ARCH_TUPLE "hppa‑linux‑gnu"
-#elif defined(__s390x__)
-# define native_architecture() ARCHITECTURE_S390X
-# define LIB_ARCH_TUPLE "s390x-linux-gnu"
-# define SECONDARY_ARCHITECTURE ARCHITECTURE_S390
-#elif defined(__s390__)
-# define native_architecture() ARCHITECTURE_S390
-# define LIB_ARCH_TUPLE "s390-linux-gnu"
-#elif defined(__sparc__) && defined (__arch64__)
-# define native_architecture() ARCHITECTURE_SPARC64
-# define LIB_ARCH_TUPLE "sparc64-linux-gnu"
-#elif defined(__sparc__)
-# define native_architecture() ARCHITECTURE_SPARC
-# define LIB_ARCH_TUPLE "sparc-linux-gnu"
-#elif defined(__mips64__)
-# if __BYTE_ORDER == __BIG_ENDIAN
-# define native_architecture() ARCHITECTURE_MIPS64
-# error "Missing LIB_ARCH_TUPLE for MIPS64"
-# else
-# define native_architecture() ARCHITECTURE_MIPS64_LE
-# error "Missing LIB_ARCH_TUPLE for MIPS64_LE"
-# endif
-#elif defined(__mips__)
-# if __BYTE_ORDER == __BIG_ENDIAN
-# define native_architecture() ARCHITECTURE_MIPS
-# define LIB_ARCH_TUPLE "mips-linux-gnu"
-# else
-# define native_architecture() ARCHITECTURE_MIPS_LE
-# define LIB_ARCH_TUPLE "mipsel-linux-gnu"
-# endif
-#elif defined(__alpha__)
-# define native_architecture() ARCHITECTURE_ALPHA
-# define LIB_ARCH_TUPLE "alpha-linux-gnu"
-#elif defined(__aarch64__)
-# if __BYTE_ORDER == __BIG_ENDIAN
-# define native_architecture() ARCHITECTURE_ARM64_BE
-# define LIB_ARCH_TUPLE "aarch64_be-linux-gnu"
-# else
-# define native_architecture() ARCHITECTURE_ARM64
-# define LIB_ARCH_TUPLE "aarch64-linux-gnu"
-# endif
-#elif defined(__arm__)
-# if __BYTE_ORDER == __BIG_ENDIAN
-# define native_architecture() ARCHITECTURE_ARM_BE
-# if defined(__ARM_EABI__)
-# if defined(__ARM_PCS_VFP)
-# define LIB_ARCH_TUPLE "armeb-linux-gnueabihf"
-# else
-# define LIB_ARCH_TUPLE "armeb-linux-gnueabi"
-# endif
-# else
-# define LIB_ARCH_TUPLE "armeb-linux-gnu"
-# endif
-# else
-# define native_architecture() ARCHITECTURE_ARM
-# if defined(__ARM_EABI__)
-# if defined(__ARM_PCS_VFP)
-# define LIB_ARCH_TUPLE "arm-linux-gnueabihf"
-# else
-# define LIB_ARCH_TUPLE "arm-linux-gnueabi"
-# endif
-# else
-# define LIB_ARCH_TUPLE "arm-linux-gnu"
-# endif
-# endif
-#elif defined(__sh64__)
-# define native_architecture() ARCHITECTURE_SH64
-# error "Missing LIB_ARCH_TUPLE for SH64"
-#elif defined(__sh__)
-# define native_architecture() ARCHITECTURE_SH
-# define LIB_ARCH_TUPLE "sh4-linux-gnu"
-#elif defined(__m68k__)
-# define native_architecture() ARCHITECTURE_M68K
-# define LIB_ARCH_TUPLE "m68k-linux-gnu"
-#elif defined(__tilegx__)
-# define native_architecture() ARCHITECTURE_TILEGX
-# error "Missing LIB_ARCH_TUPLE for TILEGX"
-#elif defined(__cris__)
-# define native_architecture() ARCHITECTURE_CRIS
-# error "Missing LIB_ARCH_TUPLE for CRIS"
-#elif defined(__nios2__)
-# define native_architecture() ARCHITECTURE_NIOS2
-# define LIB_ARCH_TUPLE "nios2-linux-gnu"
-#elif defined(__riscv__)
-# if __SIZEOF_POINTER__ == 4
-# define native_architecture() ARCHITECTURE_RISCV32
-# define LIB_ARCH_TUPLE "riscv32-linux-gnu"
-# elif __SIZEOF_POINTER__ == 8
-# define native_architecture() ARCHITECTURE_RISCV64
-# define LIB_ARCH_TUPLE "riscv64-linux-gnu"
-# else
-# error "Unrecognized riscv architecture variant"
-# endif
-#else
-# error "Please register your architecture here!"
-#endif
-
-const char *architecture_to_string(int a) _const_;
-int architecture_from_string(const char *s) _pure_;
diff --git a/src/basic/arphrd-list.c b/src/basic/arphrd-list.c
deleted file mode 100644
index 2d598dc66f..0000000000
--- a/src/basic/arphrd-list.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 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 <net/if_arp.h>
-#include <string.h>
-
-#include "arphrd-list.h"
-#include "macro.h"
-
-static const struct arphrd_name* lookup_arphrd(register const char *str, register GPERF_LEN_TYPE len);
-
-#include "arphrd-from-name.h"
-#include "arphrd-to-name.h"
-
-const char *arphrd_to_name(int id) {
-
- if (id <= 0)
- return NULL;
-
- if (id >= (int) ELEMENTSOF(arphrd_names))
- return NULL;
-
- return arphrd_names[id];
-}
-
-int arphrd_from_name(const char *name) {
- const struct arphrd_name *sc;
-
- assert(name);
-
- sc = lookup_arphrd(name, strlen(name));
- if (!sc)
- return 0;
-
- return sc->id;
-}
-
-int arphrd_max(void) {
- return ELEMENTSOF(arphrd_names);
-}
diff --git a/src/basic/arphrd-list.h b/src/basic/arphrd-list.h
deleted file mode 100644
index c0f8758dbe..0000000000
--- a/src/basic/arphrd-list.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 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/>.
-***/
-
-const char *arphrd_to_name(int id);
-int arphrd_from_name(const char *name);
-
-int arphrd_max(void);
diff --git a/src/basic/async.c b/src/basic/async.c
deleted file mode 100644
index a1f163f27b..0000000000
--- a/src/basic/async.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 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 <pthread.h>
-#include <stddef.h>
-#include <unistd.h>
-
-#include "async.h"
-#include "fd-util.h"
-#include "log.h"
-#include "macro.h"
-#include "util.h"
-
-int asynchronous_job(void* (*func)(void *p), void *arg) {
- pthread_attr_t a;
- pthread_t t;
- int r;
-
- /* It kinda sucks that we have to resort to threads to
- * implement an asynchronous sync(), but well, such is
- * life.
- *
- * Note that issuing this command right before exiting a
- * process will cause the process to wait for the sync() to
- * complete. This function hence is nicely asynchronous really
- * only in long running processes. */
-
- r = pthread_attr_init(&a);
- if (r > 0)
- return -r;
-
- r = pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED);
- if (r > 0)
- goto finish;
-
- r = pthread_create(&t, &a, func, arg);
-
-finish:
- pthread_attr_destroy(&a);
- return -r;
-}
-
-static void *sync_thread(void *p) {
- sync();
- return NULL;
-}
-
-int asynchronous_sync(void) {
- log_debug("Spawning new thread for sync");
-
- return asynchronous_job(sync_thread, NULL);
-}
-
-static void *close_thread(void *p) {
- assert_se(close_nointr(PTR_TO_FD(p)) != -EBADF);
- return NULL;
-}
-
-int asynchronous_close(int fd) {
- int r;
-
- /* This is supposed to behave similar to safe_close(), but
- * actually invoke close() asynchronously, so that it will
- * never block. Ideally the kernel would have an API for this,
- * but it doesn't, so we work around it, and hide this as a
- * far away as we can. */
-
- if (fd >= 0) {
- PROTECT_ERRNO;
-
- r = asynchronous_job(close_thread, FD_TO_PTR(fd));
- if (r < 0)
- assert_se(close_nointr(fd) != -EBADF);
- }
-
- return -1;
-}
diff --git a/src/basic/async.h b/src/basic/async.h
deleted file mode 100644
index 9bd13ff6e0..0000000000
--- a/src/basic/async.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 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/>.
-***/
-
-int asynchronous_job(void* (*func)(void *p), void *arg);
-
-int asynchronous_sync(void);
-int asynchronous_close(int fd);
diff --git a/src/basic/audit-util.c b/src/basic/audit-util.c
deleted file mode 100644
index d1c9695973..0000000000
--- a/src/basic/audit-util.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/***
- 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 <linux/netlink.h>
-#include <stdio.h>
-#include <sys/socket.h>
-
-#include "alloc-util.h"
-#include "audit-util.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "macro.h"
-#include "parse-util.h"
-#include "process-util.h"
-#include "user-util.h"
-
-int audit_session_from_pid(pid_t pid, uint32_t *id) {
- _cleanup_free_ char *s = NULL;
- const char *p;
- uint32_t u;
- int r;
-
- assert(id);
-
- /* We don't convert ENOENT to ESRCH here, since we can't
- * really distuingish between "audit is not available in the
- * kernel" and "the process does not exist", both which will
- * result in ENOENT. */
-
- p = procfs_file_alloca(pid, "sessionid");
-
- r = read_one_line_file(p, &s);
- if (r < 0)
- return r;
-
- r = safe_atou32(s, &u);
- if (r < 0)
- return r;
-
- if (u == AUDIT_SESSION_INVALID || u <= 0)
- return -ENODATA;
-
- *id = u;
- return 0;
-}
-
-int audit_loginuid_from_pid(pid_t pid, uid_t *uid) {
- _cleanup_free_ char *s = NULL;
- const char *p;
- uid_t u;
- int r;
-
- assert(uid);
-
- p = procfs_file_alloca(pid, "loginuid");
-
- r = read_one_line_file(p, &s);
- if (r < 0)
- return r;
-
- r = parse_uid(s, &u);
- if (r == -ENXIO) /* the UID was -1 */
- return -ENODATA;
- if (r < 0)
- return r;
-
- *uid = (uid_t) u;
- return 0;
-}
-
-bool use_audit(void) {
- static int cached_use = -1;
-
- if (cached_use < 0) {
- int fd;
-
- fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_AUDIT);
- if (fd < 0) {
- cached_use = !IN_SET(errno, EAFNOSUPPORT, EPROTONOSUPPORT, EPERM);
- if (errno == EPERM)
- log_debug_errno(errno, "Audit access prohibited, won't talk to audit");
- }
- else {
- cached_use = true;
- safe_close(fd);
- }
- }
-
- return cached_use;
-}
diff --git a/src/basic/audit-util.h b/src/basic/audit-util.h
deleted file mode 100644
index e048503991..0000000000
--- a/src/basic/audit-util.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#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 <stdint.h>
-#include <sys/types.h>
-
-#define AUDIT_SESSION_INVALID ((uint32_t) -1)
-
-int audit_session_from_pid(pid_t pid, uint32_t *id);
-int audit_loginuid_from_pid(pid_t pid, uid_t *uid);
-
-bool use_audit(void);
diff --git a/src/basic/barrier.c b/src/basic/barrier.c
deleted file mode 100644
index 2da633b311..0000000000
--- a/src/basic/barrier.c
+++ /dev/null
@@ -1,415 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
-
- 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 <fcntl.h>
-#include <poll.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <sys/eventfd.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "barrier.h"
-#include "fd-util.h"
-#include "macro.h"
-
-/**
- * Barriers
- * This barrier implementation provides a simple synchronization method based
- * on file-descriptors that can safely be used between threads and processes. A
- * barrier object contains 2 shared counters based on eventfd. Both processes
- * can now place barriers and wait for the other end to reach a random or
- * specific barrier.
- * Barriers are numbered, so you can either wait for the other end to reach any
- * barrier or the last barrier that you placed. This way, you can use barriers
- * for one-way *and* full synchronization. Note that even-though barriers are
- * numbered, these numbers are internal and recycled once both sides reached the
- * same barrier (implemented as a simple signed counter). It is thus not
- * possible to address barriers by their ID.
- *
- * Barrier-API: Both ends can place as many barriers via barrier_place() as
- * they want and each pair of barriers on both sides will be implicitly linked.
- * Each side can use the barrier_wait/sync_*() family of calls to wait for the
- * other side to place a specific barrier. barrier_wait_next() waits until the
- * other side calls barrier_place(). No links between the barriers are
- * considered and this simply serves as most basic asynchronous barrier.
- * barrier_sync_next() is like barrier_wait_next() and waits for the other side
- * to place their next barrier via barrier_place(). However, it only waits for
- * barriers that are linked to a barrier we already placed. If the other side
- * already placed more barriers than we did, barrier_sync_next() returns
- * immediately.
- * barrier_sync() extends barrier_sync_next() and waits until the other end
- * placed as many barriers via barrier_place() as we did. If they already placed
- * as many as we did (or more), it returns immediately.
- *
- * Additionally to basic barriers, an abortion event is available.
- * barrier_abort() places an abortion event that cannot be undone. An abortion
- * immediately cancels all placed barriers and replaces them. Any running and
- * following wait/sync call besides barrier_wait_abortion() will immediately
- * return false on both sides (otherwise, they always return true).
- * barrier_abort() can be called multiple times on both ends and will be a
- * no-op if already called on this side.
- * barrier_wait_abortion() can be used to wait for the other side to call
- * barrier_abort() and is the only wait/sync call that does not return
- * immediately if we aborted outself. It only returns once the other side
- * called barrier_abort().
- *
- * Barriers can be used for in-process and inter-process synchronization.
- * However, for in-process synchronization you could just use mutexes.
- * Therefore, main target is IPC and we require both sides to *not* share the FD
- * table. If that's given, barriers provide target tracking: If the remote side
- * exit()s, an abortion event is implicitly queued on the other side. This way,
- * a sync/wait call will be woken up if the remote side crashed or exited
- * unexpectedly. However, note that these abortion events are only queued if the
- * barrier-queue has been drained. Therefore, it is safe to place a barrier and
- * exit. The other side can safely wait on the barrier even though the exit
- * queued an abortion event. Usually, the abortion event would overwrite the
- * barrier, however, that's not true for exit-abortion events. Those are only
- * queued if the barrier-queue is drained (thus, the receiving side has placed
- * more barriers than the remote side).
- */
-
-/**
- * barrier_create() - Initialize a barrier object
- * @obj: barrier to initialize
- *
- * This initializes a barrier object. The caller is responsible of allocating
- * the memory and keeping it valid. The memory does not have to be zeroed
- * beforehand.
- * Two eventfd objects are allocated for each barrier. If allocation fails, an
- * error is returned.
- *
- * If this function fails, the barrier is reset to an invalid state so it is
- * safe to call barrier_destroy() on the object regardless whether the
- * initialization succeeded or not.
- *
- * The caller is responsible to destroy the object via barrier_destroy() before
- * releasing the underlying memory.
- *
- * Returns: 0 on success, negative error code on failure.
- */
-int barrier_create(Barrier *b) {
- _cleanup_(barrier_destroyp) Barrier *staging = b;
- int r;
-
- assert(b);
-
- b->me = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
- if (b->me < 0)
- return -errno;
-
- b->them = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
- if (b->them < 0)
- return -errno;
-
- r = pipe2(b->pipe, O_CLOEXEC | O_NONBLOCK);
- if (r < 0)
- return -errno;
-
- staging = NULL;
- return 0;
-}
-
-/**
- * barrier_destroy() - Destroy a barrier object
- * @b: barrier to destroy or NULL
- *
- * This destroys a barrier object that has previously been passed to
- * barrier_create(). The object is released and reset to invalid
- * state. Therefore, it is safe to call barrier_destroy() multiple
- * times or even if barrier_create() failed. However, barrier must be
- * always initialized with BARRIER_NULL.
- *
- * If @b is NULL, this is a no-op.
- */
-void barrier_destroy(Barrier *b) {
- if (!b)
- return;
-
- b->me = safe_close(b->me);
- b->them = safe_close(b->them);
- safe_close_pair(b->pipe);
- b->barriers = 0;
-}
-
-/**
- * barrier_set_role() - Set the local role of the barrier
- * @b: barrier to operate on
- * @role: role to set on the barrier
- *
- * This sets the roles on a barrier object. This is needed to know
- * which side of the barrier you're on. Usually, the parent creates
- * the barrier via barrier_create() and then calls fork() or clone().
- * Therefore, the FDs are duplicated and the child retains the same
- * barrier object.
- *
- * Both sides need to call barrier_set_role() after fork() or clone()
- * are done. If this is not done, barriers will not work correctly.
- *
- * Note that barriers could be supported without fork() or clone(). However,
- * this is currently not needed so it hasn't been implemented.
- */
-void barrier_set_role(Barrier *b, unsigned int role) {
- int fd;
-
- assert(b);
- assert(role == BARRIER_PARENT || role == BARRIER_CHILD);
- /* make sure this is only called once */
- assert(b->pipe[0] >= 0 && b->pipe[1] >= 0);
-
- if (role == BARRIER_PARENT)
- b->pipe[1] = safe_close(b->pipe[1]);
- else {
- b->pipe[0] = safe_close(b->pipe[0]);
-
- /* swap me/them for children */
- fd = b->me;
- b->me = b->them;
- b->them = fd;
- }
-}
-
-/* places barrier; returns false if we aborted, otherwise true */
-static bool barrier_write(Barrier *b, uint64_t buf) {
- ssize_t len;
-
- /* prevent new sync-points if we already aborted */
- if (barrier_i_aborted(b))
- return false;
-
- assert(b->me >= 0);
- do {
- len = write(b->me, &buf, sizeof(buf));
- } while (len < 0 && IN_SET(errno, EAGAIN, EINTR));
-
- if (len != sizeof(buf))
- goto error;
-
- /* lock if we aborted */
- if (buf >= (uint64_t)BARRIER_ABORTION) {
- if (barrier_they_aborted(b))
- b->barriers = BARRIER_WE_ABORTED;
- else
- b->barriers = BARRIER_I_ABORTED;
- } else if (!barrier_is_aborted(b))
- b->barriers += buf;
-
- return !barrier_i_aborted(b);
-
-error:
- /* If there is an unexpected error, we have to make this fatal. There
- * is no way we can recover from sync-errors. Therefore, we close the
- * pipe-ends and treat this as abortion. The other end will notice the
- * pipe-close and treat it as abortion, too. */
-
- safe_close_pair(b->pipe);
- b->barriers = BARRIER_WE_ABORTED;
- return false;
-}
-
-/* waits for barriers; returns false if they aborted, otherwise true */
-static bool barrier_read(Barrier *b, int64_t comp) {
- if (barrier_they_aborted(b))
- return false;
-
- while (b->barriers > comp) {
- struct pollfd pfd[2] = {
- { .fd = b->pipe[0] >= 0 ? b->pipe[0] : b->pipe[1],
- .events = POLLHUP },
- { .fd = b->them,
- .events = POLLIN }};
- uint64_t buf;
- int r;
-
- r = poll(pfd, 2, -1);
- if (r < 0 && IN_SET(errno, EAGAIN, EINTR))
- continue;
- else if (r < 0)
- goto error;
-
- if (pfd[1].revents) {
- ssize_t len;
-
- /* events on @them signal new data for us */
- len = read(b->them, &buf, sizeof(buf));
- if (len < 0 && IN_SET(errno, EAGAIN, EINTR))
- continue;
-
- if (len != sizeof(buf))
- goto error;
- } else if (pfd[0].revents & (POLLHUP | POLLERR | POLLNVAL))
- /* POLLHUP on the pipe tells us the other side exited.
- * We treat this as implicit abortion. But we only
- * handle it if there's no event on the eventfd. This
- * guarantees that exit-abortions do not overwrite real
- * barriers. */
- buf = BARRIER_ABORTION;
- else
- continue;
-
- /* lock if they aborted */
- if (buf >= (uint64_t)BARRIER_ABORTION) {
- if (barrier_i_aborted(b))
- b->barriers = BARRIER_WE_ABORTED;
- else
- b->barriers = BARRIER_THEY_ABORTED;
- } else if (!barrier_is_aborted(b))
- b->barriers -= buf;
- }
-
- return !barrier_they_aborted(b);
-
-error:
- /* If there is an unexpected error, we have to make this fatal. There
- * is no way we can recover from sync-errors. Therefore, we close the
- * pipe-ends and treat this as abortion. The other end will notice the
- * pipe-close and treat it as abortion, too. */
-
- safe_close_pair(b->pipe);
- b->barriers = BARRIER_WE_ABORTED;
- return false;
-}
-
-/**
- * barrier_place() - Place a new barrier
- * @b: barrier object
- *
- * This places a new barrier on the barrier object. If either side already
- * aborted, this is a no-op and returns "false". Otherwise, the barrier is
- * placed and this returns "true".
- *
- * Returns: true if barrier was placed, false if either side aborted.
- */
-bool barrier_place(Barrier *b) {
- assert(b);
-
- if (barrier_is_aborted(b))
- return false;
-
- barrier_write(b, BARRIER_SINGLE);
- return true;
-}
-
-/**
- * barrier_abort() - Abort the synchronization
- * @b: barrier object to abort
- *
- * This aborts the barrier-synchronization. If barrier_abort() was already
- * called on this side, this is a no-op. Otherwise, the barrier is put into the
- * ABORT-state and will stay there. The other side is notified about the
- * abortion. Any following attempt to place normal barriers or to wait on normal
- * barriers will return immediately as "false".
- *
- * You can wait for the other side to call barrier_abort(), too. Use
- * barrier_wait_abortion() for that.
- *
- * Returns: false if the other side already aborted, true otherwise.
- */
-bool barrier_abort(Barrier *b) {
- assert(b);
-
- barrier_write(b, BARRIER_ABORTION);
- return !barrier_they_aborted(b);
-}
-
-/**
- * barrier_wait_next() - Wait for the next barrier of the other side
- * @b: barrier to operate on
- *
- * This waits until the other side places its next barrier. This is independent
- * of any barrier-links and just waits for any next barrier of the other side.
- *
- * If either side aborted, this returns false.
- *
- * Returns: false if either side aborted, true otherwise.
- */
-bool barrier_wait_next(Barrier *b) {
- assert(b);
-
- if (barrier_is_aborted(b))
- return false;
-
- barrier_read(b, b->barriers - 1);
- return !barrier_is_aborted(b);
-}
-
-/**
- * barrier_wait_abortion() - Wait for the other side to abort
- * @b: barrier to operate on
- *
- * This waits until the other side called barrier_abort(). This can be called
- * regardless whether the local side already called barrier_abort() or not.
- *
- * If the other side has already aborted, this returns immediately.
- *
- * Returns: false if the local side aborted, true otherwise.
- */
-bool barrier_wait_abortion(Barrier *b) {
- assert(b);
-
- barrier_read(b, BARRIER_THEY_ABORTED);
- return !barrier_i_aborted(b);
-}
-
-/**
- * barrier_sync_next() - Wait for the other side to place a next linked barrier
- * @b: barrier to operate on
- *
- * This is like barrier_wait_next() and waits for the other side to call
- * barrier_place(). However, this only waits for linked barriers. That means, if
- * the other side already placed more barriers than (or as much as) we did, this
- * returns immediately instead of waiting.
- *
- * If either side aborted, this returns false.
- *
- * Returns: false if either side aborted, true otherwise.
- */
-bool barrier_sync_next(Barrier *b) {
- assert(b);
-
- if (barrier_is_aborted(b))
- return false;
-
- barrier_read(b, MAX((int64_t)0, b->barriers - 1));
- return !barrier_is_aborted(b);
-}
-
-/**
- * barrier_sync() - Wait for the other side to place as many barriers as we did
- * @b: barrier to operate on
- *
- * This is like barrier_sync_next() but waits for the other side to call
- * barrier_place() as often as we did (in total). If they already placed as much
- * as we did (or more), this returns immediately instead of waiting.
- *
- * If either side aborted, this returns false.
- *
- * Returns: false if either side aborted, true otherwise.
- */
-bool barrier_sync(Barrier *b) {
- assert(b);
-
- if (barrier_is_aborted(b))
- return false;
-
- barrier_read(b, 0);
- return !barrier_is_aborted(b);
-}
diff --git a/src/basic/barrier.h b/src/basic/barrier.h
deleted file mode 100644
index 6347fddc4d..0000000000
--- a/src/basic/barrier.h
+++ /dev/null
@@ -1,91 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
-
- 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 <stdint.h>
-#include <sys/types.h>
-
-#include "macro.h"
-
-/* See source file for an API description. */
-
-typedef struct Barrier Barrier;
-
-enum {
- BARRIER_SINGLE = 1LL,
- BARRIER_ABORTION = INT64_MAX,
-
- /* bias values to store state; keep @WE < @THEY < @I */
- BARRIER_BIAS = INT64_MIN,
- BARRIER_WE_ABORTED = BARRIER_BIAS + 1LL,
- BARRIER_THEY_ABORTED = BARRIER_BIAS + 2LL,
- BARRIER_I_ABORTED = BARRIER_BIAS + 3LL,
-};
-
-enum {
- BARRIER_PARENT,
- BARRIER_CHILD,
-};
-
-struct Barrier {
- int me;
- int them;
- int pipe[2];
- int64_t barriers;
-};
-
-#define BARRIER_NULL {-1, -1, {-1, -1}, 0}
-
-int barrier_create(Barrier *obj);
-void barrier_destroy(Barrier *b);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(Barrier*, barrier_destroy);
-
-void barrier_set_role(Barrier *b, unsigned int role);
-
-bool barrier_place(Barrier *b);
-bool barrier_abort(Barrier *b);
-
-bool barrier_wait_next(Barrier *b);
-bool barrier_wait_abortion(Barrier *b);
-bool barrier_sync_next(Barrier *b);
-bool barrier_sync(Barrier *b);
-
-static inline bool barrier_i_aborted(Barrier *b) {
- return b->barriers == BARRIER_I_ABORTED || b->barriers == BARRIER_WE_ABORTED;
-}
-
-static inline bool barrier_they_aborted(Barrier *b) {
- return b->barriers == BARRIER_THEY_ABORTED || b->barriers == BARRIER_WE_ABORTED;
-}
-
-static inline bool barrier_we_aborted(Barrier *b) {
- return b->barriers == BARRIER_WE_ABORTED;
-}
-
-static inline bool barrier_is_aborted(Barrier *b) {
- return b->barriers == BARRIER_I_ABORTED || b->barriers == BARRIER_THEY_ABORTED || b->barriers == BARRIER_WE_ABORTED;
-}
-
-static inline bool barrier_place_and_sync(Barrier *b) {
- (void) barrier_place(b);
- return barrier_sync(b);
-}
diff --git a/src/basic/bitmap.c b/src/basic/bitmap.c
deleted file mode 100644
index f6212e6151..0000000000
--- a/src/basic/bitmap.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2015 Tom Gundersen
-
- 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 <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "alloc-util.h"
-#include "bitmap.h"
-#include "hashmap.h"
-#include "macro.h"
-
-struct Bitmap {
- uint64_t *bitmaps;
- size_t n_bitmaps;
- size_t bitmaps_allocated;
-};
-
-/* Bitmaps are only meant to store relatively small numbers
- * (corresponding to, say, an enum), so it is ok to limit
- * the max entry. 64k should be plenty. */
-#define BITMAPS_MAX_ENTRY 0xffff
-
-/* This indicates that we reached the end of the bitmap */
-#define BITMAP_END ((unsigned) -1)
-
-#define BITMAP_NUM_TO_OFFSET(n) ((n) / (sizeof(uint64_t) * 8))
-#define BITMAP_NUM_TO_REM(n) ((n) % (sizeof(uint64_t) * 8))
-#define BITMAP_OFFSET_TO_NUM(offset, rem) ((offset) * sizeof(uint64_t) * 8 + (rem))
-
-Bitmap *bitmap_new(void) {
- return new0(Bitmap, 1);
-}
-
-Bitmap *bitmap_copy(Bitmap *b) {
- Bitmap *ret;
-
- ret = bitmap_new();
- if (!ret)
- return NULL;
-
- ret->bitmaps = newdup(uint64_t, b->bitmaps, b->n_bitmaps);
- if (!ret->bitmaps)
- return mfree(ret);
-
- ret->n_bitmaps = ret->bitmaps_allocated = b->n_bitmaps;
- return ret;
-}
-
-void bitmap_free(Bitmap *b) {
- if (!b)
- return;
-
- free(b->bitmaps);
- free(b);
-}
-
-int bitmap_ensure_allocated(Bitmap **b) {
- Bitmap *a;
-
- assert(b);
-
- if (*b)
- return 0;
-
- a = bitmap_new();
- if (!a)
- return -ENOMEM;
-
- *b = a;
-
- return 0;
-}
-
-int bitmap_set(Bitmap *b, unsigned n) {
- uint64_t bitmask;
- unsigned offset;
-
- assert(b);
-
- /* we refuse to allocate huge bitmaps */
- if (n > BITMAPS_MAX_ENTRY)
- return -ERANGE;
-
- offset = BITMAP_NUM_TO_OFFSET(n);
-
- if (offset >= b->n_bitmaps) {
- if (!GREEDY_REALLOC0(b->bitmaps, b->bitmaps_allocated, offset + 1))
- return -ENOMEM;
-
- b->n_bitmaps = offset + 1;
- }
-
- bitmask = UINT64_C(1) << BITMAP_NUM_TO_REM(n);
-
- b->bitmaps[offset] |= bitmask;
-
- return 0;
-}
-
-void bitmap_unset(Bitmap *b, unsigned n) {
- uint64_t bitmask;
- unsigned offset;
-
- if (!b)
- return;
-
- offset = BITMAP_NUM_TO_OFFSET(n);
-
- if (offset >= b->n_bitmaps)
- return;
-
- bitmask = UINT64_C(1) << BITMAP_NUM_TO_REM(n);
-
- b->bitmaps[offset] &= ~bitmask;
-}
-
-bool bitmap_isset(Bitmap *b, unsigned n) {
- uint64_t bitmask;
- unsigned offset;
-
- if (!b)
- return false;
-
- offset = BITMAP_NUM_TO_OFFSET(n);
-
- if (offset >= b->n_bitmaps)
- return false;
-
- bitmask = UINT64_C(1) << BITMAP_NUM_TO_REM(n);
-
- return !!(b->bitmaps[offset] & bitmask);
-}
-
-bool bitmap_isclear(Bitmap *b) {
- unsigned i;
-
- if (!b)
- return true;
-
- for (i = 0; i < b->n_bitmaps; i++)
- if (b->bitmaps[i] != 0)
- return false;
-
- return true;
-}
-
-void bitmap_clear(Bitmap *b) {
-
- if (!b)
- return;
-
- b->bitmaps = mfree(b->bitmaps);
- b->n_bitmaps = 0;
- b->bitmaps_allocated = 0;
-}
-
-bool bitmap_iterate(Bitmap *b, Iterator *i, unsigned *n) {
- uint64_t bitmask;
- unsigned offset, rem;
-
- assert(i);
- assert(n);
-
- if (!b || i->idx == BITMAP_END)
- return false;
-
- offset = BITMAP_NUM_TO_OFFSET(i->idx);
- rem = BITMAP_NUM_TO_REM(i->idx);
- bitmask = UINT64_C(1) << rem;
-
- for (; offset < b->n_bitmaps; offset ++) {
- if (b->bitmaps[offset]) {
- for (; bitmask; bitmask <<= 1, rem ++) {
- if (b->bitmaps[offset] & bitmask) {
- *n = BITMAP_OFFSET_TO_NUM(offset, rem);
- i->idx = *n + 1;
-
- return true;
- }
- }
- }
-
- rem = 0;
- bitmask = 1;
- }
-
- i->idx = BITMAP_END;
-
- return false;
-}
-
-bool bitmap_equal(Bitmap *a, Bitmap *b) {
- size_t common_n_bitmaps;
- Bitmap *c;
- unsigned i;
-
- if (a == b)
- return true;
-
- if (!a != !b)
- return false;
-
- if (!a)
- return true;
-
- common_n_bitmaps = MIN(a->n_bitmaps, b->n_bitmaps);
- if (memcmp(a->bitmaps, b->bitmaps, sizeof(uint64_t) * common_n_bitmaps) != 0)
- return false;
-
- c = a->n_bitmaps > b->n_bitmaps ? a : b;
- for (i = common_n_bitmaps; i < c->n_bitmaps; i++)
- if (c->bitmaps[i] != 0)
- return false;
-
- return true;
-}
diff --git a/src/basic/bitmap.h b/src/basic/bitmap.h
deleted file mode 100644
index 63fdbe8bea..0000000000
--- a/src/basic/bitmap.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2015 Tom Gundersen
-
- 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 "hashmap.h"
-#include "macro.h"
-
-typedef struct Bitmap Bitmap;
-
-Bitmap *bitmap_new(void);
-Bitmap *bitmap_copy(Bitmap *b);
-int bitmap_ensure_allocated(Bitmap **b);
-void bitmap_free(Bitmap *b);
-
-int bitmap_set(Bitmap *b, unsigned n);
-void bitmap_unset(Bitmap *b, unsigned n);
-bool bitmap_isset(Bitmap *b, unsigned n);
-bool bitmap_isclear(Bitmap *b);
-void bitmap_clear(Bitmap *b);
-
-bool bitmap_iterate(Bitmap *b, Iterator *i, unsigned *n);
-
-bool bitmap_equal(Bitmap *a, Bitmap *b);
-
-#define BITMAP_FOREACH(n, b, i) \
- for ((i).idx = 0; bitmap_iterate((b), &(i), (unsigned*)&(n)); )
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(Bitmap*, bitmap_free);
-
-#define _cleanup_bitmap_free_ _cleanup_(bitmap_freep)
diff --git a/src/basic/blkid-util.h b/src/basic/blkid-util.h
deleted file mode 100644
index 7aa75eb091..0000000000
--- a/src/basic/blkid-util.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 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/>.
-***/
-
-#ifdef HAVE_BLKID
-#include <blkid/blkid.h>
-#endif
-
-#include "util.h"
-
-#ifdef HAVE_BLKID
-DEFINE_TRIVIAL_CLEANUP_FUNC(blkid_probe, blkid_free_probe);
-#define _cleanup_blkid_free_probe_ _cleanup_(blkid_free_probep)
-#endif
diff --git a/src/basic/btrfs-ctree.h b/src/basic/btrfs-ctree.h
deleted file mode 100644
index 66bdf9736e..0000000000
--- a/src/basic/btrfs-ctree.h
+++ /dev/null
@@ -1,96 +0,0 @@
-#pragma once
-
-#include "macro.h"
-#include "sparse-endian.h"
-
-/* Stolen from btrfs' ctree.h */
-
-struct btrfs_timespec {
- le64_t sec;
- le32_t nsec;
-} _packed_;
-
-struct btrfs_disk_key {
- le64_t objectid;
- uint8_t type;
- le64_t offset;
-} _packed_;
-
-struct btrfs_inode_item {
- le64_t generation;
- le64_t transid;
- le64_t size;
- le64_t nbytes;
- le64_t block_group;
- le32_t nlink;
- le32_t uid;
- le32_t gid;
- le32_t mode;
- le64_t rdev;
- le64_t flags;
- le64_t sequence;
- le64_t reserved[4];
- struct btrfs_timespec atime;
- struct btrfs_timespec ctime;
- struct btrfs_timespec mtime;
- struct btrfs_timespec otime;
-} _packed_;
-
-struct btrfs_root_item {
- struct btrfs_inode_item inode;
- le64_t generation;
- le64_t root_dirid;
- le64_t bytenr;
- le64_t byte_limit;
- le64_t bytes_used;
- le64_t last_snapshot;
- le64_t flags;
- le32_t refs;
- struct btrfs_disk_key drop_progress;
- uint8_t drop_level;
- uint8_t level;
- le64_t generation_v2;
- uint8_t uuid[BTRFS_UUID_SIZE];
- uint8_t parent_uuid[BTRFS_UUID_SIZE];
- uint8_t received_uuid[BTRFS_UUID_SIZE];
- le64_t ctransid;
- le64_t otransid;
- le64_t stransid;
- le64_t rtransid;
- struct btrfs_timespec ctime;
- struct btrfs_timespec otime;
- struct btrfs_timespec stime;
- struct btrfs_timespec rtime;
- le64_t reserved[8];
-} _packed_;
-
-#define BTRFS_ROOT_SUBVOL_RDONLY (1ULL << 0)
-
-struct btrfs_qgroup_info_item {
- le64_t generation;
- le64_t rfer;
- le64_t rfer_cmpr;
- le64_t excl;
- le64_t excl_cmpr;
-} _packed_;
-
-#define BTRFS_QGROUP_LIMIT_MAX_RFER (1ULL << 0)
-#define BTRFS_QGROUP_LIMIT_MAX_EXCL (1ULL << 1)
-#define BTRFS_QGROUP_LIMIT_RSV_RFER (1ULL << 2)
-#define BTRFS_QGROUP_LIMIT_RSV_EXCL (1ULL << 3)
-#define BTRFS_QGROUP_LIMIT_RFER_CMPR (1ULL << 4)
-#define BTRFS_QGROUP_LIMIT_EXCL_CMPR (1ULL << 5)
-
-struct btrfs_qgroup_limit_item {
- le64_t flags;
- le64_t max_rfer;
- le64_t max_excl;
- le64_t rsv_rfer;
- le64_t rsv_excl;
-} _packed_;
-
-struct btrfs_root_ref {
- le64_t dirid;
- le64_t sequence;
- le16_t name_len;
-} _packed_;
diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c
deleted file mode 100644
index 359d85f2e8..0000000000
--- a/src/basic/btrfs-util.c
+++ /dev/null
@@ -1,2075 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 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 <fcntl.h>
-#include <inttypes.h>
-#include <linux/loop.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <sys/sysmacros.h>
-#include <unistd.h>
-
-#ifdef HAVE_LINUX_BTRFS_H
-#include <linux/btrfs.h>
-#endif
-
-#include "alloc-util.h"
-#include "btrfs-ctree.h"
-#include "btrfs-util.h"
-#include "copy.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "io-util.h"
-#include "macro.h"
-#include "missing.h"
-#include "path-util.h"
-#include "selinux-util.h"
-#include "smack-util.h"
-#include "sparse-endian.h"
-#include "stat-util.h"
-#include "string-util.h"
-#include "time-util.h"
-#include "util.h"
-
-/* WARNING: Be careful with file system ioctls! When we get an fd, we
- * need to make sure it either refers to only a regular file or
- * directory, or that it is located on btrfs, before invoking any
- * btrfs ioctls. The ioctl numbers are reused by some device drivers
- * (such as DRM), and hence might have bad effects when invoked on
- * device nodes (that reference drivers) rather than fds to normal
- * files or directories. */
-
-static int validate_subvolume_name(const char *name) {
-
- if (!filename_is_valid(name))
- return -EINVAL;
-
- if (strlen(name) > BTRFS_SUBVOL_NAME_MAX)
- return -E2BIG;
-
- return 0;
-}
-
-static int open_parent(const char *path, int flags) {
- _cleanup_free_ char *parent = NULL;
- int fd;
-
- assert(path);
-
- parent = dirname_malloc(path);
- if (!parent)
- return -ENOMEM;
-
- fd = open(parent, flags);
- if (fd < 0)
- return -errno;
-
- return fd;
-}
-
-static int extract_subvolume_name(const char *path, const char **subvolume) {
- const char *fn;
- int r;
-
- assert(path);
- assert(subvolume);
-
- fn = basename(path);
-
- r = validate_subvolume_name(fn);
- if (r < 0)
- return r;
-
- *subvolume = fn;
- return 0;
-}
-
-int btrfs_is_filesystem(int fd) {
- struct statfs sfs;
-
- assert(fd >= 0);
-
- if (fstatfs(fd, &sfs) < 0)
- return -errno;
-
- return F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC);
-}
-
-int btrfs_is_subvol_fd(int fd) {
- struct stat st;
-
- assert(fd >= 0);
-
- /* On btrfs subvolumes always have the inode 256 */
-
- if (fstat(fd, &st) < 0)
- return -errno;
-
- if (!S_ISDIR(st.st_mode) || st.st_ino != 256)
- return 0;
-
- return btrfs_is_filesystem(fd);
-}
-
-int btrfs_is_subvol(const char *path) {
- _cleanup_close_ int fd = -1;
-
- assert(path);
-
- fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
- if (fd < 0)
- return -errno;
-
- return btrfs_is_subvol_fd(fd);
-}
-
-int btrfs_subvol_make(const char *path) {
- struct btrfs_ioctl_vol_args args = {};
- _cleanup_close_ int fd = -1;
- const char *subvolume;
- int r;
-
- assert(path);
-
- r = extract_subvolume_name(path, &subvolume);
- if (r < 0)
- return r;
-
- fd = open_parent(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
- if (fd < 0)
- return fd;
-
- strncpy(args.name, subvolume, sizeof(args.name)-1);
-
- if (ioctl(fd, BTRFS_IOC_SUBVOL_CREATE, &args) < 0)
- return -errno;
-
- return 0;
-}
-
-int btrfs_subvol_make_label(const char *path) {
- int r;
-
- assert(path);
-
- r = mac_selinux_create_file_prepare(path, S_IFDIR);
- if (r < 0)
- return r;
-
- r = btrfs_subvol_make(path);
- mac_selinux_create_file_clear();
-
- if (r < 0)
- return r;
-
- return mac_smack_fix(path, false, false);
-}
-
-int btrfs_subvol_set_read_only_fd(int fd, bool b) {
- uint64_t flags, nflags;
- struct stat st;
-
- assert(fd >= 0);
-
- if (fstat(fd, &st) < 0)
- return -errno;
-
- if (!S_ISDIR(st.st_mode) || st.st_ino != 256)
- return -EINVAL;
-
- if (ioctl(fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags) < 0)
- return -errno;
-
- if (b)
- nflags = flags | BTRFS_SUBVOL_RDONLY;
- else
- nflags = flags & ~BTRFS_SUBVOL_RDONLY;
-
- if (flags == nflags)
- return 0;
-
- if (ioctl(fd, BTRFS_IOC_SUBVOL_SETFLAGS, &nflags) < 0)
- return -errno;
-
- return 0;
-}
-
-int btrfs_subvol_set_read_only(const char *path, bool b) {
- _cleanup_close_ int fd = -1;
-
- fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
- if (fd < 0)
- return -errno;
-
- return btrfs_subvol_set_read_only_fd(fd, b);
-}
-
-int btrfs_subvol_get_read_only_fd(int fd) {
- uint64_t flags;
- struct stat st;
-
- assert(fd >= 0);
-
- if (fstat(fd, &st) < 0)
- return -errno;
-
- if (!S_ISDIR(st.st_mode) || st.st_ino != 256)
- return -EINVAL;
-
- if (ioctl(fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags) < 0)
- return -errno;
-
- return !!(flags & BTRFS_SUBVOL_RDONLY);
-}
-
-int btrfs_reflink(int infd, int outfd) {
- struct stat st;
- int r;
-
- assert(infd >= 0);
- assert(outfd >= 0);
-
- /* Make sure we invoke the ioctl on a regular file, so that no
- * device driver accidentally gets it. */
-
- if (fstat(outfd, &st) < 0)
- return -errno;
-
- if (!S_ISREG(st.st_mode))
- return -EINVAL;
-
- r = ioctl(outfd, BTRFS_IOC_CLONE, infd);
- if (r < 0)
- return -errno;
-
- return 0;
-}
-
-int btrfs_clone_range(int infd, uint64_t in_offset, int outfd, uint64_t out_offset, uint64_t sz) {
- struct btrfs_ioctl_clone_range_args args = {
- .src_fd = infd,
- .src_offset = in_offset,
- .src_length = sz,
- .dest_offset = out_offset,
- };
- struct stat st;
- int r;
-
- assert(infd >= 0);
- assert(outfd >= 0);
- assert(sz > 0);
-
- if (fstat(outfd, &st) < 0)
- return -errno;
-
- if (!S_ISREG(st.st_mode))
- return -EINVAL;
-
- r = ioctl(outfd, BTRFS_IOC_CLONE_RANGE, &args);
- if (r < 0)
- return -errno;
-
- return 0;
-}
-
-int btrfs_get_block_device_fd(int fd, dev_t *dev) {
- struct btrfs_ioctl_fs_info_args fsi = {};
- uint64_t id;
- int r;
-
- assert(fd >= 0);
- assert(dev);
-
- r = btrfs_is_filesystem(fd);
- if (r < 0)
- return r;
- if (!r)
- return -ENOTTY;
-
- if (ioctl(fd, BTRFS_IOC_FS_INFO, &fsi) < 0)
- return -errno;
-
- /* We won't do this for btrfs RAID */
- if (fsi.num_devices != 1)
- return 0;
-
- for (id = 1; id <= fsi.max_id; id++) {
- struct btrfs_ioctl_dev_info_args di = {
- .devid = id,
- };
- struct stat st;
-
- if (ioctl(fd, BTRFS_IOC_DEV_INFO, &di) < 0) {
- if (errno == ENODEV)
- continue;
-
- return -errno;
- }
-
- if (stat((char*) di.path, &st) < 0)
- return -errno;
-
- if (!S_ISBLK(st.st_mode))
- return -ENODEV;
-
- if (major(st.st_rdev) == 0)
- return -ENODEV;
-
- *dev = st.st_rdev;
- return 1;
- }
-
- return -ENODEV;
-}
-
-int btrfs_get_block_device(const char *path, dev_t *dev) {
- _cleanup_close_ int fd = -1;
-
- assert(path);
- assert(dev);
-
- fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- return btrfs_get_block_device_fd(fd, dev);
-}
-
-int btrfs_subvol_get_id_fd(int fd, uint64_t *ret) {
- struct btrfs_ioctl_ino_lookup_args args = {
- .objectid = BTRFS_FIRST_FREE_OBJECTID
- };
- int r;
-
- assert(fd >= 0);
- assert(ret);
-
- r = btrfs_is_filesystem(fd);
- if (r < 0)
- return r;
- if (!r)
- return -ENOTTY;
-
- if (ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args) < 0)
- return -errno;
-
- *ret = args.treeid;
- return 0;
-}
-
-int btrfs_subvol_get_id(int fd, const char *subvol, uint64_t *ret) {
- _cleanup_close_ int subvol_fd = -1;
-
- assert(fd >= 0);
- assert(ret);
-
- subvol_fd = openat(fd, subvol, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
- if (subvol_fd < 0)
- return -errno;
-
- return btrfs_subvol_get_id_fd(subvol_fd, ret);
-}
-
-static bool btrfs_ioctl_search_args_inc(struct btrfs_ioctl_search_args *args) {
- assert(args);
-
- /* the objectid, type, offset together make up the btrfs key,
- * which is considered a single 136byte integer when
- * comparing. This call increases the counter by one, dealing
- * with the overflow between the overflows */
-
- if (args->key.min_offset < (uint64_t) -1) {
- args->key.min_offset++;
- return true;
- }
-
- if (args->key.min_type < (uint8_t) -1) {
- args->key.min_type++;
- args->key.min_offset = 0;
- return true;
- }
-
- if (args->key.min_objectid < (uint64_t) -1) {
- args->key.min_objectid++;
- args->key.min_offset = 0;
- args->key.min_type = 0;
- return true;
- }
-
- return 0;
-}
-
-static void btrfs_ioctl_search_args_set(struct btrfs_ioctl_search_args *args, const struct btrfs_ioctl_search_header *h) {
- assert(args);
- assert(h);
-
- args->key.min_objectid = h->objectid;
- args->key.min_type = h->type;
- args->key.min_offset = h->offset;
-}
-
-static int btrfs_ioctl_search_args_compare(const struct btrfs_ioctl_search_args *args) {
- assert(args);
-
- /* Compare min and max */
-
- if (args->key.min_objectid < args->key.max_objectid)
- return -1;
- if (args->key.min_objectid > args->key.max_objectid)
- return 1;
-
- if (args->key.min_type < args->key.max_type)
- return -1;
- if (args->key.min_type > args->key.max_type)
- return 1;
-
- if (args->key.min_offset < args->key.max_offset)
- return -1;
- if (args->key.min_offset > args->key.max_offset)
- return 1;
-
- return 0;
-}
-
-#define FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) \
- for ((i) = 0, \
- (sh) = (const struct btrfs_ioctl_search_header*) (args).buf; \
- (i) < (args).key.nr_items; \
- (i)++, \
- (sh) = (const struct btrfs_ioctl_search_header*) ((uint8_t*) (sh) + sizeof(struct btrfs_ioctl_search_header) + (sh)->len))
-
-#define BTRFS_IOCTL_SEARCH_HEADER_BODY(sh) \
- ((void*) ((uint8_t*) sh + sizeof(struct btrfs_ioctl_search_header)))
-
-int btrfs_subvol_get_info_fd(int fd, uint64_t subvol_id, BtrfsSubvolInfo *ret) {
- struct btrfs_ioctl_search_args args = {
- /* Tree of tree roots */
- .key.tree_id = BTRFS_ROOT_TREE_OBJECTID,
-
- /* Look precisely for the subvolume items */
- .key.min_type = BTRFS_ROOT_ITEM_KEY,
- .key.max_type = BTRFS_ROOT_ITEM_KEY,
-
- .key.min_offset = 0,
- .key.max_offset = (uint64_t) -1,
-
- /* No restrictions on the other components */
- .key.min_transid = 0,
- .key.max_transid = (uint64_t) -1,
- };
-
- bool found = false;
- int r;
-
- assert(fd >= 0);
- assert(ret);
-
- if (subvol_id == 0) {
- r = btrfs_subvol_get_id_fd(fd, &subvol_id);
- if (r < 0)
- return r;
- } else {
- r = btrfs_is_filesystem(fd);
- if (r < 0)
- return r;
- if (!r)
- return -ENOTTY;
- }
-
- args.key.min_objectid = args.key.max_objectid = subvol_id;
-
- while (btrfs_ioctl_search_args_compare(&args) <= 0) {
- const struct btrfs_ioctl_search_header *sh;
- unsigned i;
-
- args.key.nr_items = 256;
- if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
- return -errno;
-
- if (args.key.nr_items <= 0)
- break;
-
- FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) {
-
- const struct btrfs_root_item *ri;
-
- /* Make sure we start the next search at least from this entry */
- btrfs_ioctl_search_args_set(&args, sh);
-
- if (sh->objectid != subvol_id)
- continue;
- if (sh->type != BTRFS_ROOT_ITEM_KEY)
- continue;
-
- /* Older versions of the struct lacked the otime setting */
- if (sh->len < offsetof(struct btrfs_root_item, otime) + sizeof(struct btrfs_timespec))
- continue;
-
- ri = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh);
-
- ret->otime = (usec_t) le64toh(ri->otime.sec) * USEC_PER_SEC +
- (usec_t) le32toh(ri->otime.nsec) / NSEC_PER_USEC;
-
- ret->subvol_id = subvol_id;
- ret->read_only = !!(le64toh(ri->flags) & BTRFS_ROOT_SUBVOL_RDONLY);
-
- assert_cc(sizeof(ri->uuid) == sizeof(ret->uuid));
- memcpy(&ret->uuid, ri->uuid, sizeof(ret->uuid));
- memcpy(&ret->parent_uuid, ri->parent_uuid, sizeof(ret->parent_uuid));
-
- found = true;
- goto finish;
- }
-
- /* Increase search key by one, to read the next item, if we can. */
- if (!btrfs_ioctl_search_args_inc(&args))
- break;
- }
-
-finish:
- if (!found)
- return -ENODATA;
-
- return 0;
-}
-
-int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *ret) {
-
- struct btrfs_ioctl_search_args args = {
- /* Tree of quota items */
- .key.tree_id = BTRFS_QUOTA_TREE_OBJECTID,
-
- /* The object ID is always 0 */
- .key.min_objectid = 0,
- .key.max_objectid = 0,
-
- /* Look precisely for the quota items */
- .key.min_type = BTRFS_QGROUP_STATUS_KEY,
- .key.max_type = BTRFS_QGROUP_LIMIT_KEY,
-
- /* No restrictions on the other components */
- .key.min_transid = 0,
- .key.max_transid = (uint64_t) -1,
- };
-
- bool found_info = false, found_limit = false;
- int r;
-
- assert(fd >= 0);
- assert(ret);
-
- if (qgroupid == 0) {
- r = btrfs_subvol_get_id_fd(fd, &qgroupid);
- if (r < 0)
- return r;
- } else {
- r = btrfs_is_filesystem(fd);
- if (r < 0)
- return r;
- if (!r)
- return -ENOTTY;
- }
-
- args.key.min_offset = args.key.max_offset = qgroupid;
-
- while (btrfs_ioctl_search_args_compare(&args) <= 0) {
- const struct btrfs_ioctl_search_header *sh;
- unsigned i;
-
- args.key.nr_items = 256;
- if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) {
- if (errno == ENOENT) /* quota tree is missing: quota disabled */
- break;
-
- return -errno;
- }
-
- if (args.key.nr_items <= 0)
- break;
-
- FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) {
-
- /* Make sure we start the next search at least from this entry */
- btrfs_ioctl_search_args_set(&args, sh);
-
- if (sh->objectid != 0)
- continue;
- if (sh->offset != qgroupid)
- continue;
-
- if (sh->type == BTRFS_QGROUP_INFO_KEY) {
- const struct btrfs_qgroup_info_item *qii = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh);
-
- ret->referenced = le64toh(qii->rfer);
- ret->exclusive = le64toh(qii->excl);
-
- found_info = true;
-
- } else if (sh->type == BTRFS_QGROUP_LIMIT_KEY) {
- const struct btrfs_qgroup_limit_item *qli = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh);
-
- if (le64toh(qli->flags) & BTRFS_QGROUP_LIMIT_MAX_RFER)
- ret->referenced_max = le64toh(qli->max_rfer);
- else
- ret->referenced_max = (uint64_t) -1;
-
- if (le64toh(qli->flags) & BTRFS_QGROUP_LIMIT_MAX_EXCL)
- ret->exclusive_max = le64toh(qli->max_excl);
- else
- ret->exclusive_max = (uint64_t) -1;
-
- found_limit = true;
- }
-
- if (found_info && found_limit)
- goto finish;
- }
-
- /* Increase search key by one, to read the next item, if we can. */
- if (!btrfs_ioctl_search_args_inc(&args))
- break;
- }
-
-finish:
- if (!found_limit && !found_info)
- return -ENODATA;
-
- if (!found_info) {
- ret->referenced = (uint64_t) -1;
- ret->exclusive = (uint64_t) -1;
- }
-
- if (!found_limit) {
- ret->referenced_max = (uint64_t) -1;
- ret->exclusive_max = (uint64_t) -1;
- }
-
- return 0;
-}
-
-int btrfs_qgroup_get_quota(const char *path, uint64_t qgroupid, BtrfsQuotaInfo *ret) {
- _cleanup_close_ int fd = -1;
-
- fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
- if (fd < 0)
- return -errno;
-
- return btrfs_qgroup_get_quota_fd(fd, qgroupid, ret);
-}
-
-int btrfs_subvol_find_subtree_qgroup(int fd, uint64_t subvol_id, uint64_t *ret) {
- uint64_t level, lowest = (uint64_t) -1, lowest_qgroupid = 0;
- _cleanup_free_ uint64_t *qgroups = NULL;
- int r, n, i;
-
- assert(fd >= 0);
- assert(ret);
-
- /* This finds the "subtree" qgroup for a specific
- * subvolume. This only works for subvolumes that have been
- * prepared with btrfs_subvol_auto_qgroup_fd() with
- * insert_intermediary_qgroup=true (or equivalent). For others
- * it will return the leaf qgroup instead. The two cases may
- * be distuingished via the return value, which is 1 in case
- * an appropriate "subtree" qgroup was found, and 0
- * otherwise. */
-
- if (subvol_id == 0) {
- r = btrfs_subvol_get_id_fd(fd, &subvol_id);
- if (r < 0)
- return r;
- }
-
- r = btrfs_qgroupid_split(subvol_id, &level, NULL);
- if (r < 0)
- return r;
- if (level != 0) /* Input must be a leaf qgroup */
- return -EINVAL;
-
- n = btrfs_qgroup_find_parents(fd, subvol_id, &qgroups);
- if (n < 0)
- return n;
-
- for (i = 0; i < n; i++) {
- uint64_t id;
-
- r = btrfs_qgroupid_split(qgroups[i], &level, &id);
- if (r < 0)
- return r;
-
- if (id != subvol_id)
- continue;
-
- if (lowest == (uint64_t) -1 || level < lowest) {
- lowest_qgroupid = qgroups[i];
- lowest = level;
- }
- }
-
- if (lowest == (uint64_t) -1) {
- /* No suitable higher-level qgroup found, let's return
- * the leaf qgroup instead, and indicate that with the
- * return value. */
-
- *ret = subvol_id;
- return 0;
- }
-
- *ret = lowest_qgroupid;
- return 1;
-}
-
-int btrfs_subvol_get_subtree_quota_fd(int fd, uint64_t subvol_id, BtrfsQuotaInfo *ret) {
- uint64_t qgroupid;
- int r;
-
- assert(fd >= 0);
- assert(ret);
-
- /* This determines the quota data of the qgroup with the
- * lowest level, that shares the id part with the specified
- * subvolume. This is useful for determining the quota data
- * for entire subvolume subtrees, as long as the subtrees have
- * been set up with btrfs_qgroup_subvol_auto_fd() or in a
- * compatible way */
-
- r = btrfs_subvol_find_subtree_qgroup(fd, subvol_id, &qgroupid);
- if (r < 0)
- return r;
-
- return btrfs_qgroup_get_quota_fd(fd, qgroupid, ret);
-}
-
-int btrfs_subvol_get_subtree_quota(const char *path, uint64_t subvol_id, BtrfsQuotaInfo *ret) {
- _cleanup_close_ int fd = -1;
-
- fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
- if (fd < 0)
- return -errno;
-
- return btrfs_subvol_get_subtree_quota_fd(fd, subvol_id, ret);
-}
-
-int btrfs_defrag_fd(int fd) {
- struct stat st;
-
- assert(fd >= 0);
-
- if (fstat(fd, &st) < 0)
- return -errno;
-
- if (!S_ISREG(st.st_mode))
- return -EINVAL;
-
- if (ioctl(fd, BTRFS_IOC_DEFRAG, NULL) < 0)
- return -errno;
-
- return 0;
-}
-
-int btrfs_defrag(const char *p) {
- _cleanup_close_ int fd = -1;
-
- fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
- if (fd < 0)
- return -errno;
-
- return btrfs_defrag_fd(fd);
-}
-
-int btrfs_quota_enable_fd(int fd, bool b) {
- struct btrfs_ioctl_quota_ctl_args args = {
- .cmd = b ? BTRFS_QUOTA_CTL_ENABLE : BTRFS_QUOTA_CTL_DISABLE,
- };
- int r;
-
- assert(fd >= 0);
-
- r = btrfs_is_filesystem(fd);
- if (r < 0)
- return r;
- if (!r)
- return -ENOTTY;
-
- if (ioctl(fd, BTRFS_IOC_QUOTA_CTL, &args) < 0)
- return -errno;
-
- return 0;
-}
-
-int btrfs_quota_enable(const char *path, bool b) {
- _cleanup_close_ int fd = -1;
-
- fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
- if (fd < 0)
- return -errno;
-
- return btrfs_quota_enable_fd(fd, b);
-}
-
-int btrfs_qgroup_set_limit_fd(int fd, uint64_t qgroupid, uint64_t referenced_max) {
-
- struct btrfs_ioctl_qgroup_limit_args args = {
- .lim.max_rfer = referenced_max,
- .lim.flags = BTRFS_QGROUP_LIMIT_MAX_RFER,
- };
- unsigned c;
- int r;
-
- assert(fd >= 0);
-
- if (qgroupid == 0) {
- r = btrfs_subvol_get_id_fd(fd, &qgroupid);
- if (r < 0)
- return r;
- } else {
- r = btrfs_is_filesystem(fd);
- if (r < 0)
- return r;
- if (!r)
- return -ENOTTY;
- }
-
- args.qgroupid = qgroupid;
-
- for (c = 0;; c++) {
- if (ioctl(fd, BTRFS_IOC_QGROUP_LIMIT, &args) < 0) {
-
- if (errno == EBUSY && c < 10) {
- (void) btrfs_quota_scan_wait(fd);
- continue;
- }
-
- return -errno;
- }
-
- break;
- }
-
- return 0;
-}
-
-int btrfs_qgroup_set_limit(const char *path, uint64_t qgroupid, uint64_t referenced_max) {
- _cleanup_close_ int fd = -1;
-
- fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
- if (fd < 0)
- return -errno;
-
- return btrfs_qgroup_set_limit_fd(fd, qgroupid, referenced_max);
-}
-
-int btrfs_subvol_set_subtree_quota_limit_fd(int fd, uint64_t subvol_id, uint64_t referenced_max) {
- uint64_t qgroupid;
- int r;
-
- assert(fd >= 0);
-
- r = btrfs_subvol_find_subtree_qgroup(fd, subvol_id, &qgroupid);
- if (r < 0)
- return r;
-
- return btrfs_qgroup_set_limit_fd(fd, qgroupid, referenced_max);
-}
-
-int btrfs_subvol_set_subtree_quota_limit(const char *path, uint64_t subvol_id, uint64_t referenced_max) {
- _cleanup_close_ int fd = -1;
-
- fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
- if (fd < 0)
- return -errno;
-
- return btrfs_subvol_set_subtree_quota_limit_fd(fd, subvol_id, referenced_max);
-}
-
-int btrfs_resize_loopback_fd(int fd, uint64_t new_size, bool grow_only) {
- struct btrfs_ioctl_vol_args args = {};
- _cleanup_free_ char *p = NULL, *loop = NULL, *backing = NULL;
- _cleanup_close_ int loop_fd = -1, backing_fd = -1;
- struct stat st;
- dev_t dev = 0;
- int r;
-
- /* In contrast to btrfs quota ioctls ftruncate() cannot make sense of "infinity" or file sizes > 2^31 */
- if (!FILE_SIZE_VALID(new_size))
- return -EINVAL;
-
- /* btrfs cannot handle file systems < 16M, hence use this as minimum */
- if (new_size < 16*1024*1024)
- new_size = 16*1024*1024;
-
- r = btrfs_get_block_device_fd(fd, &dev);
- if (r < 0)
- return r;
- if (r == 0)
- return -ENODEV;
-
- if (asprintf(&p, "/sys/dev/block/%u:%u/loop/backing_file", major(dev), minor(dev)) < 0)
- return -ENOMEM;
- r = read_one_line_file(p, &backing);
- if (r == -ENOENT)
- return -ENODEV;
- if (r < 0)
- return r;
- if (isempty(backing) || !path_is_absolute(backing))
- return -ENODEV;
-
- backing_fd = open(backing, O_RDWR|O_CLOEXEC|O_NOCTTY);
- if (backing_fd < 0)
- return -errno;
-
- if (fstat(backing_fd, &st) < 0)
- return -errno;
- if (!S_ISREG(st.st_mode))
- return -ENODEV;
-
- if (new_size == (uint64_t) st.st_size)
- return 0;
-
- if (grow_only && new_size < (uint64_t) st.st_size)
- return -EINVAL;
-
- if (asprintf(&loop, "/dev/block/%u:%u", major(dev), minor(dev)) < 0)
- return -ENOMEM;
- loop_fd = open(loop, O_RDWR|O_CLOEXEC|O_NOCTTY);
- if (loop_fd < 0)
- return -errno;
-
- if (snprintf(args.name, sizeof(args.name), "%" PRIu64, new_size) >= (int) sizeof(args.name))
- return -EINVAL;
-
- if (new_size < (uint64_t) st.st_size) {
- /* Decrease size: first decrease btrfs size, then shorten loopback */
- if (ioctl(fd, BTRFS_IOC_RESIZE, &args) < 0)
- return -errno;
- }
-
- if (ftruncate(backing_fd, new_size) < 0)
- return -errno;
-
- if (ioctl(loop_fd, LOOP_SET_CAPACITY, 0) < 0)
- return -errno;
-
- if (new_size > (uint64_t) st.st_size) {
- /* Increase size: first enlarge loopback, then increase btrfs size */
- if (ioctl(fd, BTRFS_IOC_RESIZE, &args) < 0)
- return -errno;
- }
-
- /* Make sure the free disk space is correctly updated for both file systems */
- (void) fsync(fd);
- (void) fsync(backing_fd);
-
- return 1;
-}
-
-int btrfs_resize_loopback(const char *p, uint64_t new_size, bool grow_only) {
- _cleanup_close_ int fd = -1;
-
- fd = open(p, O_RDONLY|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- return btrfs_resize_loopback_fd(fd, new_size, grow_only);
-}
-
-int btrfs_qgroupid_make(uint64_t level, uint64_t id, uint64_t *ret) {
- assert(ret);
-
- if (level >= (UINT64_C(1) << (64 - BTRFS_QGROUP_LEVEL_SHIFT)))
- return -EINVAL;
-
- if (id >= (UINT64_C(1) << BTRFS_QGROUP_LEVEL_SHIFT))
- return -EINVAL;
-
- *ret = (level << BTRFS_QGROUP_LEVEL_SHIFT) | id;
- return 0;
-}
-
-int btrfs_qgroupid_split(uint64_t qgroupid, uint64_t *level, uint64_t *id) {
- assert(level || id);
-
- if (level)
- *level = qgroupid >> BTRFS_QGROUP_LEVEL_SHIFT;
-
- if (id)
- *id = qgroupid & ((UINT64_C(1) << BTRFS_QGROUP_LEVEL_SHIFT) - 1);
-
- return 0;
-}
-
-static int qgroup_create_or_destroy(int fd, bool b, uint64_t qgroupid) {
-
- struct btrfs_ioctl_qgroup_create_args args = {
- .create = b,
- .qgroupid = qgroupid,
- };
- unsigned c;
- int r;
-
- r = btrfs_is_filesystem(fd);
- if (r < 0)
- return r;
- if (r == 0)
- return -ENOTTY;
-
- for (c = 0;; c++) {
- if (ioctl(fd, BTRFS_IOC_QGROUP_CREATE, &args) < 0) {
-
- /* If quota is not enabled, we get EINVAL. Turn this into a recognizable error */
- if (errno == EINVAL)
- return -ENOPROTOOPT;
-
- if (errno == EBUSY && c < 10) {
- (void) btrfs_quota_scan_wait(fd);
- continue;
- }
-
- return -errno;
- }
-
- break;
- }
-
- return 0;
-}
-
-int btrfs_qgroup_create(int fd, uint64_t qgroupid) {
- return qgroup_create_or_destroy(fd, true, qgroupid);
-}
-
-int btrfs_qgroup_destroy(int fd, uint64_t qgroupid) {
- return qgroup_create_or_destroy(fd, false, qgroupid);
-}
-
-int btrfs_qgroup_destroy_recursive(int fd, uint64_t qgroupid) {
- _cleanup_free_ uint64_t *qgroups = NULL;
- uint64_t subvol_id;
- int i, n, r;
-
- /* Destroys the specified qgroup, but unassigns it from all
- * its parents first. Also, it recursively destroys all
- * qgroups it is assgined to that have the same id part of the
- * qgroupid as the specified group. */
-
- r = btrfs_qgroupid_split(qgroupid, NULL, &subvol_id);
- if (r < 0)
- return r;
-
- n = btrfs_qgroup_find_parents(fd, qgroupid, &qgroups);
- if (n < 0)
- return n;
-
- for (i = 0; i < n; i++) {
- uint64_t id;
-
- r = btrfs_qgroupid_split(qgroups[i], NULL, &id);
- if (r < 0)
- return r;
-
- r = btrfs_qgroup_unassign(fd, qgroupid, qgroups[i]);
- if (r < 0)
- return r;
-
- if (id != subvol_id)
- continue;
-
- /* The parent qgroupid shares the same id part with
- * us? If so, destroy it too. */
-
- (void) btrfs_qgroup_destroy_recursive(fd, qgroups[i]);
- }
-
- return btrfs_qgroup_destroy(fd, qgroupid);
-}
-
-int btrfs_quota_scan_start(int fd) {
- struct btrfs_ioctl_quota_rescan_args args = {};
-
- assert(fd >= 0);
-
- if (ioctl(fd, BTRFS_IOC_QUOTA_RESCAN, &args) < 0)
- return -errno;
-
- return 0;
-}
-
-int btrfs_quota_scan_wait(int fd) {
- assert(fd >= 0);
-
- if (ioctl(fd, BTRFS_IOC_QUOTA_RESCAN_WAIT) < 0)
- return -errno;
-
- return 0;
-}
-
-int btrfs_quota_scan_ongoing(int fd) {
- struct btrfs_ioctl_quota_rescan_args args = {};
-
- assert(fd >= 0);
-
- if (ioctl(fd, BTRFS_IOC_QUOTA_RESCAN_STATUS, &args) < 0)
- return -errno;
-
- return !!args.flags;
-}
-
-static int qgroup_assign_or_unassign(int fd, bool b, uint64_t child, uint64_t parent) {
- struct btrfs_ioctl_qgroup_assign_args args = {
- .assign = b,
- .src = child,
- .dst = parent,
- };
- unsigned c;
- int r;
-
- r = btrfs_is_filesystem(fd);
- if (r < 0)
- return r;
- if (r == 0)
- return -ENOTTY;
-
- for (c = 0;; c++) {
- r = ioctl(fd, BTRFS_IOC_QGROUP_ASSIGN, &args);
- if (r < 0) {
- if (errno == EBUSY && c < 10) {
- (void) btrfs_quota_scan_wait(fd);
- continue;
- }
-
- return -errno;
- }
-
- if (r == 0)
- return 0;
-
- /* If the return value is > 0, we need to request a rescan */
-
- (void) btrfs_quota_scan_start(fd);
- return 1;
- }
-}
-
-int btrfs_qgroup_assign(int fd, uint64_t child, uint64_t parent) {
- return qgroup_assign_or_unassign(fd, true, child, parent);
-}
-
-int btrfs_qgroup_unassign(int fd, uint64_t child, uint64_t parent) {
- return qgroup_assign_or_unassign(fd, false, child, parent);
-}
-
-static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol_id, BtrfsRemoveFlags flags) {
- struct btrfs_ioctl_search_args args = {
- .key.tree_id = BTRFS_ROOT_TREE_OBJECTID,
-
- .key.min_objectid = BTRFS_FIRST_FREE_OBJECTID,
- .key.max_objectid = BTRFS_LAST_FREE_OBJECTID,
-
- .key.min_type = BTRFS_ROOT_BACKREF_KEY,
- .key.max_type = BTRFS_ROOT_BACKREF_KEY,
-
- .key.min_transid = 0,
- .key.max_transid = (uint64_t) -1,
- };
-
- struct btrfs_ioctl_vol_args vol_args = {};
- _cleanup_close_ int subvol_fd = -1;
- struct stat st;
- bool made_writable = false;
- int r;
-
- assert(fd >= 0);
- assert(subvolume);
-
- if (fstat(fd, &st) < 0)
- return -errno;
-
- if (!S_ISDIR(st.st_mode))
- return -EINVAL;
-
- subvol_fd = openat(fd, subvolume, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
- if (subvol_fd < 0)
- return -errno;
-
- if (subvol_id == 0) {
- r = btrfs_subvol_get_id_fd(subvol_fd, &subvol_id);
- if (r < 0)
- return r;
- }
-
- /* First, try to remove the subvolume. If it happens to be
- * already empty, this will just work. */
- strncpy(vol_args.name, subvolume, sizeof(vol_args.name)-1);
- if (ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &vol_args) >= 0) {
- (void) btrfs_qgroup_destroy_recursive(fd, subvol_id); /* for the leaf subvolumes, the qgroup id is identical to the subvol id */
- return 0;
- }
- if (!(flags & BTRFS_REMOVE_RECURSIVE) || errno != ENOTEMPTY)
- return -errno;
-
- /* OK, the subvolume is not empty, let's look for child
- * subvolumes, and remove them, first */
-
- args.key.min_offset = args.key.max_offset = subvol_id;
-
- while (btrfs_ioctl_search_args_compare(&args) <= 0) {
- const struct btrfs_ioctl_search_header *sh;
- unsigned i;
-
- args.key.nr_items = 256;
- if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
- return -errno;
-
- if (args.key.nr_items <= 0)
- break;
-
- FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) {
- _cleanup_free_ char *p = NULL;
- const struct btrfs_root_ref *ref;
- struct btrfs_ioctl_ino_lookup_args ino_args;
-
- btrfs_ioctl_search_args_set(&args, sh);
-
- if (sh->type != BTRFS_ROOT_BACKREF_KEY)
- continue;
- if (sh->offset != subvol_id)
- continue;
-
- ref = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh);
-
- p = strndup((char*) ref + sizeof(struct btrfs_root_ref), le64toh(ref->name_len));
- if (!p)
- return -ENOMEM;
-
- zero(ino_args);
- ino_args.treeid = subvol_id;
- ino_args.objectid = htole64(ref->dirid);
-
- if (ioctl(fd, BTRFS_IOC_INO_LOOKUP, &ino_args) < 0)
- return -errno;
-
- if (!made_writable) {
- r = btrfs_subvol_set_read_only_fd(subvol_fd, false);
- if (r < 0)
- return r;
-
- made_writable = true;
- }
-
- if (isempty(ino_args.name))
- /* Subvolume is in the top-level
- * directory of the subvolume. */
- r = subvol_remove_children(subvol_fd, p, sh->objectid, flags);
- else {
- _cleanup_close_ int child_fd = -1;
-
- /* Subvolume is somewhere further down,
- * hence we need to open the
- * containing directory first */
-
- child_fd = openat(subvol_fd, ino_args.name, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
- if (child_fd < 0)
- return -errno;
-
- r = subvol_remove_children(child_fd, p, sh->objectid, flags);
- }
- if (r < 0)
- return r;
- }
-
- /* Increase search key by one, to read the next item, if we can. */
- if (!btrfs_ioctl_search_args_inc(&args))
- break;
- }
-
- /* OK, the child subvolumes should all be gone now, let's try
- * again to remove the subvolume */
- if (ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &vol_args) < 0)
- return -errno;
-
- (void) btrfs_qgroup_destroy_recursive(fd, subvol_id);
- return 0;
-}
-
-int btrfs_subvol_remove(const char *path, BtrfsRemoveFlags flags) {
- _cleanup_close_ int fd = -1;
- const char *subvolume;
- int r;
-
- assert(path);
-
- r = extract_subvolume_name(path, &subvolume);
- if (r < 0)
- return r;
-
- fd = open_parent(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
- if (fd < 0)
- return fd;
-
- return subvol_remove_children(fd, subvolume, 0, flags);
-}
-
-int btrfs_subvol_remove_fd(int fd, const char *subvolume, BtrfsRemoveFlags flags) {
- return subvol_remove_children(fd, subvolume, 0, flags);
-}
-
-int btrfs_qgroup_copy_limits(int fd, uint64_t old_qgroupid, uint64_t new_qgroupid) {
-
- struct btrfs_ioctl_search_args args = {
- /* Tree of quota items */
- .key.tree_id = BTRFS_QUOTA_TREE_OBJECTID,
-
- /* The object ID is always 0 */
- .key.min_objectid = 0,
- .key.max_objectid = 0,
-
- /* Look precisely for the quota items */
- .key.min_type = BTRFS_QGROUP_LIMIT_KEY,
- .key.max_type = BTRFS_QGROUP_LIMIT_KEY,
-
- /* For our qgroup */
- .key.min_offset = old_qgroupid,
- .key.max_offset = old_qgroupid,
-
- /* No restrictions on the other components */
- .key.min_transid = 0,
- .key.max_transid = (uint64_t) -1,
- };
-
- int r;
-
- r = btrfs_is_filesystem(fd);
- if (r < 0)
- return r;
- if (!r)
- return -ENOTTY;
-
- while (btrfs_ioctl_search_args_compare(&args) <= 0) {
- const struct btrfs_ioctl_search_header *sh;
- unsigned i;
-
- args.key.nr_items = 256;
- if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) {
- if (errno == ENOENT) /* quota tree missing: quota is not enabled, hence nothing to copy */
- break;
-
- return -errno;
- }
-
- if (args.key.nr_items <= 0)
- break;
-
- FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) {
- const struct btrfs_qgroup_limit_item *qli = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh);
- struct btrfs_ioctl_qgroup_limit_args qargs;
- unsigned c;
-
- /* Make sure we start the next search at least from this entry */
- btrfs_ioctl_search_args_set(&args, sh);
-
- if (sh->objectid != 0)
- continue;
- if (sh->type != BTRFS_QGROUP_LIMIT_KEY)
- continue;
- if (sh->offset != old_qgroupid)
- continue;
-
- /* We found the entry, now copy things over. */
-
- qargs = (struct btrfs_ioctl_qgroup_limit_args) {
- .qgroupid = new_qgroupid,
-
- .lim.max_rfer = le64toh(qli->max_rfer),
- .lim.max_excl = le64toh(qli->max_excl),
- .lim.rsv_rfer = le64toh(qli->rsv_rfer),
- .lim.rsv_excl = le64toh(qli->rsv_excl),
-
- .lim.flags = le64toh(qli->flags) & (BTRFS_QGROUP_LIMIT_MAX_RFER|
- BTRFS_QGROUP_LIMIT_MAX_EXCL|
- BTRFS_QGROUP_LIMIT_RSV_RFER|
- BTRFS_QGROUP_LIMIT_RSV_EXCL),
- };
-
- for (c = 0;; c++) {
- if (ioctl(fd, BTRFS_IOC_QGROUP_LIMIT, &qargs) < 0) {
- if (errno == EBUSY && c < 10) {
- (void) btrfs_quota_scan_wait(fd);
- continue;
- }
- return -errno;
- }
-
- break;
- }
-
- return 1;
- }
-
- /* Increase search key by one, to read the next item, if we can. */
- if (!btrfs_ioctl_search_args_inc(&args))
- break;
- }
-
- return 0;
-}
-
-static int copy_quota_hierarchy(int fd, uint64_t old_subvol_id, uint64_t new_subvol_id) {
- _cleanup_free_ uint64_t *old_qgroups = NULL, *old_parent_qgroups = NULL;
- bool copy_from_parent = false, insert_intermediary_qgroup = false;
- int n_old_qgroups, n_old_parent_qgroups, r, i;
- uint64_t old_parent_id;
-
- assert(fd >= 0);
-
- /* Copies a reduced form of quota information from the old to
- * the new subvolume. */
-
- n_old_qgroups = btrfs_qgroup_find_parents(fd, old_subvol_id, &old_qgroups);
- if (n_old_qgroups <= 0) /* Nothing to copy */
- return n_old_qgroups;
-
- r = btrfs_subvol_get_parent(fd, old_subvol_id, &old_parent_id);
- if (r == -ENXIO)
- /* We have no parent, hence nothing to copy. */
- n_old_parent_qgroups = 0;
- else if (r < 0)
- return r;
- else {
- n_old_parent_qgroups = btrfs_qgroup_find_parents(fd, old_parent_id, &old_parent_qgroups);
- if (n_old_parent_qgroups < 0)
- return n_old_parent_qgroups;
- }
-
- for (i = 0; i < n_old_qgroups; i++) {
- uint64_t id;
- int j;
-
- r = btrfs_qgroupid_split(old_qgroups[i], NULL, &id);
- if (r < 0)
- return r;
-
- if (id == old_subvol_id) {
- /* The old subvolume was member of a qgroup
- * that had the same id, but a different level
- * as it self. Let's set up something similar
- * in the destination. */
- insert_intermediary_qgroup = true;
- break;
- }
-
- for (j = 0; j < n_old_parent_qgroups; j++)
- if (old_parent_qgroups[j] == old_qgroups[i]) {
- /* The old subvolume shared a common
- * parent qgroup with its parent
- * subvolume. Let's set up something
- * similar in the destination. */
- copy_from_parent = true;
- }
- }
-
- if (!insert_intermediary_qgroup && !copy_from_parent)
- return 0;
-
- return btrfs_subvol_auto_qgroup_fd(fd, new_subvol_id, insert_intermediary_qgroup);
-}
-
-static int copy_subtree_quota_limits(int fd, uint64_t old_subvol, uint64_t new_subvol) {
- uint64_t old_subtree_qgroup, new_subtree_qgroup;
- bool changed;
- int r;
-
- /* First copy the leaf limits */
- r = btrfs_qgroup_copy_limits(fd, old_subvol, new_subvol);
- if (r < 0)
- return r;
- changed = r > 0;
-
- /* Then, try to copy the subtree limits, if there are any. */
- r = btrfs_subvol_find_subtree_qgroup(fd, old_subvol, &old_subtree_qgroup);
- if (r < 0)
- return r;
- if (r == 0)
- return changed;
-
- r = btrfs_subvol_find_subtree_qgroup(fd, new_subvol, &new_subtree_qgroup);
- if (r < 0)
- return r;
- if (r == 0)
- return changed;
-
- r = btrfs_qgroup_copy_limits(fd, old_subtree_qgroup, new_subtree_qgroup);
- if (r != 0)
- return r;
-
- return changed;
-}
-
-static int subvol_snapshot_children(int old_fd, int new_fd, const char *subvolume, uint64_t old_subvol_id, BtrfsSnapshotFlags flags) {
-
- struct btrfs_ioctl_search_args args = {
- .key.tree_id = BTRFS_ROOT_TREE_OBJECTID,
-
- .key.min_objectid = BTRFS_FIRST_FREE_OBJECTID,
- .key.max_objectid = BTRFS_LAST_FREE_OBJECTID,
-
- .key.min_type = BTRFS_ROOT_BACKREF_KEY,
- .key.max_type = BTRFS_ROOT_BACKREF_KEY,
-
- .key.min_transid = 0,
- .key.max_transid = (uint64_t) -1,
- };
-
- struct btrfs_ioctl_vol_args_v2 vol_args = {
- .flags = flags & BTRFS_SNAPSHOT_READ_ONLY ? BTRFS_SUBVOL_RDONLY : 0,
- .fd = old_fd,
- };
- _cleanup_close_ int subvolume_fd = -1;
- uint64_t new_subvol_id;
- int r;
-
- assert(old_fd >= 0);
- assert(new_fd >= 0);
- assert(subvolume);
-
- strncpy(vol_args.name, subvolume, sizeof(vol_args.name)-1);
-
- if (ioctl(new_fd, BTRFS_IOC_SNAP_CREATE_V2, &vol_args) < 0)
- return -errno;
-
- if (!(flags & BTRFS_SNAPSHOT_RECURSIVE) &&
- !(flags & BTRFS_SNAPSHOT_QUOTA))
- return 0;
-
- if (old_subvol_id == 0) {
- r = btrfs_subvol_get_id_fd(old_fd, &old_subvol_id);
- if (r < 0)
- return r;
- }
-
- r = btrfs_subvol_get_id(new_fd, vol_args.name, &new_subvol_id);
- if (r < 0)
- return r;
-
- if (flags & BTRFS_SNAPSHOT_QUOTA)
- (void) copy_quota_hierarchy(new_fd, old_subvol_id, new_subvol_id);
-
- if (!(flags & BTRFS_SNAPSHOT_RECURSIVE)) {
-
- if (flags & BTRFS_SNAPSHOT_QUOTA)
- (void) copy_subtree_quota_limits(new_fd, old_subvol_id, new_subvol_id);
-
- return 0;
- }
-
- args.key.min_offset = args.key.max_offset = old_subvol_id;
-
- while (btrfs_ioctl_search_args_compare(&args) <= 0) {
- const struct btrfs_ioctl_search_header *sh;
- unsigned i;
-
- args.key.nr_items = 256;
- if (ioctl(old_fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
- return -errno;
-
- if (args.key.nr_items <= 0)
- break;
-
- FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) {
- _cleanup_free_ char *p = NULL, *c = NULL, *np = NULL;
- struct btrfs_ioctl_ino_lookup_args ino_args;
- const struct btrfs_root_ref *ref;
- _cleanup_close_ int old_child_fd = -1, new_child_fd = -1;
-
- btrfs_ioctl_search_args_set(&args, sh);
-
- if (sh->type != BTRFS_ROOT_BACKREF_KEY)
- continue;
-
- /* Avoid finding the source subvolume a second
- * time */
- if (sh->offset != old_subvol_id)
- continue;
-
- /* Avoid running into loops if the new
- * subvolume is below the old one. */
- if (sh->objectid == new_subvol_id)
- continue;
-
- ref = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh);
- p = strndup((char*) ref + sizeof(struct btrfs_root_ref), le64toh(ref->name_len));
- if (!p)
- return -ENOMEM;
-
- zero(ino_args);
- ino_args.treeid = old_subvol_id;
- ino_args.objectid = htole64(ref->dirid);
-
- if (ioctl(old_fd, BTRFS_IOC_INO_LOOKUP, &ino_args) < 0)
- return -errno;
-
- /* The kernel returns an empty name if the
- * subvolume is in the top-level directory,
- * and otherwise appends a slash, so that we
- * can just concatenate easily here, without
- * adding a slash. */
- c = strappend(ino_args.name, p);
- if (!c)
- return -ENOMEM;
-
- old_child_fd = openat(old_fd, c, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
- if (old_child_fd < 0)
- return -errno;
-
- np = strjoin(subvolume, "/", ino_args.name, NULL);
- if (!np)
- return -ENOMEM;
-
- new_child_fd = openat(new_fd, np, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
- if (new_child_fd < 0)
- return -errno;
-
- if (flags & BTRFS_SNAPSHOT_READ_ONLY) {
- /* If the snapshot is read-only we
- * need to mark it writable
- * temporarily, to put the subsnapshot
- * into place. */
-
- if (subvolume_fd < 0) {
- subvolume_fd = openat(new_fd, subvolume, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
- if (subvolume_fd < 0)
- return -errno;
- }
-
- r = btrfs_subvol_set_read_only_fd(subvolume_fd, false);
- if (r < 0)
- return r;
- }
-
- /* When btrfs clones the subvolumes, child
- * subvolumes appear as empty directories. Remove
- * them, so that we can create a new snapshot
- * in their place */
- if (unlinkat(new_child_fd, p, AT_REMOVEDIR) < 0) {
- int k = -errno;
-
- if (flags & BTRFS_SNAPSHOT_READ_ONLY)
- (void) btrfs_subvol_set_read_only_fd(subvolume_fd, true);
-
- return k;
- }
-
- r = subvol_snapshot_children(old_child_fd, new_child_fd, p, sh->objectid, flags & ~BTRFS_SNAPSHOT_FALLBACK_COPY);
-
- /* Restore the readonly flag */
- if (flags & BTRFS_SNAPSHOT_READ_ONLY) {
- int k;
-
- k = btrfs_subvol_set_read_only_fd(subvolume_fd, true);
- if (r >= 0 && k < 0)
- return k;
- }
-
- if (r < 0)
- return r;
- }
-
- /* Increase search key by one, to read the next item, if we can. */
- if (!btrfs_ioctl_search_args_inc(&args))
- break;
- }
-
- if (flags & BTRFS_SNAPSHOT_QUOTA)
- (void) copy_subtree_quota_limits(new_fd, old_subvol_id, new_subvol_id);
-
- return 0;
-}
-
-int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlags flags) {
- _cleanup_close_ int new_fd = -1;
- const char *subvolume;
- int r;
-
- assert(old_fd >= 0);
- assert(new_path);
-
- r = btrfs_is_subvol_fd(old_fd);
- if (r < 0)
- return r;
- if (r == 0) {
- if (!(flags & BTRFS_SNAPSHOT_FALLBACK_COPY))
- return -EISDIR;
-
- r = btrfs_subvol_make(new_path);
- if (r < 0)
- return r;
-
- r = copy_directory_fd(old_fd, new_path, true);
- if (r < 0) {
- (void) btrfs_subvol_remove(new_path, BTRFS_REMOVE_QUOTA);
- return r;
- }
-
- if (flags & BTRFS_SNAPSHOT_READ_ONLY) {
- r = btrfs_subvol_set_read_only(new_path, true);
- if (r < 0) {
- (void) btrfs_subvol_remove(new_path, BTRFS_REMOVE_QUOTA);
- return r;
- }
- }
-
- return 0;
- }
-
- r = extract_subvolume_name(new_path, &subvolume);
- if (r < 0)
- return r;
-
- new_fd = open_parent(new_path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
- if (new_fd < 0)
- return new_fd;
-
- return subvol_snapshot_children(old_fd, new_fd, subvolume, 0, flags);
-}
-
-int btrfs_subvol_snapshot(const char *old_path, const char *new_path, BtrfsSnapshotFlags flags) {
- _cleanup_close_ int old_fd = -1;
-
- assert(old_path);
- assert(new_path);
-
- old_fd = open(old_path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
- if (old_fd < 0)
- return -errno;
-
- return btrfs_subvol_snapshot_fd(old_fd, new_path, flags);
-}
-
-int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret) {
-
- struct btrfs_ioctl_search_args args = {
- /* Tree of quota items */
- .key.tree_id = BTRFS_QUOTA_TREE_OBJECTID,
-
- /* Look precisely for the quota relation items */
- .key.min_type = BTRFS_QGROUP_RELATION_KEY,
- .key.max_type = BTRFS_QGROUP_RELATION_KEY,
-
- /* No restrictions on the other components */
- .key.min_offset = 0,
- .key.max_offset = (uint64_t) -1,
-
- .key.min_transid = 0,
- .key.max_transid = (uint64_t) -1,
- };
-
- _cleanup_free_ uint64_t *items = NULL;
- size_t n_items = 0, n_allocated = 0;
- int r;
-
- assert(fd >= 0);
- assert(ret);
-
- if (qgroupid == 0) {
- r = btrfs_subvol_get_id_fd(fd, &qgroupid);
- if (r < 0)
- return r;
- } else {
- r = btrfs_is_filesystem(fd);
- if (r < 0)
- return r;
- if (!r)
- return -ENOTTY;
- }
-
- args.key.min_objectid = args.key.max_objectid = qgroupid;
-
- while (btrfs_ioctl_search_args_compare(&args) <= 0) {
- const struct btrfs_ioctl_search_header *sh;
- unsigned i;
-
- args.key.nr_items = 256;
- if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) {
- if (errno == ENOENT) /* quota tree missing: quota is disabled */
- break;
-
- return -errno;
- }
-
- if (args.key.nr_items <= 0)
- break;
-
- FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) {
-
- /* Make sure we start the next search at least from this entry */
- btrfs_ioctl_search_args_set(&args, sh);
-
- if (sh->type != BTRFS_QGROUP_RELATION_KEY)
- continue;
- if (sh->offset < sh->objectid)
- continue;
- if (sh->objectid != qgroupid)
- continue;
-
- if (!GREEDY_REALLOC(items, n_allocated, n_items+1))
- return -ENOMEM;
-
- items[n_items++] = sh->offset;
- }
-
- /* Increase search key by one, to read the next item, if we can. */
- if (!btrfs_ioctl_search_args_inc(&args))
- break;
- }
-
- if (n_items <= 0) {
- *ret = NULL;
- return 0;
- }
-
- *ret = items;
- items = NULL;
-
- return (int) n_items;
-}
-
-int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool insert_intermediary_qgroup) {
- _cleanup_free_ uint64_t *qgroups = NULL;
- uint64_t parent_subvol;
- bool changed = false;
- int n = 0, r;
-
- assert(fd >= 0);
-
- /*
- * Sets up the specified subvolume's qgroup automatically in
- * one of two ways:
- *
- * If insert_intermediary_qgroup is false, the subvolume's
- * leaf qgroup will be assigned to the same parent qgroups as
- * the subvolume's parent subvolume.
- *
- * If insert_intermediary_qgroup is true a new intermediary
- * higher-level qgroup is created, with a higher level number,
- * but reusing the id of the subvolume. The level number is
- * picked as one smaller than the lowest level qgroup the
- * parent subvolume is a member of. If the parent subvolume's
- * leaf qgroup is assigned to no higher-level qgroup a new
- * qgroup of level 255 is created instead. Either way, the new
- * qgroup is then assigned to the parent's higher-level
- * qgroup, and the subvolume itself is assigned to it.
- *
- * If the subvolume is already assigned to a higher level
- * qgroup, no operation is executed.
- *
- * Effectively this means: regardless if
- * insert_intermediary_qgroup is true or not, after this
- * function is invoked the subvolume will be accounted within
- * the same qgroups as the parent. However, if it is true, it
- * will also get its own higher-level qgroup, which may in
- * turn be used by subvolumes created beneath this subvolume
- * later on.
- *
- * This hence defines a simple default qgroup setup for
- * subvolumes, as long as this function is invoked on each
- * created subvolume: each subvolume is always accounting
- * together with its immediate parents. Optionally, if
- * insert_intermediary_qgroup is true, it will also get a
- * qgroup that then includes all its own child subvolumes.
- */
-
- if (subvol_id == 0) {
- r = btrfs_is_subvol_fd(fd);
- if (r < 0)
- return r;
- if (!r)
- return -ENOTTY;
-
- r = btrfs_subvol_get_id_fd(fd, &subvol_id);
- if (r < 0)
- return r;
- }
-
- n = btrfs_qgroup_find_parents(fd, subvol_id, &qgroups);
- if (n < 0)
- return n;
- if (n > 0) /* already parent qgroups set up, let's bail */
- return 0;
-
- qgroups = mfree(qgroups);
-
- r = btrfs_subvol_get_parent(fd, subvol_id, &parent_subvol);
- if (r == -ENXIO)
- /* No parent, hence no qgroup memberships */
- n = 0;
- else if (r < 0)
- return r;
- else {
- n = btrfs_qgroup_find_parents(fd, parent_subvol, &qgroups);
- if (n < 0)
- return n;
- }
-
- if (insert_intermediary_qgroup) {
- uint64_t lowest = 256, new_qgroupid;
- bool created = false;
- int i;
-
- /* Determine the lowest qgroup that the parent
- * subvolume is assigned to. */
-
- for (i = 0; i < n; i++) {
- uint64_t level;
-
- r = btrfs_qgroupid_split(qgroups[i], &level, NULL);
- if (r < 0)
- return r;
-
- if (level < lowest)
- lowest = level;
- }
-
- if (lowest <= 1) /* There are no levels left we could use insert an intermediary qgroup at */
- return -EBUSY;
-
- r = btrfs_qgroupid_make(lowest - 1, subvol_id, &new_qgroupid);
- if (r < 0)
- return r;
-
- /* Create the new intermediary group, unless it already exists */
- r = btrfs_qgroup_create(fd, new_qgroupid);
- if (r < 0 && r != -EEXIST)
- return r;
- if (r >= 0)
- changed = created = true;
-
- for (i = 0; i < n; i++) {
- r = btrfs_qgroup_assign(fd, new_qgroupid, qgroups[i]);
- if (r < 0 && r != -EEXIST) {
- if (created)
- (void) btrfs_qgroup_destroy_recursive(fd, new_qgroupid);
-
- return r;
- }
- if (r >= 0)
- changed = true;
- }
-
- r = btrfs_qgroup_assign(fd, subvol_id, new_qgroupid);
- if (r < 0 && r != -EEXIST) {
- if (created)
- (void) btrfs_qgroup_destroy_recursive(fd, new_qgroupid);
- return r;
- }
- if (r >= 0)
- changed = true;
-
- } else {
- int i;
-
- /* Assign our subvolume to all the same qgroups as the parent */
-
- for (i = 0; i < n; i++) {
- r = btrfs_qgroup_assign(fd, subvol_id, qgroups[i]);
- if (r < 0 && r != -EEXIST)
- return r;
- if (r >= 0)
- changed = true;
- }
- }
-
- return changed;
-}
-
-int btrfs_subvol_auto_qgroup(const char *path, uint64_t subvol_id, bool create_intermediary_qgroup) {
- _cleanup_close_ int fd = -1;
-
- fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
- if (fd < 0)
- return -errno;
-
- return btrfs_subvol_auto_qgroup_fd(fd, subvol_id, create_intermediary_qgroup);
-}
-
-int btrfs_subvol_get_parent(int fd, uint64_t subvol_id, uint64_t *ret) {
-
- struct btrfs_ioctl_search_args args = {
- /* Tree of tree roots */
- .key.tree_id = BTRFS_ROOT_TREE_OBJECTID,
-
- /* Look precisely for the subvolume items */
- .key.min_type = BTRFS_ROOT_BACKREF_KEY,
- .key.max_type = BTRFS_ROOT_BACKREF_KEY,
-
- /* No restrictions on the other components */
- .key.min_offset = 0,
- .key.max_offset = (uint64_t) -1,
-
- .key.min_transid = 0,
- .key.max_transid = (uint64_t) -1,
- };
- int r;
-
- assert(fd >= 0);
- assert(ret);
-
- if (subvol_id == 0) {
- r = btrfs_subvol_get_id_fd(fd, &subvol_id);
- if (r < 0)
- return r;
- } else {
- r = btrfs_is_filesystem(fd);
- if (r < 0)
- return r;
- if (!r)
- return -ENOTTY;
- }
-
- args.key.min_objectid = args.key.max_objectid = subvol_id;
-
- while (btrfs_ioctl_search_args_compare(&args) <= 0) {
- const struct btrfs_ioctl_search_header *sh;
- unsigned i;
-
- args.key.nr_items = 256;
- if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
- return negative_errno();
-
- if (args.key.nr_items <= 0)
- break;
-
- FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) {
-
- if (sh->type != BTRFS_ROOT_BACKREF_KEY)
- continue;
- if (sh->objectid != subvol_id)
- continue;
-
- *ret = sh->offset;
- return 0;
- }
- }
-
- return -ENXIO;
-}
diff --git a/src/basic/btrfs-util.h b/src/basic/btrfs-util.h
deleted file mode 100644
index 1d852d502c..0000000000
--- a/src/basic/btrfs-util.h
+++ /dev/null
@@ -1,131 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 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 <stdint.h>
-#include <sys/types.h>
-
-#include "sd-id128.h"
-
-#include "time-util.h"
-
-typedef struct BtrfsSubvolInfo {
- uint64_t subvol_id;
- usec_t otime;
-
- sd_id128_t uuid;
- sd_id128_t parent_uuid;
-
- bool read_only;
-} BtrfsSubvolInfo;
-
-typedef struct BtrfsQuotaInfo {
- uint64_t referenced;
- uint64_t exclusive;
- uint64_t referenced_max;
- uint64_t exclusive_max;
-} BtrfsQuotaInfo;
-
-typedef enum BtrfsSnapshotFlags {
- BTRFS_SNAPSHOT_FALLBACK_COPY = 1,
- BTRFS_SNAPSHOT_READ_ONLY = 2,
- BTRFS_SNAPSHOT_RECURSIVE = 4,
- BTRFS_SNAPSHOT_QUOTA = 8,
-} BtrfsSnapshotFlags;
-
-typedef enum BtrfsRemoveFlags {
- BTRFS_REMOVE_RECURSIVE = 1,
- BTRFS_REMOVE_QUOTA = 2,
-} BtrfsRemoveFlags;
-
-int btrfs_is_filesystem(int fd);
-
-int btrfs_is_subvol_fd(int fd);
-int btrfs_is_subvol(const char *path);
-
-int btrfs_reflink(int infd, int outfd);
-int btrfs_clone_range(int infd, uint64_t in_offset, int ofd, uint64_t out_offset, uint64_t sz);
-
-int btrfs_get_block_device_fd(int fd, dev_t *dev);
-int btrfs_get_block_device(const char *path, dev_t *dev);
-
-int btrfs_defrag_fd(int fd);
-int btrfs_defrag(const char *p);
-
-int btrfs_quota_enable_fd(int fd, bool b);
-int btrfs_quota_enable(const char *path, bool b);
-
-int btrfs_quota_scan_start(int fd);
-int btrfs_quota_scan_wait(int fd);
-int btrfs_quota_scan_ongoing(int fd);
-
-int btrfs_resize_loopback_fd(int fd, uint64_t size, bool grow_only);
-int btrfs_resize_loopback(const char *path, uint64_t size, bool grow_only);
-
-int btrfs_subvol_make(const char *path);
-int btrfs_subvol_make_label(const char *path);
-
-int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlags flags);
-int btrfs_subvol_snapshot(const char *old_path, const char *new_path, BtrfsSnapshotFlags flags);
-
-int btrfs_subvol_remove(const char *path, BtrfsRemoveFlags flags);
-int btrfs_subvol_remove_fd(int fd, const char *subvolume, BtrfsRemoveFlags flags);
-
-int btrfs_subvol_set_read_only_fd(int fd, bool b);
-int btrfs_subvol_set_read_only(const char *path, bool b);
-int btrfs_subvol_get_read_only_fd(int fd);
-
-int btrfs_subvol_get_id(int fd, const char *subvolume, uint64_t *ret);
-int btrfs_subvol_get_id_fd(int fd, uint64_t *ret);
-int btrfs_subvol_get_parent(int fd, uint64_t subvol_id, uint64_t *ret);
-
-int btrfs_subvol_get_info_fd(int fd, uint64_t subvol_id, BtrfsSubvolInfo *info);
-
-int btrfs_subvol_find_subtree_qgroup(int fd, uint64_t subvol_id, uint64_t *ret);
-
-int btrfs_subvol_get_subtree_quota(const char *path, uint64_t subvol_id, BtrfsQuotaInfo *quota);
-int btrfs_subvol_get_subtree_quota_fd(int fd, uint64_t subvol_id, BtrfsQuotaInfo *quota);
-
-int btrfs_subvol_set_subtree_quota_limit(const char *path, uint64_t subvol_id, uint64_t referenced_max);
-int btrfs_subvol_set_subtree_quota_limit_fd(int fd, uint64_t subvol_id, uint64_t referenced_max);
-
-int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool new_qgroup);
-int btrfs_subvol_auto_qgroup(const char *path, uint64_t subvol_id, bool create_intermediary_qgroup);
-
-int btrfs_qgroupid_make(uint64_t level, uint64_t id, uint64_t *ret);
-int btrfs_qgroupid_split(uint64_t qgroupid, uint64_t *level, uint64_t *id);
-
-int btrfs_qgroup_create(int fd, uint64_t qgroupid);
-int btrfs_qgroup_destroy(int fd, uint64_t qgroupid);
-int btrfs_qgroup_destroy_recursive(int fd, uint64_t qgroupid);
-
-int btrfs_qgroup_set_limit_fd(int fd, uint64_t qgroupid, uint64_t referenced_max);
-int btrfs_qgroup_set_limit(const char *path, uint64_t qgroupid, uint64_t referenced_max);
-
-int btrfs_qgroup_copy_limits(int fd, uint64_t old_qgroupid, uint64_t new_qgroupid);
-
-int btrfs_qgroup_assign(int fd, uint64_t child, uint64_t parent);
-int btrfs_qgroup_unassign(int fd, uint64_t child, uint64_t parent);
-
-int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret);
-
-int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *quota);
-int btrfs_qgroup_get_quota(const char *path, uint64_t qgroupid, BtrfsQuotaInfo *quota);
diff --git a/src/basic/build.h b/src/basic/build.h
deleted file mode 100644
index 633c2aaccb..0000000000
--- a/src/basic/build.h
+++ /dev/null
@@ -1,155 +0,0 @@
-#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/>.
-***/
-
-#ifdef HAVE_PAM
-#define _PAM_FEATURE_ "+PAM"
-#else
-#define _PAM_FEATURE_ "-PAM"
-#endif
-
-#ifdef HAVE_AUDIT
-#define _AUDIT_FEATURE_ "+AUDIT"
-#else
-#define _AUDIT_FEATURE_ "-AUDIT"
-#endif
-
-#ifdef HAVE_SELINUX
-#define _SELINUX_FEATURE_ "+SELINUX"
-#else
-#define _SELINUX_FEATURE_ "-SELINUX"
-#endif
-
-#ifdef HAVE_APPARMOR
-#define _APPARMOR_FEATURE_ "+APPARMOR"
-#else
-#define _APPARMOR_FEATURE_ "-APPARMOR"
-#endif
-
-#ifdef HAVE_IMA
-#define _IMA_FEATURE_ "+IMA"
-#else
-#define _IMA_FEATURE_ "-IMA"
-#endif
-
-#ifdef HAVE_SMACK
-#define _SMACK_FEATURE_ "+SMACK"
-#else
-#define _SMACK_FEATURE_ "-SMACK"
-#endif
-
-#ifdef HAVE_SYSV_COMPAT
-#define _SYSVINIT_FEATURE_ "+SYSVINIT"
-#else
-#define _SYSVINIT_FEATURE_ "-SYSVINIT"
-#endif
-
-#ifdef HAVE_UTMP
-#define _UTMP_FEATURE_ "+UTMP"
-#else
-#define _UTMP_FEATURE_ "-UTMP"
-#endif
-
-#ifdef HAVE_LIBCRYPTSETUP
-#define _LIBCRYPTSETUP_FEATURE_ "+LIBCRYPTSETUP"
-#else
-#define _LIBCRYPTSETUP_FEATURE_ "-LIBCRYPTSETUP"
-#endif
-
-#ifdef HAVE_GCRYPT
-#define _GCRYPT_FEATURE_ "+GCRYPT"
-#else
-#define _GCRYPT_FEATURE_ "-GCRYPT"
-#endif
-
-#ifdef HAVE_GNUTLS
-#define _GNUTLS_FEATURE_ "+GNUTLS"
-#else
-#define _GNUTLS_FEATURE_ "-GNUTLS"
-#endif
-
-#ifdef HAVE_ACL
-#define _ACL_FEATURE_ "+ACL"
-#else
-#define _ACL_FEATURE_ "-ACL"
-#endif
-
-#ifdef HAVE_XZ
-#define _XZ_FEATURE_ "+XZ"
-#else
-#define _XZ_FEATURE_ "-XZ"
-#endif
-
-#ifdef HAVE_LZ4
-#define _LZ4_FEATURE_ "+LZ4"
-#else
-#define _LZ4_FEATURE_ "-LZ4"
-#endif
-
-#ifdef HAVE_SECCOMP
-#define _SECCOMP_FEATURE_ "+SECCOMP"
-#else
-#define _SECCOMP_FEATURE_ "-SECCOMP"
-#endif
-
-#ifdef HAVE_BLKID
-#define _BLKID_FEATURE_ "+BLKID"
-#else
-#define _BLKID_FEATURE_ "-BLKID"
-#endif
-
-#ifdef HAVE_ELFUTILS
-#define _ELFUTILS_FEATURE_ "+ELFUTILS"
-#else
-#define _ELFUTILS_FEATURE_ "-ELFUTILS"
-#endif
-
-#ifdef HAVE_KMOD
-#define _KMOD_FEATURE_ "+KMOD"
-#else
-#define _KMOD_FEATURE_ "-KMOD"
-#endif
-
-#ifdef HAVE_LIBIDN
-#define _IDN_FEATURE_ "+IDN"
-#else
-#define _IDN_FEATURE_ "-IDN"
-#endif
-
-#define SYSTEMD_FEATURES \
- _PAM_FEATURE_ " " \
- _AUDIT_FEATURE_ " " \
- _SELINUX_FEATURE_ " " \
- _IMA_FEATURE_ " " \
- _APPARMOR_FEATURE_ " " \
- _SMACK_FEATURE_ " " \
- _SYSVINIT_FEATURE_ " " \
- _UTMP_FEATURE_ " " \
- _LIBCRYPTSETUP_FEATURE_ " " \
- _GCRYPT_FEATURE_ " " \
- _GNUTLS_FEATURE_ " " \
- _ACL_FEATURE_ " " \
- _XZ_FEATURE_ " " \
- _LZ4_FEATURE_ " " \
- _SECCOMP_FEATURE_ " " \
- _BLKID_FEATURE_ " " \
- _ELFUTILS_FEATURE_ " " \
- _KMOD_FEATURE_ " " \
- _IDN_FEATURE_
diff --git a/src/basic/bus-label.c b/src/basic/bus-label.c
deleted file mode 100644
index d4531c7947..0000000000
--- a/src/basic/bus-label.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 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 "alloc-util.h"
-#include "bus-label.h"
-#include "hexdecoct.h"
-#include "macro.h"
-
-char *bus_label_escape(const char *s) {
- char *r, *t;
- const char *f;
-
- assert_return(s, NULL);
-
- /* Escapes all chars that D-Bus' object path cannot deal
- * with. Can be reversed with bus_path_unescape(). We special
- * case the empty string. */
-
- if (*s == 0)
- return strdup("_");
-
- r = new(char, strlen(s)*3 + 1);
- if (!r)
- return NULL;
-
- for (f = s, t = r; *f; f++) {
-
- /* Escape everything that is not a-zA-Z0-9. We also
- * escape 0-9 if it's the first character */
-
- if (!(*f >= 'A' && *f <= 'Z') &&
- !(*f >= 'a' && *f <= 'z') &&
- !(f > s && *f >= '0' && *f <= '9')) {
- *(t++) = '_';
- *(t++) = hexchar(*f >> 4);
- *(t++) = hexchar(*f);
- } else
- *(t++) = *f;
- }
-
- *t = 0;
-
- return r;
-}
-
-char *bus_label_unescape_n(const char *f, size_t l) {
- char *r, *t;
- size_t i;
-
- assert_return(f, NULL);
-
- /* Special case for the empty string */
- if (l == 1 && *f == '_')
- return strdup("");
-
- r = new(char, l + 1);
- if (!r)
- return NULL;
-
- for (i = 0, t = r; i < l; ++i) {
- if (f[i] == '_') {
- int a, b;
-
- if (l - i < 3 ||
- (a = unhexchar(f[i + 1])) < 0 ||
- (b = unhexchar(f[i + 2])) < 0) {
- /* Invalid escape code, let's take it literal then */
- *(t++) = '_';
- } else {
- *(t++) = (char) ((a << 4) | b);
- i += 2;
- }
- } else
- *(t++) = f[i];
- }
-
- *t = 0;
-
- return r;
-}
diff --git a/src/basic/bus-label.h b/src/basic/bus-label.h
deleted file mode 100644
index 62fb2c450c..0000000000
--- a/src/basic/bus-label.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 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 <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-char *bus_label_escape(const char *s);
-char *bus_label_unescape_n(const char *f, size_t l);
-
-static inline char *bus_label_unescape(const char *f) {
- return bus_label_unescape_n(f, f ? strlen(f) : 0);
-}
diff --git a/src/basic/calendarspec.c b/src/basic/calendarspec.c
deleted file mode 100644
index fda293fcb9..0000000000
--- a/src/basic/calendarspec.c
+++ /dev/null
@@ -1,1166 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 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 <alloca.h>
-#include <errno.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include "alloc-util.h"
-#include "calendarspec.h"
-#include "fileio.h"
-#include "macro.h"
-#include "parse-util.h"
-#include "string-util.h"
-
-/* Longest valid date/time range is 1970..2199 */
-#define MAX_RANGE_LEN 230
-#define BITS_WEEKDAYS 127
-
-static void free_chain(CalendarComponent *c) {
- CalendarComponent *n;
-
- while (c) {
- n = c->next;
- free(c);
- c = n;
- }
-}
-
-void calendar_spec_free(CalendarSpec *c) {
-
- if (!c)
- return;
-
- free_chain(c->year);
- free_chain(c->month);
- free_chain(c->day);
- free_chain(c->hour);
- free_chain(c->minute);
- free_chain(c->microsecond);
-
- free(c);
-}
-
-static int component_compare(const void *_a, const void *_b) {
- CalendarComponent * const *a = _a, * const *b = _b;
-
- if ((*a)->value < (*b)->value)
- return -1;
- if ((*a)->value > (*b)->value)
- return 1;
-
- if ((*a)->repeat < (*b)->repeat)
- return -1;
- if ((*a)->repeat > (*b)->repeat)
- return 1;
-
- return 0;
-}
-
-static void sort_chain(CalendarComponent **c) {
- unsigned n = 0, k;
- CalendarComponent **b, *i, **j, *next;
-
- assert(c);
-
- for (i = *c; i; i = i->next)
- n++;
-
- if (n <= 1)
- return;
-
- j = b = alloca(sizeof(CalendarComponent*) * n);
- for (i = *c; i; i = i->next)
- *(j++) = i;
-
- qsort(b, n, sizeof(CalendarComponent*), component_compare);
-
- b[n-1]->next = NULL;
- next = b[n-1];
-
- /* Drop non-unique entries */
- for (k = n-1; k > 0; k--) {
- if (b[k-1]->value == next->value &&
- b[k-1]->repeat == next->repeat) {
- free(b[k-1]);
- continue;
- }
-
- b[k-1]->next = next;
- next = b[k-1];
- }
-
- *c = next;
-}
-
-static void fix_year(CalendarComponent *c) {
- /* Turns 12 → 2012, 89 → 1989 */
-
- while (c) {
- CalendarComponent *n = c->next;
-
- if (c->value >= 0 && c->value < 70)
- c->value += 2000;
-
- if (c->value >= 70 && c->value < 100)
- c->value += 1900;
-
- c = n;
- }
-}
-
-int calendar_spec_normalize(CalendarSpec *c) {
- assert(c);
-
- if (c->weekdays_bits <= 0 || c->weekdays_bits >= BITS_WEEKDAYS)
- c->weekdays_bits = -1;
-
- fix_year(c->year);
-
- sort_chain(&c->year);
- sort_chain(&c->month);
- sort_chain(&c->day);
- sort_chain(&c->hour);
- sort_chain(&c->minute);
- sort_chain(&c->microsecond);
-
- return 0;
-}
-
-_pure_ static bool chain_valid(CalendarComponent *c, int from, int to) {
- if (!c)
- return true;
-
- if (c->value < from || c->value > to)
- return false;
-
- if (c->value + c->repeat > to)
- return false;
-
- if (c->next)
- return chain_valid(c->next, from, to);
-
- return true;
-}
-
-_pure_ bool calendar_spec_valid(CalendarSpec *c) {
- assert(c);
-
- if (c->weekdays_bits > BITS_WEEKDAYS)
- return false;
-
- if (!chain_valid(c->year, 1970, 2199))
- return false;
-
- if (!chain_valid(c->month, 1, 12))
- return false;
-
- if (!chain_valid(c->day, 1, 31))
- return false;
-
- if (!chain_valid(c->hour, 0, 23))
- return false;
-
- if (!chain_valid(c->minute, 0, 59))
- return false;
-
- if (!chain_valid(c->microsecond, 0, 60*USEC_PER_SEC-1))
- return false;
-
- return true;
-}
-
-static void format_weekdays(FILE *f, const CalendarSpec *c) {
- static const char *const days[] = {
- "Mon",
- "Tue",
- "Wed",
- "Thu",
- "Fri",
- "Sat",
- "Sun"
- };
-
- int l, x;
- bool need_comma = false;
-
- assert(f);
- assert(c);
- assert(c->weekdays_bits > 0 && c->weekdays_bits <= BITS_WEEKDAYS);
-
- for (x = 0, l = -1; x < (int) ELEMENTSOF(days); x++) {
-
- if (c->weekdays_bits & (1 << x)) {
-
- if (l < 0) {
- if (need_comma)
- fputc(',', f);
- else
- need_comma = true;
-
- fputs(days[x], f);
- l = x;
- }
-
- } else if (l >= 0) {
-
- if (x > l + 1) {
- fputs(x > l + 2 ? ".." : ",", f);
- fputs(days[x-1], f);
- }
-
- l = -1;
- }
- }
-
- if (l >= 0 && x > l + 1) {
- fputs(x > l + 2 ? ".." : ",", f);
- fputs(days[x-1], f);
- }
-}
-
-static void format_chain(FILE *f, int space, const CalendarComponent *c, bool usec) {
- assert(f);
-
- if (!c) {
- fputc('*', f);
- return;
- }
-
- assert(c->value >= 0);
- if (!usec)
- fprintf(f, "%0*i", space, c->value);
- else if (c->value % USEC_PER_SEC == 0)
- fprintf(f, "%0*i", space, (int) (c->value / USEC_PER_SEC));
- else
- fprintf(f, "%0*i.%06i", space, (int) (c->value / USEC_PER_SEC), (int) (c->value % USEC_PER_SEC));
-
- if (c->repeat > 0) {
- if (!usec)
- fprintf(f, "/%i", c->repeat);
- else if (c->repeat % USEC_PER_SEC == 0)
- fprintf(f, "/%i", (int) (c->repeat / USEC_PER_SEC));
- else
- fprintf(f, "/%i.%06i", (int) (c->repeat / USEC_PER_SEC), (int) (c->repeat % USEC_PER_SEC));
- }
-
- if (c->next) {
- fputc(',', f);
- format_chain(f, space, c->next, usec);
- }
-}
-
-int calendar_spec_to_string(const CalendarSpec *c, char **p) {
- char *buf = NULL;
- size_t sz = 0;
- FILE *f;
- int r;
-
- assert(c);
- assert(p);
-
- f = open_memstream(&buf, &sz);
- if (!f)
- return -ENOMEM;
-
- if (c->weekdays_bits > 0 && c->weekdays_bits <= BITS_WEEKDAYS) {
- format_weekdays(f, c);
- fputc(' ', f);
- }
-
- format_chain(f, 4, c->year, false);
- fputc('-', f);
- format_chain(f, 2, c->month, false);
- fputc('-', f);
- format_chain(f, 2, c->day, false);
- fputc(' ', f);
- format_chain(f, 2, c->hour, false);
- fputc(':', f);
- format_chain(f, 2, c->minute, false);
- fputc(':', f);
- format_chain(f, 2, c->microsecond, true);
-
- if (c->utc)
- fputs(" UTC", f);
- else if (IN_SET(c->dst, 0, 1)) {
-
- /* If daylight saving is explicitly on or off, let's show the used timezone. */
-
- tzset();
-
- if (!isempty(tzname[c->dst])) {
- fputc(' ', f);
- fputs(tzname[c->dst], f);
- }
- }
-
- r = fflush_and_check(f);
- if (r < 0) {
- free(buf);
- fclose(f);
- return r;
- }
-
- fclose(f);
-
- *p = buf;
- return 0;
-}
-
-static int parse_weekdays(const char **p, CalendarSpec *c) {
- static const struct {
- const char *name;
- const int nr;
- } day_nr[] = {
- { "Monday", 0 },
- { "Mon", 0 },
- { "Tuesday", 1 },
- { "Tue", 1 },
- { "Wednesday", 2 },
- { "Wed", 2 },
- { "Thursday", 3 },
- { "Thu", 3 },
- { "Friday", 4 },
- { "Fri", 4 },
- { "Saturday", 5 },
- { "Sat", 5 },
- { "Sunday", 6 },
- { "Sun", 6 }
- };
-
- int l = -1;
- bool first = true;
-
- assert(p);
- assert(*p);
- assert(c);
-
- for (;;) {
- unsigned i;
-
- if (!first && **p == ' ')
- return 0;
-
- for (i = 0; i < ELEMENTSOF(day_nr); i++) {
- size_t skip;
-
- if (!startswith_no_case(*p, day_nr[i].name))
- continue;
-
- skip = strlen(day_nr[i].name);
-
- if ((*p)[skip] != '-' &&
- (*p)[skip] != '.' &&
- (*p)[skip] != ',' &&
- (*p)[skip] != ' ' &&
- (*p)[skip] != 0)
- return -EINVAL;
-
- c->weekdays_bits |= 1 << day_nr[i].nr;
-
- if (l >= 0) {
- int j;
-
- if (l > day_nr[i].nr)
- return -EINVAL;
-
- for (j = l + 1; j < day_nr[i].nr; j++)
- c->weekdays_bits |= 1 << j;
- }
-
- *p += skip;
- break;
- }
-
- /* Couldn't find this prefix, so let's assume the
- weekday was not specified and let's continue with
- the date */
- if (i >= ELEMENTSOF(day_nr))
- return first ? 0 : -EINVAL;
-
- /* We reached the end of the string */
- if (**p == 0)
- return 0;
-
- /* We reached the end of the weekday spec part */
- if (**p == ' ') {
- *p += strspn(*p, " ");
- return 0;
- }
-
- if (**p == '.') {
- if (l >= 0)
- return -EINVAL;
-
- if ((*p)[1] != '.')
- return -EINVAL;
-
- l = day_nr[i].nr;
- *p += 1;
-
- /* Support ranges with "-" for backwards compatibility */
- } else if (**p == '-') {
- if (l >= 0)
- return -EINVAL;
-
- l = day_nr[i].nr;
- } else
- l = -1;
-
- *p += 1;
- first = false;
- }
-}
-
-static int parse_component_decimal(const char **p, bool usec, unsigned long *res) {
- unsigned long value;
- const char *e = NULL;
- char *ee = NULL;
- int r;
-
- errno = 0;
- value = strtoul(*p, &ee, 10);
- if (errno > 0)
- return -errno;
- if (ee == *p)
- return -EINVAL;
- if ((unsigned long) (int) value != value)
- return -ERANGE;
- e = ee;
-
- if (usec) {
- if (value * USEC_PER_SEC / USEC_PER_SEC != value)
- return -ERANGE;
-
- value *= USEC_PER_SEC;
- if (*e == '.') {
- unsigned add;
-
- e++;
- r = parse_fractional_part_u(&e, 6, &add);
- if (r < 0)
- return r;
-
- if (add + value < value)
- return -ERANGE;
- value += add;
- }
- }
-
- *p = e;
- *res = value;
-
- return 0;
-}
-
-static int const_chain(int value, CalendarComponent **c) {
- CalendarComponent *cc = NULL;
-
- assert(c);
-
- cc = new0(CalendarComponent, 1);
- if (!cc)
- return -ENOMEM;
-
- cc->value = value;
- cc->repeat = 0;
- cc->next = *c;
-
- *c = cc;
-
- return 0;
-}
-
-static int prepend_component(const char **p, bool usec, CalendarComponent **c) {
- unsigned long i, value, range_end, range_inc, repeat = 0;
- CalendarComponent *cc;
- int r;
- const char *e;
-
- assert(p);
- assert(c);
-
- e = *p;
-
- r = parse_component_decimal(&e, usec, &value);
- if (r < 0)
- return r;
-
- if (*e == '/') {
- e++;
- r = parse_component_decimal(&e, usec, &repeat);
- if (r < 0)
- return r;
-
- if (repeat == 0)
- return -ERANGE;
- } else if (e[0] == '.' && e[1] == '.') {
- e += 2;
- r = parse_component_decimal(&e, usec, &range_end);
- if (r < 0)
- return r;
-
- if (value >= range_end)
- return -EINVAL;
-
- range_inc = usec ? USEC_PER_SEC : 1;
-
- /* Don't allow impossibly large ranges... */
- if (range_end - value >= MAX_RANGE_LEN * range_inc)
- return -EINVAL;
-
- /* ...or ranges with only a single element */
- if (range_end - value < range_inc)
- return -EINVAL;
-
- for (i = value; i <= range_end; i += range_inc) {
- r = const_chain(i, c);
- if (r < 0)
- return r;
- }
- }
-
- if (*e != 0 && *e != ' ' && *e != ',' && *e != '-' && *e != ':')
- return -EINVAL;
-
- cc = new0(CalendarComponent, 1);
- if (!cc)
- return -ENOMEM;
-
- cc->value = value;
- cc->repeat = repeat;
- cc->next = *c;
-
- *p = e;
- *c = cc;
-
- if (*e ==',') {
- *p += 1;
- return prepend_component(p, usec, c);
- }
-
- return 0;
-}
-
-static int parse_chain(const char **p, bool usec, CalendarComponent **c) {
- const char *t;
- CalendarComponent *cc = NULL;
- int r;
-
- assert(p);
- assert(c);
-
- t = *p;
-
- if (t[0] == '*') {
- if (usec) {
- r = const_chain(0, c);
- if (r < 0)
- return r;
- (*c)->repeat = USEC_PER_SEC;
- } else
- *c = NULL;
-
- *p = t + 1;
- return 0;
- }
-
- r = prepend_component(&t, usec, &cc);
- if (r < 0) {
- free_chain(cc);
- return r;
- }
-
- *p = t;
- *c = cc;
- return 0;
-}
-
-static int parse_date(const char **p, CalendarSpec *c) {
- const char *t;
- int r;
- CalendarComponent *first, *second, *third;
-
- assert(p);
- assert(*p);
- assert(c);
-
- t = *p;
-
- if (*t == 0)
- return 0;
-
- r = parse_chain(&t, false, &first);
- if (r < 0)
- return r;
-
- /* Already the end? A ':' as separator? In that case this was a time, not a date */
- if (*t == 0 || *t == ':') {
- free_chain(first);
- return 0;
- }
-
- if (*t != '-') {
- free_chain(first);
- return -EINVAL;
- }
-
- t++;
- r = parse_chain(&t, false, &second);
- if (r < 0) {
- free_chain(first);
- return r;
- }
-
- /* Got two parts, hence it's month and day */
- if (*t == ' ' || *t == 0) {
- *p = t + strspn(t, " ");
- c->month = first;
- c->day = second;
- return 0;
- }
-
- if (*t != '-') {
- free_chain(first);
- free_chain(second);
- return -EINVAL;
- }
-
- t++;
- r = parse_chain(&t, false, &third);
- if (r < 0) {
- free_chain(first);
- free_chain(second);
- return r;
- }
-
- /* Got tree parts, hence it is year, month and day */
- if (*t == ' ' || *t == 0) {
- *p = t + strspn(t, " ");
- c->year = first;
- c->month = second;
- c->day = third;
- return 0;
- }
-
- free_chain(first);
- free_chain(second);
- free_chain(third);
- return -EINVAL;
-}
-
-static int parse_calendar_time(const char **p, CalendarSpec *c) {
- CalendarComponent *h = NULL, *m = NULL, *s = NULL;
- const char *t;
- int r;
-
- assert(p);
- assert(*p);
- assert(c);
-
- t = *p;
-
- if (*t == 0) {
- /* If no time is specified at all, but a date of some
- * kind, then this means 00:00:00 */
- if (c->day || c->weekdays_bits > 0)
- goto null_hour;
-
- goto finish;
- }
-
- r = parse_chain(&t, false, &h);
- if (r < 0)
- goto fail;
-
- if (*t != ':') {
- r = -EINVAL;
- goto fail;
- }
-
- t++;
- r = parse_chain(&t, false, &m);
- if (r < 0)
- goto fail;
-
- /* Already at the end? Then it's hours and minutes, and seconds are 0 */
- if (*t == 0) {
- if (m != NULL)
- goto null_second;
-
- goto finish;
- }
-
- if (*t != ':') {
- r = -EINVAL;
- goto fail;
- }
-
- t++;
- r = parse_chain(&t, true, &s);
- if (r < 0)
- goto fail;
-
- /* At the end? Then it's hours, minutes and seconds */
- if (*t == 0)
- goto finish;
-
- r = -EINVAL;
- goto fail;
-
-null_hour:
- r = const_chain(0, &h);
- if (r < 0)
- goto fail;
-
- r = const_chain(0, &m);
- if (r < 0)
- goto fail;
-
-null_second:
- r = const_chain(0, &s);
- if (r < 0)
- goto fail;
-
-finish:
- *p = t;
- c->hour = h;
- c->minute = m;
- c->microsecond = s;
-
- return 0;
-
-fail:
- free_chain(h);
- free_chain(m);
- free_chain(s);
- return r;
-}
-
-int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
- const char *utc;
- CalendarSpec *c;
- int r;
-
- assert(p);
- assert(spec);
-
- if (isempty(p))
- return -EINVAL;
-
- c = new0(CalendarSpec, 1);
- if (!c)
- return -ENOMEM;
- c->dst = -1;
-
- utc = endswith_no_case(p, " UTC");
- if (utc) {
- c->utc = true;
- p = strndupa(p, utc - p);
- } else {
- const char *e = NULL;
- int j;
-
- tzset();
-
- /* Check if the local timezone was specified? */
- for (j = 0; j <= 1; j++) {
- if (isempty(tzname[j]))
- continue;
-
- e = endswith_no_case(p, tzname[j]);
- if(!e)
- continue;
- if (e == p)
- continue;
- if (e[-1] != ' ')
- continue;
-
- break;
- }
-
- /* Found one of the two timezones specified? */
- if (IN_SET(j, 0, 1)) {
- p = strndupa(p, e - p - 1);
- c->dst = j;
- }
- }
-
- if (strcaseeq(p, "minutely")) {
- r = const_chain(0, &c->microsecond);
- if (r < 0)
- goto fail;
-
- } else if (strcaseeq(p, "hourly")) {
- r = const_chain(0, &c->minute);
- if (r < 0)
- goto fail;
- r = const_chain(0, &c->microsecond);
- if (r < 0)
- goto fail;
-
- } else if (strcaseeq(p, "daily")) {
- r = const_chain(0, &c->hour);
- if (r < 0)
- goto fail;
- r = const_chain(0, &c->minute);
- if (r < 0)
- goto fail;
- r = const_chain(0, &c->microsecond);
- if (r < 0)
- goto fail;
-
- } else if (strcaseeq(p, "monthly")) {
- r = const_chain(1, &c->day);
- if (r < 0)
- goto fail;
- r = const_chain(0, &c->hour);
- if (r < 0)
- goto fail;
- r = const_chain(0, &c->minute);
- if (r < 0)
- goto fail;
- r = const_chain(0, &c->microsecond);
- if (r < 0)
- goto fail;
-
- } else if (strcaseeq(p, "annually") ||
- strcaseeq(p, "yearly") ||
- strcaseeq(p, "anually") /* backwards compatibility */ ) {
-
- r = const_chain(1, &c->month);
- if (r < 0)
- goto fail;
- r = const_chain(1, &c->day);
- if (r < 0)
- goto fail;
- r = const_chain(0, &c->hour);
- if (r < 0)
- goto fail;
- r = const_chain(0, &c->minute);
- if (r < 0)
- goto fail;
- r = const_chain(0, &c->microsecond);
- if (r < 0)
- goto fail;
-
- } else if (strcaseeq(p, "weekly")) {
-
- c->weekdays_bits = 1;
-
- r = const_chain(0, &c->hour);
- if (r < 0)
- goto fail;
- r = const_chain(0, &c->minute);
- if (r < 0)
- goto fail;
- r = const_chain(0, &c->microsecond);
- if (r < 0)
- goto fail;
-
- } else if (strcaseeq(p, "quarterly")) {
-
- r = const_chain(1, &c->month);
- if (r < 0)
- goto fail;
- r = const_chain(4, &c->month);
- if (r < 0)
- goto fail;
- r = const_chain(7, &c->month);
- if (r < 0)
- goto fail;
- r = const_chain(10, &c->month);
- if (r < 0)
- goto fail;
- r = const_chain(1, &c->day);
- if (r < 0)
- goto fail;
- r = const_chain(0, &c->hour);
- if (r < 0)
- goto fail;
- r = const_chain(0, &c->minute);
- if (r < 0)
- goto fail;
- r = const_chain(0, &c->microsecond);
- if (r < 0)
- goto fail;
-
- } else if (strcaseeq(p, "biannually") ||
- strcaseeq(p, "bi-annually") ||
- strcaseeq(p, "semiannually") ||
- strcaseeq(p, "semi-annually")) {
-
- r = const_chain(1, &c->month);
- if (r < 0)
- goto fail;
- r = const_chain(7, &c->month);
- if (r < 0)
- goto fail;
- r = const_chain(1, &c->day);
- if (r < 0)
- goto fail;
- r = const_chain(0, &c->hour);
- if (r < 0)
- goto fail;
- r = const_chain(0, &c->minute);
- if (r < 0)
- goto fail;
- r = const_chain(0, &c->microsecond);
- if (r < 0)
- goto fail;
-
- } else {
- r = parse_weekdays(&p, c);
- if (r < 0)
- goto fail;
-
- r = parse_date(&p, c);
- if (r < 0)
- goto fail;
-
- r = parse_calendar_time(&p, c);
- if (r < 0)
- goto fail;
-
- if (*p != 0) {
- r = -EINVAL;
- goto fail;
- }
- }
-
- r = calendar_spec_normalize(c);
- if (r < 0)
- goto fail;
-
- if (!calendar_spec_valid(c)) {
- r = -EINVAL;
- goto fail;
- }
-
- *spec = c;
- return 0;
-
-fail:
- calendar_spec_free(c);
- return r;
-}
-
-static int find_matching_component(const CalendarComponent *c, int *val) {
- const CalendarComponent *n;
- int d = -1;
- bool d_set = false;
- int r;
-
- assert(val);
-
- if (!c)
- return 0;
-
- while (c) {
- n = c->next;
-
- if (c->value >= *val) {
-
- if (!d_set || c->value < d) {
- d = c->value;
- d_set = true;
- }
-
- } else if (c->repeat > 0) {
- int k;
-
- k = c->value + c->repeat * ((*val - c->value + c->repeat -1) / c->repeat);
-
- if (!d_set || k < d) {
- d = k;
- d_set = true;
- }
- }
-
- c = n;
- }
-
- if (!d_set)
- return -ENOENT;
-
- r = *val != d;
- *val = d;
- return r;
-}
-
-static bool tm_out_of_bounds(const struct tm *tm, bool utc) {
- struct tm t;
- assert(tm);
-
- t = *tm;
-
- if (mktime_or_timegm(&t, utc) == (time_t) -1)
- return true;
-
- /* Did any normalization take place? If so, it was out of bounds before */
- return
- t.tm_year != tm->tm_year ||
- t.tm_mon != tm->tm_mon ||
- t.tm_mday != tm->tm_mday ||
- t.tm_hour != tm->tm_hour ||
- t.tm_min != tm->tm_min ||
- t.tm_sec != tm->tm_sec;
-}
-
-static bool matches_weekday(int weekdays_bits, const struct tm *tm, bool utc) {
- struct tm t;
- int k;
-
- if (weekdays_bits < 0 || weekdays_bits >= BITS_WEEKDAYS)
- return true;
-
- t = *tm;
- if (mktime_or_timegm(&t, utc) == (time_t) -1)
- return false;
-
- k = t.tm_wday == 0 ? 6 : t.tm_wday - 1;
- return (weekdays_bits & (1 << k));
-}
-
-static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) {
- struct tm c;
- int tm_usec;
- int r;
-
- assert(spec);
- assert(tm);
-
- c = *tm;
- tm_usec = *usec;
-
- for (;;) {
- /* Normalize the current date */
- (void) mktime_or_timegm(&c, spec->utc);
- c.tm_isdst = spec->dst;
-
- c.tm_year += 1900;
- r = find_matching_component(spec->year, &c.tm_year);
- c.tm_year -= 1900;
-
- if (r > 0) {
- c.tm_mon = 0;
- c.tm_mday = 1;
- c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
- }
- if (r < 0)
- return r;
- if (tm_out_of_bounds(&c, spec->utc))
- return -ENOENT;
-
- c.tm_mon += 1;
- r = find_matching_component(spec->month, &c.tm_mon);
- c.tm_mon -= 1;
-
- if (r > 0) {
- c.tm_mday = 1;
- c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
- }
- if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
- c.tm_year++;
- c.tm_mon = 0;
- c.tm_mday = 1;
- c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
- continue;
- }
-
- r = find_matching_component(spec->day, &c.tm_mday);
- if (r > 0)
- c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
- if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
- c.tm_mon++;
- c.tm_mday = 1;
- c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
- continue;
- }
-
- if (!matches_weekday(spec->weekdays_bits, &c, spec->utc)) {
- c.tm_mday++;
- c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
- continue;
- }
-
- r = find_matching_component(spec->hour, &c.tm_hour);
- if (r > 0)
- c.tm_min = c.tm_sec = tm_usec = 0;
- if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
- c.tm_mday++;
- c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
- continue;
- }
-
- r = find_matching_component(spec->minute, &c.tm_min);
- if (r > 0)
- c.tm_sec = tm_usec = 0;
- if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
- c.tm_hour++;
- c.tm_min = c.tm_sec = tm_usec = 0;
- continue;
- }
-
- c.tm_sec = c.tm_sec * USEC_PER_SEC + tm_usec;
- r = find_matching_component(spec->microsecond, &c.tm_sec);
- tm_usec = c.tm_sec % USEC_PER_SEC;
- c.tm_sec /= USEC_PER_SEC;
-
- if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
- c.tm_min++;
- c.tm_sec = tm_usec = 0;
- continue;
- }
-
- *tm = c;
- *usec = tm_usec;
- return 0;
- }
-}
-
-int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next) {
- struct tm tm;
- time_t t;
- int r;
- usec_t tm_usec;
-
- assert(spec);
- assert(next);
-
- usec++;
- t = (time_t) (usec / USEC_PER_SEC);
- assert_se(localtime_or_gmtime_r(&t, &tm, spec->utc));
- tm_usec = usec % USEC_PER_SEC;
-
- r = find_next(spec, &tm, &tm_usec);
- if (r < 0)
- return r;
-
- t = mktime_or_timegm(&tm, spec->utc);
- if (t == (time_t) -1)
- return -EINVAL;
-
- *next = (usec_t) t * USEC_PER_SEC + tm_usec;
- return 0;
-}
diff --git a/src/basic/calendarspec.h b/src/basic/calendarspec.h
deleted file mode 100644
index c6087228fd..0000000000
--- a/src/basic/calendarspec.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 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/>.
-***/
-
-/* A structure for specifying (possibly repetitive) points in calendar
- * time, a la cron */
-
-#include <stdbool.h>
-
-#include "time-util.h"
-#include "util.h"
-
-typedef struct CalendarComponent {
- int value;
- int repeat;
-
- struct CalendarComponent *next;
-} CalendarComponent;
-
-typedef struct CalendarSpec {
- int weekdays_bits;
- bool utc;
- int dst;
-
- CalendarComponent *year;
- CalendarComponent *month;
- CalendarComponent *day;
-
- CalendarComponent *hour;
- CalendarComponent *minute;
- CalendarComponent *microsecond;
-} CalendarSpec;
-
-void calendar_spec_free(CalendarSpec *c);
-
-int calendar_spec_normalize(CalendarSpec *spec);
-bool calendar_spec_valid(CalendarSpec *spec);
-
-int calendar_spec_to_string(const CalendarSpec *spec, char **p);
-int calendar_spec_from_string(const char *p, CalendarSpec **spec);
-
-int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next);
diff --git a/src/basic/cap-list.c b/src/basic/cap-list.c
deleted file mode 100644
index d68cc78d05..0000000000
--- a/src/basic/cap-list.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 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 <string.h>
-
-#include "cap-list.h"
-#include "macro.h"
-#include "missing.h"
-#include "parse-util.h"
-#include "util.h"
-
-static const struct capability_name* lookup_capability(register const char *str, register GPERF_LEN_TYPE len);
-
-#include "cap-from-name.h"
-#include "cap-to-name.h"
-
-const char *capability_to_name(int id) {
-
- if (id < 0)
- return NULL;
-
- if (id >= (int) ELEMENTSOF(capability_names))
- return NULL;
-
- return capability_names[id];
-}
-
-int capability_from_name(const char *name) {
- const struct capability_name *sc;
- int r, i;
-
- assert(name);
-
- /* Try to parse numeric capability */
- r = safe_atoi(name, &i);
- if (r >= 0 && i >= 0)
- return i;
-
- /* Try to parse string capability */
- sc = lookup_capability(name, strlen(name));
- if (!sc)
- return -EINVAL;
-
- return sc->id;
-}
-
-int capability_list_length(void) {
- return (int) ELEMENTSOF(capability_names);
-}
diff --git a/src/basic/cap-list.h b/src/basic/cap-list.h
deleted file mode 100644
index c1f6b94ad3..0000000000
--- a/src/basic/cap-list.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 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/>.
-***/
-
-const char *capability_to_name(int id);
-int capability_from_name(const char *name);
-int capability_list_length(void);
diff --git a/src/basic/capability-util.c b/src/basic/capability-util.c
deleted file mode 100644
index c3de20a0e8..0000000000
--- a/src/basic/capability-util.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/***
- 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 <grp.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/capability.h>
-#include <sys/prctl.h>
-#include <unistd.h>
-
-#include "alloc-util.h"
-#include "capability-util.h"
-#include "fileio.h"
-#include "log.h"
-#include "macro.h"
-#include "parse-util.h"
-#include "user-util.h"
-#include "util.h"
-
-int have_effective_cap(int value) {
- _cleanup_cap_free_ cap_t cap;
- cap_flag_value_t fv;
-
- cap = cap_get_proc();
- if (!cap)
- return -errno;
-
- if (cap_get_flag(cap, value, CAP_EFFECTIVE, &fv) < 0)
- return -errno;
- else
- return fv == CAP_SET;
-}
-
-unsigned long cap_last_cap(void) {
- static thread_local unsigned long saved;
- static thread_local bool valid = false;
- _cleanup_free_ char *content = NULL;
- unsigned long p = 0;
- int r;
-
- if (valid)
- return saved;
-
- /* available since linux-3.2 */
- r = read_one_line_file("/proc/sys/kernel/cap_last_cap", &content);
- if (r >= 0) {
- r = safe_atolu(content, &p);
- if (r >= 0) {
- saved = p;
- valid = true;
- return p;
- }
- }
-
- /* fall back to syscall-probing for pre linux-3.2 */
- p = (unsigned long) CAP_LAST_CAP;
-
- if (prctl(PR_CAPBSET_READ, p) < 0) {
-
- /* Hmm, look downwards, until we find one that
- * works */
- for (p--; p > 0; p --)
- if (prctl(PR_CAPBSET_READ, p) >= 0)
- break;
-
- } else {
-
- /* Hmm, look upwards, until we find one that doesn't
- * work */
- for (;; p++)
- if (prctl(PR_CAPBSET_READ, p+1) < 0)
- break;
- }
-
- saved = p;
- valid = true;
-
- return p;
-}
-
-int capability_update_inherited_set(cap_t caps, uint64_t set) {
- unsigned long i;
-
- /* Add capabilities in the set to the inherited caps. Do not apply
- * them yet. */
-
- for (i = 0; i < cap_last_cap(); i++) {
-
- if (set & (UINT64_C(1) << i)) {
- cap_value_t v;
-
- v = (cap_value_t) i;
-
- /* Make the capability inheritable. */
- if (cap_set_flag(caps, CAP_INHERITABLE, 1, &v, CAP_SET) < 0)
- return -errno;
- }
- }
-
- return 0;
-}
-
-int capability_ambient_set_apply(uint64_t set, bool also_inherit) {
- unsigned long i;
- _cleanup_cap_free_ cap_t caps = NULL;
-
- /* Add the capabilities to the ambient set. */
-
- if (also_inherit) {
- int r;
- caps = cap_get_proc();
- if (!caps)
- return -errno;
-
- r = capability_update_inherited_set(caps, set);
- if (r < 0)
- return -errno;
-
- if (cap_set_proc(caps) < 0)
- return -errno;
- }
-
- for (i = 0; i < cap_last_cap(); i++) {
-
- if (set & (UINT64_C(1) << i)) {
-
- /* Add the capability to the ambient set. */
- if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0, 0) < 0)
- return -errno;
- }
- }
-
- return 0;
-}
-
-int capability_bounding_set_drop(uint64_t keep, bool right_now) {
- _cleanup_cap_free_ cap_t after_cap = NULL;
- cap_flag_value_t fv;
- unsigned long i;
- int r;
-
- /* If we are run as PID 1 we will lack CAP_SETPCAP by default
- * in the effective set (yes, the kernel drops that when
- * executing init!), so get it back temporarily so that we can
- * call PR_CAPBSET_DROP. */
-
- after_cap = cap_get_proc();
- if (!after_cap)
- return -errno;
-
- if (cap_get_flag(after_cap, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0)
- return -errno;
-
- if (fv != CAP_SET) {
- _cleanup_cap_free_ cap_t temp_cap = NULL;
- static const cap_value_t v = CAP_SETPCAP;
-
- temp_cap = cap_dup(after_cap);
- if (!temp_cap) {
- r = -errno;
- goto finish;
- }
-
- if (cap_set_flag(temp_cap, CAP_EFFECTIVE, 1, &v, CAP_SET) < 0) {
- r = -errno;
- goto finish;
- }
-
- if (cap_set_proc(temp_cap) < 0) {
- r = -errno;
- goto finish;
- }
- }
-
- for (i = 0; i <= cap_last_cap(); i++) {
-
- if (!(keep & (UINT64_C(1) << i))) {
- cap_value_t v;
-
- /* Drop it from the bounding set */
- if (prctl(PR_CAPBSET_DROP, i) < 0) {
- r = -errno;
- goto finish;
- }
- v = (cap_value_t) i;
-
- /* Also drop it from the inheritable set, so
- * that anything we exec() loses the
- * capability for good. */
- if (cap_set_flag(after_cap, CAP_INHERITABLE, 1, &v, CAP_CLEAR) < 0) {
- r = -errno;
- goto finish;
- }
-
- /* If we shall apply this right now drop it
- * also from our own capability sets. */
- if (right_now) {
- if (cap_set_flag(after_cap, CAP_PERMITTED, 1, &v, CAP_CLEAR) < 0 ||
- cap_set_flag(after_cap, CAP_EFFECTIVE, 1, &v, CAP_CLEAR) < 0) {
- r = -errno;
- goto finish;
- }
- }
- }
- }
-
- r = 0;
-
-finish:
- if (cap_set_proc(after_cap) < 0)
- return -errno;
-
- return r;
-}
-
-static int drop_from_file(const char *fn, uint64_t keep) {
- int r, k;
- uint32_t hi, lo;
- uint64_t current, after;
- char *p;
-
- r = read_one_line_file(fn, &p);
- if (r < 0)
- return r;
-
- assert_cc(sizeof(hi) == sizeof(unsigned));
- assert_cc(sizeof(lo) == sizeof(unsigned));
-
- k = sscanf(p, "%u %u", &lo, &hi);
- free(p);
-
- if (k != 2)
- return -EIO;
-
- current = (uint64_t) lo | ((uint64_t) hi << 32ULL);
- after = current & keep;
-
- if (current == after)
- return 0;
-
- lo = (unsigned) (after & 0xFFFFFFFFULL);
- hi = (unsigned) ((after >> 32ULL) & 0xFFFFFFFFULL);
-
- if (asprintf(&p, "%u %u", lo, hi) < 0)
- return -ENOMEM;
-
- r = write_string_file(fn, p, WRITE_STRING_FILE_CREATE);
- free(p);
-
- return r;
-}
-
-int capability_bounding_set_drop_usermode(uint64_t keep) {
- int r;
-
- r = drop_from_file("/proc/sys/kernel/usermodehelper/inheritable", keep);
- if (r < 0)
- return r;
-
- r = drop_from_file("/proc/sys/kernel/usermodehelper/bset", keep);
- if (r < 0)
- return r;
-
- return r;
-}
-
-int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) {
- _cleanup_cap_free_ cap_t d = NULL;
- unsigned i, j = 0;
- int r;
-
- /* Unfortunately we cannot leave privilege dropping to PID 1
- * here, since we want to run as user but want to keep some
- * capabilities. Since file capabilities have been introduced
- * this cannot be done across exec() anymore, unless our
- * binary has the capability configured in the file system,
- * which we want to avoid. */
-
- if (setresgid(gid, gid, gid) < 0)
- return log_error_errno(errno, "Failed to change group ID: %m");
-
- r = maybe_setgroups(0, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to drop auxiliary groups list: %m");
-
- /* Ensure we keep the permitted caps across the setresuid() */
- if (prctl(PR_SET_KEEPCAPS, 1) < 0)
- return log_error_errno(errno, "Failed to enable keep capabilities flag: %m");
-
- r = setresuid(uid, uid, uid);
- if (r < 0)
- return log_error_errno(errno, "Failed to change user ID: %m");
-
- if (prctl(PR_SET_KEEPCAPS, 0) < 0)
- return log_error_errno(errno, "Failed to disable keep capabilities flag: %m");
-
- /* Drop all caps from the bounding set, except the ones we want */
- r = capability_bounding_set_drop(keep_capabilities, true);
- if (r < 0)
- return log_error_errno(r, "Failed to drop capabilities: %m");
-
- /* Now upgrade the permitted caps we still kept to effective caps */
- d = cap_init();
- if (!d)
- return log_oom();
-
- if (keep_capabilities) {
- cap_value_t bits[u64log2(keep_capabilities) + 1];
-
- for (i = 0; i < ELEMENTSOF(bits); i++)
- if (keep_capabilities & (1ULL << i))
- bits[j++] = i;
-
- /* use enough bits */
- assert(i == 64 || (keep_capabilities >> i) == 0);
- /* don't use too many bits */
- assert(keep_capabilities & (1ULL << (i - 1)));
-
- if (cap_set_flag(d, CAP_EFFECTIVE, j, bits, CAP_SET) < 0 ||
- cap_set_flag(d, CAP_PERMITTED, j, bits, CAP_SET) < 0)
- return log_error_errno(errno, "Failed to enable capabilities bits: %m");
-
- if (cap_set_proc(d) < 0)
- return log_error_errno(errno, "Failed to increase capabilities: %m");
- }
-
- return 0;
-}
-
-int drop_capability(cap_value_t cv) {
- _cleanup_cap_free_ cap_t tmp_cap = NULL;
-
- tmp_cap = cap_get_proc();
- if (!tmp_cap)
- return -errno;
-
- if ((cap_set_flag(tmp_cap, CAP_INHERITABLE, 1, &cv, CAP_CLEAR) < 0) ||
- (cap_set_flag(tmp_cap, CAP_PERMITTED, 1, &cv, CAP_CLEAR) < 0) ||
- (cap_set_flag(tmp_cap, CAP_EFFECTIVE, 1, &cv, CAP_CLEAR) < 0))
- return -errno;
-
- if (cap_set_proc(tmp_cap) < 0)
- return -errno;
-
- return 0;
-}
diff --git a/src/basic/capability-util.h b/src/basic/capability-util.h
deleted file mode 100644
index 35a896e229..0000000000
--- a/src/basic/capability-util.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#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 <stdint.h>
-#include <sys/capability.h>
-#include <sys/types.h>
-
-#include "macro.h"
-#include "util.h"
-
-#define CAP_ALL (uint64_t) -1
-
-unsigned long cap_last_cap(void);
-int have_effective_cap(int value);
-int capability_bounding_set_drop(uint64_t keep, bool right_now);
-int capability_bounding_set_drop_usermode(uint64_t keep);
-
-int capability_ambient_set_apply(uint64_t set, bool also_inherit);
-int capability_update_inherited_set(cap_t caps, uint64_t ambient_set);
-
-int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities);
-
-int drop_capability(cap_value_t cv);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(cap_t, cap_free);
-#define _cleanup_cap_free_ _cleanup_(cap_freep)
-
-static inline void cap_free_charpp(char **p) {
- if (*p)
- cap_free(*p);
-}
-#define _cleanup_cap_free_charp_ _cleanup_(cap_free_charpp)
-
-static inline bool cap_test_all(uint64_t caps) {
- uint64_t m;
- m = (UINT64_C(1) << (cap_last_cap() + 1)) - 1;
- return (caps & m) == m;
-}
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
deleted file mode 100644
index 134e6e3664..0000000000
--- a/src/basic/cgroup-util.c
+++ /dev/null
@@ -1,2541 +0,0 @@
-/***
- 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 <dirent.h>
-#include <errno.h>
-#include <ftw.h>
-#include <limits.h>
-#include <signal.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <sys/types.h>
-#include <sys/xattr.h>
-#include <unistd.h>
-
-#include "alloc-util.h"
-#include "cgroup-util.h"
-#include "def.h"
-#include "dirent-util.h"
-#include "extract-word.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "formats-util.h"
-#include "fs-util.h"
-#include "log.h"
-#include "login-util.h"
-#include "macro.h"
-#include "missing.h"
-#include "mkdir.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "proc-cmdline.h"
-#include "process-util.h"
-#include "set.h"
-#include "special.h"
-#include "stat-util.h"
-#include "stdio-util.h"
-#include "string-table.h"
-#include "string-util.h"
-#include "unit-name.h"
-#include "user-util.h"
-
-int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
- _cleanup_free_ char *fs = NULL;
- FILE *f;
- int r;
-
- assert(_f);
-
- r = cg_get_path(controller, path, "cgroup.procs", &fs);
- if (r < 0)
- return r;
-
- f = fopen(fs, "re");
- 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. */
-
- assert(f);
- assert(_pid);
-
- errno = 0;
- if (fscanf(f, "%lu", &ul) != 1) {
-
- if (feof(f))
- return 0;
-
- return errno > 0 ? -errno : -EIO;
- }
-
- if (ul <= 0)
- return -EIO;
-
- *_pid = (pid_t) ul;
- return 1;
-}
-
-int cg_read_event(const char *controller, const char *path, const char *event,
- char **val)
-{
- _cleanup_free_ char *events = NULL, *content = NULL;
- char *p, *line;
- int r;
-
- r = cg_get_path(controller, path, "cgroup.events", &events);
- if (r < 0)
- return r;
-
- r = read_full_file(events, &content, NULL);
- if (r < 0)
- return r;
-
- p = content;
- while ((line = strsep(&p, "\n"))) {
- char *key;
-
- key = strsep(&line, " ");
- if (!key || !line)
- return -EINVAL;
-
- if (strcmp(key, event))
- continue;
-
- *val = strdup(line);
- return 0;
- }
-
- return -ENOENT;
-}
-
-bool cg_ns_supported(void) {
- static thread_local int enabled = -1;
-
- if (enabled >= 0)
- return enabled;
-
- if (access("/proc/self/ns/cgroup", F_OK) == 0)
- enabled = 1;
- else
- enabled = 0;
-
- return enabled;
-}
-
-int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) {
- _cleanup_free_ char *fs = NULL;
- int r;
- DIR *d;
-
- assert(_d);
-
- /* This is not recursive! */
-
- r = cg_get_path(controller, path, NULL, &fs);
- if (r < 0)
- return r;
-
- d = opendir(fs);
- if (!d)
- return -errno;
-
- *_d = d;
- return 0;
-}
-
-int cg_read_subgroup(DIR *d, char **fn) {
- struct dirent *de;
-
- assert(d);
- assert(fn);
-
- FOREACH_DIRENT_ALL(de, d, return -errno) {
- char *b;
-
- if (de->d_type != DT_DIR)
- continue;
-
- if (streq(de->d_name, ".") ||
- streq(de->d_name, ".."))
- continue;
-
- b = strdup(de->d_name);
- if (!b)
- return -ENOMEM;
-
- *fn = b;
- return 1;
- }
-
- return 0;
-}
-
-int cg_rmdir(const char *controller, const char *path) {
- _cleanup_free_ char *p = NULL;
- int r;
-
- r = cg_get_path(controller, path, NULL, &p);
- if (r < 0)
- return r;
-
- r = rmdir(p);
- if (r < 0 && errno != ENOENT)
- return -errno;
-
- return 0;
-}
-
-int cg_kill(
- const char *controller,
- const char *path,
- int sig,
- CGroupFlags flags,
- Set *s,
- cg_kill_log_func_t log_kill,
- void *userdata) {
-
- _cleanup_set_free_ Set *allocated_set = NULL;
- bool done = false;
- int r, ret = 0;
- pid_t my_pid;
-
- assert(sig >= 0);
-
- /* Don't send SIGCONT twice. Also, SIGKILL always works even when process is suspended, hence don't send
- * SIGCONT on SIGKILL. */
- if (IN_SET(sig, SIGCONT, SIGKILL))
- flags &= ~CGROUP_SIGCONT;
-
- /* 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) {
- s = allocated_set = set_new(NULL);
- if (!s)
- return -ENOMEM;
- }
-
- my_pid = getpid();
-
- do {
- _cleanup_fclose_ FILE *f = NULL;
- pid_t pid = 0;
- done = true;
-
- r = cg_enumerate_processes(controller, path, &f);
- if (r < 0) {
- if (ret >= 0 && r != -ENOENT)
- return r;
-
- return ret;
- }
-
- while ((r = cg_read_pid(f, &pid)) > 0) {
-
- if ((flags & CGROUP_IGNORE_SELF) && pid == my_pid)
- continue;
-
- if (set_get(s, PID_TO_PTR(pid)) == PID_TO_PTR(pid))
- continue;
-
- if (log_kill)
- log_kill(pid, sig, userdata);
-
- /* If we haven't killed this process yet, kill
- * it */
- if (kill(pid, sig) < 0) {
- if (ret >= 0 && errno != ESRCH)
- ret = -errno;
- } else {
- if (flags & CGROUP_SIGCONT)
- (void) kill(pid, SIGCONT);
-
- if (ret == 0)
- ret = 1;
- }
-
- done = false;
-
- r = set_put(s, PID_TO_PTR(pid));
- if (r < 0) {
- if (ret >= 0)
- return r;
-
- return ret;
- }
- }
-
- if (r < 0) {
- if (ret >= 0)
- return r;
-
- return ret;
- }
-
- /* 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);
-
- return ret;
-}
-
-int cg_kill_recursive(
- const char *controller,
- const char *path,
- int sig,
- CGroupFlags flags,
- Set *s,
- cg_kill_log_func_t log_kill,
- void *userdata) {
-
- _cleanup_set_free_ Set *allocated_set = NULL;
- _cleanup_closedir_ DIR *d = NULL;
- int r, ret;
- char *fn;
-
- assert(path);
- assert(sig >= 0);
-
- if (!s) {
- s = allocated_set = set_new(NULL);
- if (!s)
- return -ENOMEM;
- }
-
- ret = cg_kill(controller, path, sig, flags, s, log_kill, userdata);
-
- r = cg_enumerate_subgroups(controller, path, &d);
- if (r < 0) {
- if (ret >= 0 && r != -ENOENT)
- return r;
-
- return ret;
- }
-
- while ((r = cg_read_subgroup(d, &fn)) > 0) {
- _cleanup_free_ char *p = NULL;
-
- p = strjoin(path, "/", fn, NULL);
- free(fn);
- if (!p)
- return -ENOMEM;
-
- r = cg_kill_recursive(controller, p, sig, flags, s, log_kill, userdata);
- if (r != 0 && ret >= 0)
- ret = r;
- }
- if (ret >= 0 && r < 0)
- ret = r;
-
- if (flags & CGROUP_REMOVE) {
- r = cg_rmdir(controller, path);
- if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
- return r;
- }
-
- return ret;
-}
-
-int cg_migrate(
- const char *cfrom,
- const char *pfrom,
- const char *cto,
- const char *pto,
- CGroupFlags flags) {
-
- bool done = false;
- _cleanup_set_free_ Set *s = NULL;
- int r, ret = 0;
- pid_t my_pid;
-
- assert(cfrom);
- assert(pfrom);
- assert(cto);
- assert(pto);
-
- s = set_new(NULL);
- if (!s)
- return -ENOMEM;
-
- my_pid = getpid();
-
- do {
- _cleanup_fclose_ FILE *f = NULL;
- pid_t pid = 0;
- done = true;
-
- r = cg_enumerate_processes(cfrom, pfrom, &f);
- if (r < 0) {
- if (ret >= 0 && r != -ENOENT)
- return r;
-
- return ret;
- }
-
- 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 ((flags & CGROUP_IGNORE_SELF) && pid == my_pid)
- continue;
-
- if (set_get(s, PID_TO_PTR(pid)) == PID_TO_PTR(pid))
- continue;
-
- /* Ignore kernel threads. Since they can only
- * exist in the root cgroup, we only check for
- * them there. */
- if (cfrom &&
- (isempty(pfrom) || path_equal(pfrom, "/")) &&
- is_kernel_thread(pid) > 0)
- continue;
-
- r = cg_attach(cto, pto, pid);
- if (r < 0) {
- if (ret >= 0 && r != -ESRCH)
- ret = r;
- } else if (ret == 0)
- ret = 1;
-
- done = false;
-
- r = set_put(s, PID_TO_PTR(pid));
- if (r < 0) {
- if (ret >= 0)
- return r;
-
- return ret;
- }
- }
-
- if (r < 0) {
- if (ret >= 0)
- return r;
-
- return ret;
- }
- } while (!done);
-
- return ret;
-}
-
-int cg_migrate_recursive(
- const char *cfrom,
- const char *pfrom,
- const char *cto,
- const char *pto,
- CGroupFlags flags) {
-
- _cleanup_closedir_ DIR *d = NULL;
- int r, ret = 0;
- char *fn;
-
- assert(cfrom);
- assert(pfrom);
- assert(cto);
- assert(pto);
-
- ret = cg_migrate(cfrom, pfrom, cto, pto, flags);
-
- r = cg_enumerate_subgroups(cfrom, pfrom, &d);
- if (r < 0) {
- if (ret >= 0 && r != -ENOENT)
- return r;
-
- return ret;
- }
-
- while ((r = cg_read_subgroup(d, &fn)) > 0) {
- _cleanup_free_ char *p = NULL;
-
- p = strjoin(pfrom, "/", fn, NULL);
- free(fn);
- if (!p)
- return -ENOMEM;
-
- r = cg_migrate_recursive(cfrom, p, cto, pto, flags);
- if (r != 0 && ret >= 0)
- ret = r;
- }
-
- if (r < 0 && ret >= 0)
- ret = r;
-
- if (flags & CGROUP_REMOVE) {
- r = cg_rmdir(cfrom, pfrom);
- if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
- return r;
- }
-
- return ret;
-}
-
-int cg_migrate_recursive_fallback(
- const char *cfrom,
- const char *pfrom,
- const char *cto,
- const char *pto,
- CGroupFlags flags) {
-
- int r;
-
- assert(cfrom);
- assert(pfrom);
- assert(cto);
- assert(pto);
-
- r = cg_migrate_recursive(cfrom, pfrom, cto, pto, flags);
- if (r < 0) {
- char prefix[strlen(pto) + 1];
-
- /* This didn't work? Then let's try all prefixes of the destination */
-
- PATH_FOREACH_PREFIX(prefix, pto) {
- int q;
-
- q = cg_migrate_recursive(cfrom, pfrom, cto, prefix, flags);
- if (q >= 0)
- return q;
- }
- }
-
- return r;
-}
-
-static const char *controller_to_dirname(const char *controller) {
- const char *e;
-
- assert(controller);
-
- /* Converts a controller name to the directory name below
- * /sys/fs/cgroup/ we want to mount it to. Effectively, this
- * just cuts off the name= prefixed used for named
- * hierarchies, if it is specified. */
-
- e = startswith(controller, "name=");
- if (e)
- return e;
-
- return controller;
-}
-
-static int join_path_legacy(const char *controller, const char *path, const char *suffix, char **fs) {
- const char *dn;
- char *t = NULL;
-
- assert(fs);
- assert(controller);
-
- dn = controller_to_dirname(controller);
-
- if (isempty(path) && isempty(suffix))
- t = strappend("/sys/fs/cgroup/", dn);
- else if (isempty(path))
- t = strjoin("/sys/fs/cgroup/", dn, "/", suffix, NULL);
- else if (isempty(suffix))
- t = strjoin("/sys/fs/cgroup/", dn, "/", path, NULL);
- else
- t = strjoin("/sys/fs/cgroup/", dn, "/", path, "/", suffix, NULL);
- if (!t)
- return -ENOMEM;
-
- *fs = t;
- return 0;
-}
-
-static int join_path_unified(const char *path, const char *suffix, char **fs) {
- char *t;
-
- assert(fs);
-
- if (isempty(path) && isempty(suffix))
- t = strdup("/sys/fs/cgroup");
- else if (isempty(path))
- t = strappend("/sys/fs/cgroup/", suffix);
- else if (isempty(suffix))
- t = strappend("/sys/fs/cgroup/", path);
- else
- t = strjoin("/sys/fs/cgroup/", path, "/", suffix, NULL);
- if (!t)
- return -ENOMEM;
-
- *fs = t;
- return 0;
-}
-
-int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
- int unified, r;
-
- assert(fs);
-
- if (!controller) {
- char *t;
-
- /* If no controller is specified, we return the path
- * *below* the controllers, without any prefix. */
-
- if (!path && !suffix)
- return -EINVAL;
-
- if (!suffix)
- t = strdup(path);
- else if (!path)
- t = strdup(suffix);
- else
- t = strjoin(path, "/", suffix, NULL);
- if (!t)
- return -ENOMEM;
-
- *fs = path_kill_slashes(t);
- return 0;
- }
-
- if (!cg_controller_is_valid(controller))
- return -EINVAL;
-
- unified = cg_all_unified();
- if (unified < 0)
- return unified;
-
- if (unified > 0)
- r = join_path_unified(path, suffix, fs);
- else
- r = join_path_legacy(controller, path, suffix, fs);
- if (r < 0)
- return r;
-
- path_kill_slashes(*fs);
- return 0;
-}
-
-static int controller_is_accessible(const char *controller) {
- int unified;
-
- assert(controller);
-
- /* Checks whether a specific controller is accessible,
- * i.e. its hierarchy mounted. In the unified hierarchy all
- * controllers are considered accessible, except for the named
- * hierarchies */
-
- if (!cg_controller_is_valid(controller))
- return -EINVAL;
-
- unified = cg_all_unified();
- if (unified < 0)
- return unified;
- if (unified > 0) {
- /* We don't support named hierarchies if we are using
- * the unified hierarchy. */
-
- if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
- return 0;
-
- if (startswith(controller, "name="))
- return -EOPNOTSUPP;
-
- } else {
- const char *cc, *dn;
-
- dn = controller_to_dirname(controller);
- cc = strjoina("/sys/fs/cgroup/", dn);
-
- if (laccess(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) {
- int r;
-
- assert(controller);
- assert(fs);
-
- /* Check if the specified controller is actually accessible */
- r = controller_is_accessible(controller);
- if (r < 0)
- return r;
-
- return cg_get_path(controller, path, suffix, fs);
-}
-
-static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
- assert(path);
- assert(sb);
- assert(ftwbuf);
-
- if (typeflag != FTW_DP)
- return 0;
-
- if (ftwbuf->level < 1)
- return 0;
-
- (void) rmdir(path);
- return 0;
-}
-
-int cg_trim(const char *controller, const char *path, bool delete_root) {
- _cleanup_free_ char *fs = NULL;
- int r = 0;
-
- 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) {
- if (errno == ENOENT)
- r = 0;
- else if (errno > 0)
- r = -errno;
- else
- r = -EIO;
- }
-
- if (delete_root) {
- if (rmdir(fs) < 0 && errno != ENOENT)
- return -errno;
- }
-
- return r;
-}
-
-int cg_create(const char *controller, const char *path) {
- _cleanup_free_ char *fs = NULL;
- int r;
-
- r = cg_get_path_and_check(controller, path, NULL, &fs);
- if (r < 0)
- return r;
-
- r = mkdir_parents(fs, 0755);
- if (r < 0)
- return r;
-
- if (mkdir(fs, 0755) < 0) {
-
- if (errno == EEXIST)
- return 0;
-
- return -errno;
- }
-
- return 1;
-}
-
-int cg_create_and_attach(const char *controller, const char *path, pid_t pid) {
- int r, q;
-
- assert(pid >= 0);
-
- r = cg_create(controller, path);
- if (r < 0)
- return r;
-
- q = cg_attach(controller, path, pid);
- if (q < 0)
- return q;
-
- /* This does not remove the cgroup on failure */
- return r;
-}
-
-int cg_attach(const char *controller, const char *path, pid_t pid) {
- _cleanup_free_ char *fs = NULL;
- char c[DECIMAL_STR_MAX(pid_t) + 2];
- int r;
-
- assert(path);
- assert(pid >= 0);
-
- r = cg_get_path_and_check(controller, path, "cgroup.procs", &fs);
- if (r < 0)
- return r;
-
- if (pid == 0)
- pid = getpid();
-
- xsprintf(c, PID_FMT "\n", pid);
-
- return write_string_file(fs, c, 0);
-}
-
-int cg_attach_fallback(const char *controller, const char *path, pid_t pid) {
- int r;
-
- assert(controller);
- assert(path);
- assert(pid >= 0);
-
- r = cg_attach(controller, path, pid);
- if (r < 0) {
- char prefix[strlen(path) + 1];
-
- /* This didn't work? Then let's try all prefixes of
- * the destination */
-
- PATH_FOREACH_PREFIX(prefix, path) {
- int q;
-
- q = cg_attach(controller, prefix, pid);
- if (q >= 0)
- return q;
- }
- }
-
- return r;
-}
-
-int cg_set_group_access(
- const char *controller,
- const char *path,
- mode_t mode,
- uid_t uid,
- gid_t gid) {
-
- _cleanup_free_ char *fs = NULL;
- int r;
-
- if (mode == MODE_INVALID && uid == UID_INVALID && gid == GID_INVALID)
- return 0;
-
- if (mode != MODE_INVALID)
- mode &= 0777;
-
- r = cg_get_path(controller, path, NULL, &fs);
- if (r < 0)
- return r;
-
- return chmod_and_chown(fs, mode, uid, gid);
-}
-
-int cg_set_task_access(
- const char *controller,
- const char *path,
- mode_t mode,
- uid_t uid,
- gid_t gid) {
-
- _cleanup_free_ char *fs = NULL, *procs = NULL;
- int r, unified;
-
- assert(path);
-
- if (mode == MODE_INVALID && uid == UID_INVALID && gid == GID_INVALID)
- return 0;
-
- if (mode != MODE_INVALID)
- mode &= 0666;
-
- r = cg_get_path(controller, path, "cgroup.procs", &fs);
- if (r < 0)
- return r;
-
- r = chmod_and_chown(fs, mode, uid, gid);
- if (r < 0)
- return r;
-
- unified = cg_unified(controller);
- if (unified < 0)
- return unified;
- if (unified)
- return 0;
-
- /* Compatibility, Always keep values for "tasks" in sync with
- * "cgroup.procs" */
- if (cg_get_path(controller, path, "tasks", &procs) >= 0)
- (void) chmod_and_chown(procs, mode, uid, gid);
-
- return 0;
-}
-
-int cg_set_xattr(const char *controller, const char *path, const char *name, const void *value, size_t size, int flags) {
- _cleanup_free_ char *fs = NULL;
- int r;
-
- assert(path);
- assert(name);
- assert(value || size <= 0);
-
- r = cg_get_path(controller, path, NULL, &fs);
- if (r < 0)
- return r;
-
- if (setxattr(fs, name, value, size, flags) < 0)
- return -errno;
-
- return 0;
-}
-
-int cg_get_xattr(const char *controller, const char *path, const char *name, void *value, size_t size) {
- _cleanup_free_ char *fs = NULL;
- ssize_t n;
- int r;
-
- assert(path);
- assert(name);
-
- r = cg_get_path(controller, path, NULL, &fs);
- if (r < 0)
- return r;
-
- n = getxattr(fs, name, value, size);
- if (n < 0)
- return -errno;
-
- return (int) n;
-}
-
-int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
- _cleanup_fclose_ FILE *f = NULL;
- char line[LINE_MAX];
- const char *fs;
- size_t cs = 0;
- int unified;
-
- assert(path);
- assert(pid >= 0);
-
- if (controller) {
- if (!cg_controller_is_valid(controller))
- return -EINVAL;
- } else
- controller = SYSTEMD_CGROUP_CONTROLLER;
-
- unified = cg_unified(controller);
- if (unified < 0)
- return unified;
- if (unified == 0)
- cs = strlen(controller);
-
- fs = procfs_file_alloca(pid, "cgroup");
- f = fopen(fs, "re");
- if (!f)
- return errno == ENOENT ? -ESRCH : -errno;
-
- FOREACH_LINE(line, f, return -errno) {
- char *e, *p;
-
- truncate_nl(line);
-
- if (unified) {
- e = startswith(line, "0:");
- if (!e)
- continue;
-
- e = strchr(e, ':');
- if (!e)
- continue;
- } else {
- char *l;
- size_t k;
- const char *word, *state;
- bool found = false;
-
- l = strchr(line, ':');
- if (!l)
- continue;
-
- l++;
- e = strchr(l, ':');
- if (!e)
- continue;
-
- *e = 0;
- FOREACH_WORD_SEPARATOR(word, k, l, ",", state) {
- if (k == cs && memcmp(word, controller, cs) == 0) {
- found = true;
- break;
- }
- }
-
- if (!found)
- continue;
- }
-
- p = strdup(e + 1);
- if (!p)
- return -ENOMEM;
-
- *path = p;
- return 0;
- }
-
- return -ENODATA;
-}
-
-int cg_install_release_agent(const char *controller, const char *agent) {
- _cleanup_free_ char *fs = NULL, *contents = NULL;
- const char *sc;
- int r, unified;
-
- assert(agent);
-
- unified = cg_unified(controller);
- if (unified < 0)
- return unified;
- if (unified) /* doesn't apply to unified hierarchy */
- return -EOPNOTSUPP;
-
- r = cg_get_path(controller, NULL, "release_agent", &fs);
- if (r < 0)
- return r;
-
- r = read_one_line_file(fs, &contents);
- if (r < 0)
- return r;
-
- sc = strstrip(contents);
- if (isempty(sc)) {
- r = write_string_file(fs, agent, 0);
- if (r < 0)
- return r;
- } else if (!path_equal(sc, agent))
- return -EEXIST;
-
- fs = mfree(fs);
- r = cg_get_path(controller, NULL, "notify_on_release", &fs);
- if (r < 0)
- return r;
-
- contents = mfree(contents);
- r = read_one_line_file(fs, &contents);
- if (r < 0)
- return r;
-
- sc = strstrip(contents);
- if (streq(sc, "0")) {
- r = write_string_file(fs, "1", 0);
- if (r < 0)
- return r;
-
- return 1;
- }
-
- if (!streq(sc, "1"))
- return -EIO;
-
- return 0;
-}
-
-int cg_uninstall_release_agent(const char *controller) {
- _cleanup_free_ char *fs = NULL;
- int r, unified;
-
- unified = cg_unified(controller);
- if (unified < 0)
- return unified;
- if (unified) /* Doesn't apply to unified hierarchy */
- return -EOPNOTSUPP;
-
- r = cg_get_path(controller, NULL, "notify_on_release", &fs);
- if (r < 0)
- return r;
-
- r = write_string_file(fs, "0", 0);
- if (r < 0)
- return r;
-
- fs = mfree(fs);
-
- r = cg_get_path(controller, NULL, "release_agent", &fs);
- if (r < 0)
- return r;
-
- r = write_string_file(fs, "", 0);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-int cg_is_empty(const char *controller, const char *path) {
- _cleanup_fclose_ FILE *f = NULL;
- pid_t pid;
- int r;
-
- assert(path);
-
- r = cg_enumerate_processes(controller, path, &f);
- if (r == -ENOENT)
- return 1;
- if (r < 0)
- return r;
-
- r = cg_read_pid(f, &pid);
- if (r < 0)
- return r;
-
- return r == 0;
-}
-
-int cg_is_empty_recursive(const char *controller, const char *path) {
- int unified, r;
-
- assert(path);
-
- /* The root cgroup is always populated */
- if (controller && (isempty(path) || path_equal(path, "/")))
- return false;
-
- unified = cg_unified(controller);
- if (unified < 0)
- return unified;
-
- if (unified > 0) {
- _cleanup_free_ char *t = NULL;
-
- /* On the unified hierarchy we can check empty state
- * via the "populated" attribute of "cgroup.events". */
-
- r = cg_read_event(controller, path, "populated", &t);
- if (r < 0)
- return r;
-
- return streq(t, "0");
- } else {
- _cleanup_closedir_ DIR *d = NULL;
- char *fn;
-
- r = cg_is_empty(controller, path);
- if (r <= 0)
- return r;
-
- r = cg_enumerate_subgroups(controller, path, &d);
- if (r == -ENOENT)
- return 1;
- if (r < 0)
- return r;
-
- while ((r = cg_read_subgroup(d, &fn)) > 0) {
- _cleanup_free_ char *p = NULL;
-
- p = strjoin(path, "/", fn, NULL);
- free(fn);
- if (!p)
- return -ENOMEM;
-
- r = cg_is_empty_recursive(controller, p);
- if (r <= 0)
- return r;
- }
- if (r < 0)
- return r;
-
- return true;
- }
-}
-
-int cg_split_spec(const char *spec, char **controller, char **path) {
- char *t = NULL, *u = NULL;
- const char *e;
-
- assert(spec);
-
- if (*spec == '/') {
- if (!path_is_safe(spec))
- return -EINVAL;
-
- if (path) {
- t = strdup(spec);
- if (!t)
- return -ENOMEM;
-
- *path = path_kill_slashes(t);
- }
-
- if (controller)
- *controller = NULL;
-
- return 0;
- }
-
- e = strchr(spec, ':');
- if (!e) {
- if (!cg_controller_is_valid(spec))
- return -EINVAL;
-
- if (controller) {
- t = strdup(spec);
- if (!t)
- return -ENOMEM;
-
- *controller = t;
- }
-
- if (path)
- *path = NULL;
-
- return 0;
- }
-
- t = strndup(spec, e-spec);
- if (!t)
- return -ENOMEM;
- if (!cg_controller_is_valid(t)) {
- free(t);
- return -EINVAL;
- }
-
- if (isempty(e+1))
- u = NULL;
- else {
- u = strdup(e+1);
- if (!u) {
- free(t);
- return -ENOMEM;
- }
-
- if (!path_is_safe(u) ||
- !path_is_absolute(u)) {
- free(t);
- free(u);
- return -EINVAL;
- }
-
- path_kill_slashes(u);
- }
-
- if (controller)
- *controller = t;
- else
- free(t);
-
- if (path)
- *path = u;
- else
- free(u);
-
- return 0;
-}
-
-int cg_mangle_path(const char *path, char **result) {
- _cleanup_free_ char *c = NULL, *p = NULL;
- char *t;
- int r;
-
- assert(path);
- assert(result);
-
- /* First, check if it already is a filesystem path */
- if (path_startswith(path, "/sys/fs/cgroup")) {
-
- t = strdup(path);
- if (!t)
- return -ENOMEM;
-
- *result = path_kill_slashes(t);
- return 0;
- }
-
- /* Otherwise, treat it as cg spec */
- r = cg_split_spec(path, &c, &p);
- if (r < 0)
- return r;
-
- return cg_get_path(c ?: SYSTEMD_CGROUP_CONTROLLER, p ?: "/", NULL, result);
-}
-
-int cg_get_root_path(char **path) {
- char *p, *e;
- int r;
-
- assert(path);
-
- r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p);
- if (r < 0)
- return r;
-
- e = endswith(p, "/" SPECIAL_INIT_SCOPE);
- if (!e)
- e = endswith(p, "/" SPECIAL_SYSTEM_SLICE); /* legacy */
- if (!e)
- e = endswith(p, "/system"); /* even more legacy */
- if (e)
- *e = 0;
-
- *path = p;
- return 0;
-}
-
-int cg_shift_path(const char *cgroup, const char *root, const char **shifted) {
- _cleanup_free_ char *rt = NULL;
- char *p;
- int r;
-
- assert(cgroup);
- assert(shifted);
-
- if (!root) {
- /* If the root was specified let's use that, otherwise
- * let's determine it from PID 1 */
-
- r = cg_get_root_path(&rt);
- if (r < 0)
- return r;
-
- root = rt;
- }
-
- p = path_startswith(cgroup, root);
- if (p && p > cgroup)
- *shifted = p - 1;
- else
- *shifted = cgroup;
-
- return 0;
-}
-
-int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
- _cleanup_free_ char *raw = NULL;
- const char *c;
- int r;
-
- assert(pid >= 0);
- assert(cgroup);
-
- r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &raw);
- if (r < 0)
- return r;
-
- r = cg_shift_path(raw, root, &c);
- if (r < 0)
- return r;
-
- if (c == raw) {
- *cgroup = raw;
- raw = NULL;
- } else {
- char *n;
-
- n = strdup(c);
- if (!n)
- return -ENOMEM;
-
- *cgroup = n;
- }
-
- return 0;
-}
-
-int cg_path_decode_unit(const char *cgroup, char **unit) {
- char *c, *s;
- size_t n;
-
- assert(cgroup);
- assert(unit);
-
- n = strcspn(cgroup, "/");
- if (n < 3)
- return -ENXIO;
-
- c = strndupa(cgroup, n);
- c = cg_unescape(c);
-
- if (!unit_name_is_valid(c, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
- return -ENXIO;
-
- s = strdup(c);
- if (!s)
- return -ENOMEM;
-
- *unit = s;
- return 0;
-}
-
-static bool valid_slice_name(const char *p, size_t n) {
-
- if (!p)
- return false;
-
- if (n < strlen("x.slice"))
- return false;
-
- if (memcmp(p + n - 6, ".slice", 6) == 0) {
- char buf[n+1], *c;
-
- memcpy(buf, p, n);
- buf[n] = 0;
-
- c = cg_unescape(buf);
-
- return unit_name_is_valid(c, UNIT_NAME_PLAIN);
- }
-
- return false;
-}
-
-static const char *skip_slices(const char *p) {
- assert(p);
-
- /* Skips over all slice assignments */
-
- for (;;) {
- size_t n;
-
- p += strspn(p, "/");
-
- n = strcspn(p, "/");
- if (!valid_slice_name(p, n))
- return p;
-
- p += n;
- }
-}
-
-int cg_path_get_unit(const char *path, char **ret) {
- const char *e;
- char *unit;
- int r;
-
- assert(path);
- assert(ret);
-
- e = skip_slices(path);
-
- r = cg_path_decode_unit(e, &unit);
- if (r < 0)
- return r;
-
- /* We skipped over the slices, don't accept any now */
- if (endswith(unit, ".slice")) {
- free(unit);
- return -ENXIO;
- }
-
- *ret = unit;
- return 0;
-}
-
-int cg_pid_get_unit(pid_t pid, char **unit) {
- _cleanup_free_ char *cgroup = NULL;
- int r;
-
- assert(unit);
-
- r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
- if (r < 0)
- return r;
-
- return cg_path_get_unit(cgroup, unit);
-}
-
-/**
- * Skip session-*.scope, but require it to be there.
- */
-static const char *skip_session(const char *p) {
- size_t n;
-
- if (isempty(p))
- return NULL;
-
- p += strspn(p, "/");
-
- n = strcspn(p, "/");
- if (n < strlen("session-x.scope"))
- return NULL;
-
- if (memcmp(p, "session-", 8) == 0 && memcmp(p + n - 6, ".scope", 6) == 0) {
- char buf[n - 8 - 6 + 1];
-
- memcpy(buf, p + 8, n - 8 - 6);
- buf[n - 8 - 6] = 0;
-
- /* Note that session scopes never need unescaping,
- * since they cannot conflict with the kernel's own
- * names, hence we don't need to call cg_unescape()
- * here. */
-
- if (!session_id_valid(buf))
- return false;
-
- p += n;
- p += strspn(p, "/");
- return p;
- }
-
- return NULL;
-}
-
-/**
- * Skip user@*.service, but require it to be there.
- */
-static const char *skip_user_manager(const char *p) {
- size_t n;
-
- if (isempty(p))
- return NULL;
-
- p += strspn(p, "/");
-
- n = strcspn(p, "/");
- if (n < strlen("user@x.service"))
- return NULL;
-
- if (memcmp(p, "user@", 5) == 0 && memcmp(p + n - 8, ".service", 8) == 0) {
- char buf[n - 5 - 8 + 1];
-
- memcpy(buf, p + 5, n - 5 - 8);
- buf[n - 5 - 8] = 0;
-
- /* Note that user manager services never need unescaping,
- * since they cannot conflict with the kernel's own
- * names, hence we don't need to call cg_unescape()
- * here. */
-
- if (parse_uid(buf, NULL) < 0)
- return NULL;
-
- p += n;
- p += strspn(p, "/");
-
- return p;
- }
-
- return NULL;
-}
-
-static const char *skip_user_prefix(const char *path) {
- const char *e, *t;
-
- assert(path);
-
- /* Skip slices, if there are any */
- e = skip_slices(path);
-
- /* Skip the user manager, if it's in the path now... */
- t = skip_user_manager(e);
- if (t)
- return t;
-
- /* Alternatively skip the user session if it is in the path... */
- return skip_session(e);
-}
-
-int cg_path_get_user_unit(const char *path, char **ret) {
- const char *t;
-
- assert(path);
- assert(ret);
-
- t = skip_user_prefix(path);
- if (!t)
- return -ENXIO;
-
- /* And from here on it looks pretty much the same as for a
- * system unit, hence let's use the same parser from here
- * on. */
- return cg_path_get_unit(t, ret);
-}
-
-int cg_pid_get_user_unit(pid_t pid, char **unit) {
- _cleanup_free_ char *cgroup = NULL;
- int r;
-
- assert(unit);
-
- r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
- if (r < 0)
- return r;
-
- return cg_path_get_user_unit(cgroup, unit);
-}
-
-int cg_path_get_machine_name(const char *path, char **machine) {
- _cleanup_free_ char *u = NULL;
- const char *sl;
- int r;
-
- r = cg_path_get_unit(path, &u);
- if (r < 0)
- return r;
-
- sl = strjoina("/run/systemd/machines/unit:", u);
- return readlink_malloc(sl, machine);
-}
-
-int cg_pid_get_machine_name(pid_t pid, char **machine) {
- _cleanup_free_ char *cgroup = NULL;
- int r;
-
- assert(machine);
-
- r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
- if (r < 0)
- return r;
-
- return cg_path_get_machine_name(cgroup, machine);
-}
-
-int cg_path_get_session(const char *path, char **session) {
- _cleanup_free_ char *unit = NULL;
- char *start, *end;
- int r;
-
- assert(path);
-
- r = cg_path_get_unit(path, &unit);
- if (r < 0)
- return r;
-
- start = startswith(unit, "session-");
- if (!start)
- return -ENXIO;
- end = endswith(start, ".scope");
- if (!end)
- return -ENXIO;
-
- *end = 0;
- if (!session_id_valid(start))
- return -ENXIO;
-
- if (session) {
- char *rr;
-
- rr = strdup(start);
- if (!rr)
- return -ENOMEM;
-
- *session = rr;
- }
-
- return 0;
-}
-
-int cg_pid_get_session(pid_t pid, char **session) {
- _cleanup_free_ char *cgroup = NULL;
- int r;
-
- r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
- if (r < 0)
- return r;
-
- return cg_path_get_session(cgroup, session);
-}
-
-int cg_path_get_owner_uid(const char *path, uid_t *uid) {
- _cleanup_free_ char *slice = NULL;
- char *start, *end;
- int r;
-
- assert(path);
-
- r = cg_path_get_slice(path, &slice);
- if (r < 0)
- return r;
-
- start = startswith(slice, "user-");
- if (!start)
- return -ENXIO;
- end = endswith(start, ".slice");
- if (!end)
- return -ENXIO;
-
- *end = 0;
- if (parse_uid(start, uid) < 0)
- return -ENXIO;
-
- return 0;
-}
-
-int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) {
- _cleanup_free_ char *cgroup = NULL;
- int r;
-
- r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
- if (r < 0)
- return r;
-
- return cg_path_get_owner_uid(cgroup, uid);
-}
-
-int cg_path_get_slice(const char *p, char **slice) {
- const char *e = NULL;
-
- assert(p);
- assert(slice);
-
- /* Finds the right-most slice unit from the beginning, but
- * stops before we come to the first non-slice unit. */
-
- for (;;) {
- size_t n;
-
- p += strspn(p, "/");
-
- n = strcspn(p, "/");
- if (!valid_slice_name(p, n)) {
-
- if (!e) {
- char *s;
-
- s = strdup(SPECIAL_ROOT_SLICE);
- if (!s)
- return -ENOMEM;
-
- *slice = s;
- return 0;
- }
-
- return cg_path_decode_unit(e, slice);
- }
-
- e = p;
- p += n;
- }
-}
-
-int cg_pid_get_slice(pid_t pid, char **slice) {
- _cleanup_free_ char *cgroup = NULL;
- int r;
-
- assert(slice);
-
- r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
- if (r < 0)
- return r;
-
- return cg_path_get_slice(cgroup, slice);
-}
-
-int cg_path_get_user_slice(const char *p, char **slice) {
- const char *t;
- assert(p);
- assert(slice);
-
- t = skip_user_prefix(p);
- if (!t)
- return -ENXIO;
-
- /* And now it looks pretty much the same as for a system
- * slice, so let's just use the same parser from here on. */
- return cg_path_get_slice(t, slice);
-}
-
-int cg_pid_get_user_slice(pid_t pid, char **slice) {
- _cleanup_free_ char *cgroup = NULL;
- int r;
-
- assert(slice);
-
- r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
- if (r < 0)
- return r;
-
- return cg_path_get_user_slice(cgroup, slice);
-}
-
-char *cg_escape(const char *p) {
- bool need_prefix = false;
-
- /* This implements very minimal escaping for names to be used
- * as file names in the cgroup tree: any name which might
- * conflict with a kernel name or is prefixed with '_' is
- * prefixed with a '_'. That way, when reading cgroup names it
- * is sufficient to remove a single prefixing underscore if
- * there is one. */
-
- /* The return value of this function (unlike cg_unescape())
- * needs free()! */
-
- if (p[0] == 0 ||
- p[0] == '_' ||
- p[0] == '.' ||
- streq(p, "notify_on_release") ||
- streq(p, "release_agent") ||
- streq(p, "tasks") ||
- startswith(p, "cgroup."))
- need_prefix = true;
- else {
- const char *dot;
-
- dot = strrchr(p, '.');
- if (dot) {
- CGroupController c;
- size_t l = dot - p;
-
- for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
- const char *n;
-
- n = cgroup_controller_to_string(c);
-
- if (l != strlen(n))
- continue;
-
- if (memcmp(p, n, l) != 0)
- continue;
-
- need_prefix = true;
- break;
- }
- }
- }
-
- if (need_prefix)
- return strappend("_", p);
-
- return strdup(p);
-}
-
-char *cg_unescape(const char *p) {
- assert(p);
-
- /* The return value of this function (unlike cg_escape())
- * doesn't need free()! */
-
- if (p[0] == '_')
- return (char*) p+1;
-
- return (char*) p;
-}
-
-#define CONTROLLER_VALID \
- DIGITS LETTERS \
- "_"
-
-bool cg_controller_is_valid(const char *p) {
- const char *t, *s;
-
- if (!p)
- return false;
-
- s = startswith(p, "name=");
- if (s)
- p = s;
-
- if (*p == 0 || *p == '_')
- return false;
-
- for (t = p; *t; t++)
- if (!strchr(CONTROLLER_VALID, *t))
- return false;
-
- if (t - p > FILENAME_MAX)
- return false;
-
- return true;
-}
-
-int cg_slice_to_path(const char *unit, char **ret) {
- _cleanup_free_ char *p = NULL, *s = NULL, *e = NULL;
- const char *dash;
- int r;
-
- assert(unit);
- assert(ret);
-
- if (streq(unit, SPECIAL_ROOT_SLICE)) {
- char *x;
-
- x = strdup("");
- if (!x)
- return -ENOMEM;
- *ret = x;
- return 0;
- }
-
- if (!unit_name_is_valid(unit, UNIT_NAME_PLAIN))
- return -EINVAL;
-
- if (!endswith(unit, ".slice"))
- return -EINVAL;
-
- r = unit_name_to_prefix(unit, &p);
- if (r < 0)
- return r;
-
- dash = strchr(p, '-');
-
- /* Don't allow initial dashes */
- if (dash == p)
- return -EINVAL;
-
- while (dash) {
- _cleanup_free_ char *escaped = NULL;
- char n[dash - p + sizeof(".slice")];
-
- /* Don't allow trailing or double dashes */
- if (dash[1] == 0 || dash[1] == '-')
- return -EINVAL;
-
- strcpy(stpncpy(n, p, dash - p), ".slice");
- if (!unit_name_is_valid(n, UNIT_NAME_PLAIN))
- return -EINVAL;
-
- escaped = cg_escape(n);
- if (!escaped)
- return -ENOMEM;
-
- if (!strextend(&s, escaped, "/", NULL))
- return -ENOMEM;
-
- dash = strchr(dash+1, '-');
- }
-
- e = cg_escape(unit);
- if (!e)
- return -ENOMEM;
-
- if (!strextend(&s, e, NULL))
- return -ENOMEM;
-
- *ret = s;
- s = NULL;
-
- return 0;
-}
-
-int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value) {
- _cleanup_free_ char *p = NULL;
- int r;
-
- r = cg_get_path(controller, path, attribute, &p);
- if (r < 0)
- return r;
-
- return write_string_file(p, value, 0);
-}
-
-int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret) {
- _cleanup_free_ char *p = NULL;
- int r;
-
- r = cg_get_path(controller, path, attribute, &p);
- if (r < 0)
- return r;
-
- return read_one_line_file(p, ret);
-}
-
-int cg_get_keyed_attribute(const char *controller, const char *path, const char *attribute, const char **keys, char **values) {
- _cleanup_free_ char *filename = NULL, *content = NULL;
- char *line, *p;
- int i, r;
-
- for (i = 0; keys[i]; i++)
- values[i] = NULL;
-
- r = cg_get_path(controller, path, attribute, &filename);
- if (r < 0)
- return r;
-
- r = read_full_file(filename, &content, NULL);
- if (r < 0)
- return r;
-
- p = content;
- while ((line = strsep(&p, "\n"))) {
- char *key;
-
- key = strsep(&line, " ");
-
- for (i = 0; keys[i]; i++) {
- if (streq(key, keys[i])) {
- values[i] = strdup(line);
- break;
- }
- }
- }
-
- for (i = 0; keys[i]; i++) {
- if (!values[i]) {
- for (i = 0; keys[i]; i++) {
- free(values[i]);
- values[i] = NULL;
- }
- return -ENOENT;
- }
- }
-
- return 0;
-}
-
-int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path) {
- CGroupController c;
- int r, unified;
-
- /* This one will create a cgroup in our private tree, but also
- * duplicate it in the trees specified in mask, and remove it
- * in all others */
-
- /* First create the cgroup in our own hierarchy. */
- r = cg_create(SYSTEMD_CGROUP_CONTROLLER, path);
- if (r < 0)
- return r;
-
- /* If we are in the unified hierarchy, we are done now */
- unified = cg_all_unified();
- if (unified < 0)
- return unified;
- if (unified > 0)
- return 0;
-
- /* Otherwise, do the same in the other hierarchies */
- for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
- CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c);
- const char *n;
-
- n = cgroup_controller_to_string(c);
-
- if (mask & bit)
- (void) cg_create(n, path);
- else if (supported & bit)
- (void) cg_trim(n, path, true);
- }
-
- return 0;
-}
-
-int cg_attach_everywhere(CGroupMask supported, const char *path, pid_t pid, cg_migrate_callback_t path_callback, void *userdata) {
- CGroupController c;
- int r, unified;
-
- r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, path, pid);
- if (r < 0)
- return r;
-
- unified = cg_all_unified();
- if (unified < 0)
- return unified;
- if (unified > 0)
- return 0;
-
- for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
- CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c);
- const char *p = NULL;
-
- if (!(supported & bit))
- continue;
-
- if (path_callback)
- p = path_callback(bit, userdata);
-
- if (!p)
- p = path;
-
- (void) cg_attach_fallback(cgroup_controller_to_string(c), p, pid);
- }
-
- return 0;
-}
-
-int cg_attach_many_everywhere(CGroupMask supported, const char *path, Set* pids, cg_migrate_callback_t path_callback, void *userdata) {
- Iterator i;
- void *pidp;
- int r = 0;
-
- SET_FOREACH(pidp, pids, i) {
- pid_t pid = PTR_TO_PID(pidp);
- int q;
-
- q = cg_attach_everywhere(supported, path, pid, path_callback, userdata);
- if (q < 0 && r >= 0)
- r = q;
- }
-
- return r;
-}
-
-int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to, cg_migrate_callback_t to_callback, void *userdata) {
- CGroupController c;
- int r = 0, unified;
-
- if (!path_equal(from, to)) {
- r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, CGROUP_REMOVE);
- if (r < 0)
- return r;
- }
-
- unified = cg_all_unified();
- if (unified < 0)
- return unified;
- if (unified > 0)
- return r;
-
- for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
- CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c);
- const char *p = NULL;
-
- if (!(supported & bit))
- continue;
-
- if (to_callback)
- p = to_callback(bit, userdata);
-
- if (!p)
- p = to;
-
- (void) cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, cgroup_controller_to_string(c), p, 0);
- }
-
- return 0;
-}
-
-int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root) {
- CGroupController c;
- int r, unified;
-
- r = cg_trim(SYSTEMD_CGROUP_CONTROLLER, path, delete_root);
- if (r < 0)
- return r;
-
- unified = cg_all_unified();
- if (unified < 0)
- return unified;
- if (unified > 0)
- return r;
-
- for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
- CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c);
-
- if (!(supported & bit))
- continue;
-
- (void) cg_trim(cgroup_controller_to_string(c), path, delete_root);
- }
-
- return 0;
-}
-
-int cg_mask_supported(CGroupMask *ret) {
- CGroupMask mask = 0;
- int r, unified;
-
- /* Determines the mask of supported cgroup controllers. Only
- * includes controllers we can make sense of and that are
- * actually accessible. */
-
- unified = cg_all_unified();
- if (unified < 0)
- return unified;
- if (unified > 0) {
- _cleanup_free_ char *root = NULL, *controllers = NULL, *path = NULL;
- const char *c;
-
- /* In the unified hierarchy we can read the supported
- * and accessible controllers from a the top-level
- * cgroup attribute */
-
- r = cg_get_root_path(&root);
- if (r < 0)
- return r;
-
- r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, root, "cgroup.controllers", &path);
- if (r < 0)
- return r;
-
- r = read_one_line_file(path, &controllers);
- if (r < 0)
- return r;
-
- c = controllers;
- for (;;) {
- _cleanup_free_ char *n = NULL;
- CGroupController v;
-
- r = extract_first_word(&c, &n, NULL, 0);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- v = cgroup_controller_from_string(n);
- if (v < 0)
- continue;
-
- mask |= CGROUP_CONTROLLER_TO_MASK(v);
- }
-
- /* Currently, we support the cpu, memory, io and pids
- * controller in the unified hierarchy, mask
- * everything else off. */
- mask &= CGROUP_MASK_CPU | CGROUP_MASK_MEMORY | CGROUP_MASK_IO | CGROUP_MASK_PIDS;
-
- } else {
- CGroupController c;
-
- /* In the legacy hierarchy, we check whether which
- * hierarchies are mounted. */
-
- for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
- const char *n;
-
- n = cgroup_controller_to_string(c);
- if (controller_is_accessible(n) >= 0)
- mask |= CGROUP_CONTROLLER_TO_MASK(c);
- }
- }
-
- *ret = mask;
- return 0;
-}
-
-int cg_kernel_controllers(Set *controllers) {
- _cleanup_fclose_ FILE *f = NULL;
- char buf[LINE_MAX];
- int r;
-
- assert(controllers);
-
- /* Determines the full list of kernel-known controllers. Might
- * include controllers we don't actually support, arbitrary
- * named hierarchies and controllers that aren't currently
- * accessible (because not mounted). */
-
- f = fopen("/proc/cgroups", "re");
- if (!f) {
- if (errno == ENOENT)
- return 0;
- return -errno;
- }
-
- /* Ignore the header line */
- (void) fgets(buf, sizeof(buf), f);
-
- for (;;) {
- char *controller;
- int enabled = 0;
-
- errno = 0;
- if (fscanf(f, "%ms %*i %*i %i", &controller, &enabled) != 2) {
-
- if (feof(f))
- break;
-
- if (ferror(f) && errno > 0)
- return -errno;
-
- return -EBADMSG;
- }
-
- if (!enabled) {
- free(controller);
- continue;
- }
-
- if (!cg_controller_is_valid(controller)) {
- free(controller);
- return -EBADMSG;
- }
-
- r = set_consume(controllers, controller);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static thread_local CGroupUnified unified_cache = CGROUP_UNIFIED_UNKNOWN;
-
-static int cg_update_unified(void) {
-
- struct statfs fs;
-
- /* Checks if we support the unified hierarchy. Returns an
- * error when the cgroup hierarchies aren't mounted yet or we
- * have any other trouble determining if the unified hierarchy
- * is supported. */
-
- if (unified_cache >= CGROUP_UNIFIED_NONE)
- return 0;
-
- if (statfs("/sys/fs/cgroup/", &fs) < 0)
- return -errno;
-
- if (F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC))
- unified_cache = CGROUP_UNIFIED_ALL;
- else if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC)) {
- if (statfs("/sys/fs/cgroup/systemd/", &fs) < 0)
- return -errno;
-
- unified_cache = F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC) ?
- CGROUP_UNIFIED_SYSTEMD : CGROUP_UNIFIED_NONE;
- } else
- return -ENOMEDIUM;
-
- return 0;
-}
-
-int cg_unified(const char *controller) {
-
- int r;
-
- r = cg_update_unified();
- if (r < 0)
- return r;
-
- if (streq_ptr(controller, SYSTEMD_CGROUP_CONTROLLER))
- return unified_cache >= CGROUP_UNIFIED_SYSTEMD;
- else
- return unified_cache >= CGROUP_UNIFIED_ALL;
-}
-
-int cg_all_unified(void) {
-
- return cg_unified(NULL);
-}
-
-void cg_unified_flush(void) {
- unified_cache = CGROUP_UNIFIED_UNKNOWN;
-}
-
-int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p) {
- _cleanup_free_ char *fs = NULL;
- CGroupController c;
- int r, unified;
-
- assert(p);
-
- if (supported == 0)
- return 0;
-
- unified = cg_all_unified();
- if (unified < 0)
- return unified;
- if (!unified) /* on the legacy hiearchy there's no joining of controllers defined */
- return 0;
-
- r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, p, "cgroup.subtree_control", &fs);
- if (r < 0)
- return r;
-
- for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
- CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c);
- const char *n;
-
- if (!(supported & bit))
- continue;
-
- n = cgroup_controller_to_string(c);
- {
- char s[1 + strlen(n) + 1];
-
- s[0] = mask & bit ? '+' : '-';
- strcpy(s + 1, n);
-
- r = write_string_file(fs, s, 0);
- if (r < 0)
- log_debug_errno(r, "Failed to enable controller %s for %s (%s): %m", n, p, fs);
- }
- }
-
- return 0;
-}
-
-bool cg_is_unified_wanted(void) {
- static thread_local int wanted = -1;
- int r, unified;
-
- /* If the hierarchy is already mounted, then follow whatever
- * was chosen for it. */
- unified = cg_all_unified();
- if (unified >= 0)
- return unified;
-
- /* Otherwise, let's see what the kernel command line has to
- * say. Since checking that is expensive, let's cache the
- * result. */
- if (wanted >= 0)
- return wanted;
-
- r = get_proc_cmdline_key("systemd.unified_cgroup_hierarchy", NULL);
- if (r > 0)
- return (wanted = true);
- else {
- _cleanup_free_ char *value = NULL;
-
- r = get_proc_cmdline_key("systemd.unified_cgroup_hierarchy=", &value);
- if (r < 0)
- return false;
- if (r == 0)
- return (wanted = false);
-
- return (wanted = parse_boolean(value) > 0);
- }
-}
-
-bool cg_is_legacy_wanted(void) {
- return !cg_is_unified_wanted();
-}
-
-bool cg_is_unified_systemd_controller_wanted(void) {
- static thread_local int wanted = -1;
- int r, unified;
-
- /* If the unified hierarchy is requested in full, no need to
- * bother with this. */
- if (cg_is_unified_wanted())
- return 0;
-
- /* If the hierarchy is already mounted, then follow whatever
- * was chosen for it. */
- unified = cg_unified(SYSTEMD_CGROUP_CONTROLLER);
- if (unified >= 0)
- return unified;
-
- /* Otherwise, let's see what the kernel command line has to
- * say. Since checking that is expensive, let's cache the
- * result. */
- if (wanted >= 0)
- return wanted;
-
- r = get_proc_cmdline_key("systemd.legacy_systemd_cgroup_controller", NULL);
- if (r > 0)
- wanted = false;
- else {
- _cleanup_free_ char *value = NULL;
-
- r = get_proc_cmdline_key("systemd.legacy_systemd_cgroup_controller=", &value);
- if (r < 0)
- return false;
-
- if (r == 0)
- wanted = false;
- else
- wanted = parse_boolean(value) <= 0;
- }
-
- return wanted;
-}
-
-bool cg_is_legacy_systemd_controller_wanted(void) {
- return cg_is_legacy_wanted() && !cg_is_unified_systemd_controller_wanted();
-}
-
-int cg_weight_parse(const char *s, uint64_t *ret) {
- uint64_t u;
- int r;
-
- if (isempty(s)) {
- *ret = CGROUP_WEIGHT_INVALID;
- return 0;
- }
-
- r = safe_atou64(s, &u);
- if (r < 0)
- return r;
-
- if (u < CGROUP_WEIGHT_MIN || u > CGROUP_WEIGHT_MAX)
- return -ERANGE;
-
- *ret = u;
- return 0;
-}
-
-const uint64_t cgroup_io_limit_defaults[_CGROUP_IO_LIMIT_TYPE_MAX] = {
- [CGROUP_IO_RBPS_MAX] = CGROUP_LIMIT_MAX,
- [CGROUP_IO_WBPS_MAX] = CGROUP_LIMIT_MAX,
- [CGROUP_IO_RIOPS_MAX] = CGROUP_LIMIT_MAX,
- [CGROUP_IO_WIOPS_MAX] = CGROUP_LIMIT_MAX,
-};
-
-static const char* const cgroup_io_limit_type_table[_CGROUP_IO_LIMIT_TYPE_MAX] = {
- [CGROUP_IO_RBPS_MAX] = "IOReadBandwidthMax",
- [CGROUP_IO_WBPS_MAX] = "IOWriteBandwidthMax",
- [CGROUP_IO_RIOPS_MAX] = "IOReadIOPSMax",
- [CGROUP_IO_WIOPS_MAX] = "IOWriteIOPSMax",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(cgroup_io_limit_type, CGroupIOLimitType);
-
-int cg_cpu_shares_parse(const char *s, uint64_t *ret) {
- uint64_t u;
- int r;
-
- if (isempty(s)) {
- *ret = CGROUP_CPU_SHARES_INVALID;
- return 0;
- }
-
- r = safe_atou64(s, &u);
- if (r < 0)
- return r;
-
- if (u < CGROUP_CPU_SHARES_MIN || u > CGROUP_CPU_SHARES_MAX)
- return -ERANGE;
-
- *ret = u;
- return 0;
-}
-
-int cg_blkio_weight_parse(const char *s, uint64_t *ret) {
- uint64_t u;
- int r;
-
- if (isempty(s)) {
- *ret = CGROUP_BLKIO_WEIGHT_INVALID;
- return 0;
- }
-
- r = safe_atou64(s, &u);
- if (r < 0)
- return r;
-
- if (u < CGROUP_BLKIO_WEIGHT_MIN || u > CGROUP_BLKIO_WEIGHT_MAX)
- return -ERANGE;
-
- *ret = u;
- return 0;
-}
-
-bool is_cgroup_fs(const struct statfs *s) {
- return is_fs_type(s, CGROUP_SUPER_MAGIC) ||
- is_fs_type(s, CGROUP2_SUPER_MAGIC);
-}
-
-bool fd_is_cgroup_fs(int fd) {
- struct statfs s;
-
- if (fstatfs(fd, &s) < 0)
- return -errno;
-
- return is_cgroup_fs(&s);
-}
-
-static const char *cgroup_controller_table[_CGROUP_CONTROLLER_MAX] = {
- [CGROUP_CONTROLLER_CPU] = "cpu",
- [CGROUP_CONTROLLER_CPUACCT] = "cpuacct",
- [CGROUP_CONTROLLER_IO] = "io",
- [CGROUP_CONTROLLER_BLKIO] = "blkio",
- [CGROUP_CONTROLLER_MEMORY] = "memory",
- [CGROUP_CONTROLLER_DEVICES] = "devices",
- [CGROUP_CONTROLLER_PIDS] = "pids",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(cgroup_controller, CGroupController);
diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h
deleted file mode 100644
index 0aa27c4cd7..0000000000
--- a/src/basic/cgroup-util.h
+++ /dev/null
@@ -1,260 +0,0 @@
-#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 <dirent.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <sys/statfs.h>
-#include <sys/types.h>
-
-#include "def.h"
-#include "hashmap.h"
-#include "macro.h"
-#include "set.h"
-
-/* An enum of well known cgroup controllers */
-typedef enum CGroupController {
- CGROUP_CONTROLLER_CPU,
- CGROUP_CONTROLLER_CPUACCT,
- CGROUP_CONTROLLER_IO,
- CGROUP_CONTROLLER_BLKIO,
- CGROUP_CONTROLLER_MEMORY,
- CGROUP_CONTROLLER_DEVICES,
- CGROUP_CONTROLLER_PIDS,
- _CGROUP_CONTROLLER_MAX,
- _CGROUP_CONTROLLER_INVALID = -1,
-} CGroupController;
-
-#define CGROUP_CONTROLLER_TO_MASK(c) (1 << (c))
-
-/* A bit mask of well known cgroup controllers */
-typedef enum CGroupMask {
- CGROUP_MASK_CPU = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPU),
- CGROUP_MASK_CPUACCT = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPUACCT),
- CGROUP_MASK_IO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_IO),
- CGROUP_MASK_BLKIO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BLKIO),
- CGROUP_MASK_MEMORY = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_MEMORY),
- CGROUP_MASK_DEVICES = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_DEVICES),
- CGROUP_MASK_PIDS = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_PIDS),
- _CGROUP_MASK_ALL = CGROUP_CONTROLLER_TO_MASK(_CGROUP_CONTROLLER_MAX) - 1
-} CGroupMask;
-
-/* Special values for all weight knobs on unified hierarchy */
-#define CGROUP_WEIGHT_INVALID ((uint64_t) -1)
-#define CGROUP_WEIGHT_MIN UINT64_C(1)
-#define CGROUP_WEIGHT_MAX UINT64_C(10000)
-#define CGROUP_WEIGHT_DEFAULT UINT64_C(100)
-
-#define CGROUP_LIMIT_MIN UINT64_C(0)
-#define CGROUP_LIMIT_MAX ((uint64_t) -1)
-
-static inline bool CGROUP_WEIGHT_IS_OK(uint64_t x) {
- return
- x == CGROUP_WEIGHT_INVALID ||
- (x >= CGROUP_WEIGHT_MIN && x <= CGROUP_WEIGHT_MAX);
-}
-
-/* IO limits on unified hierarchy */
-typedef enum CGroupIOLimitType {
- CGROUP_IO_RBPS_MAX,
- CGROUP_IO_WBPS_MAX,
- CGROUP_IO_RIOPS_MAX,
- CGROUP_IO_WIOPS_MAX,
-
- _CGROUP_IO_LIMIT_TYPE_MAX,
- _CGROUP_IO_LIMIT_TYPE_INVALID = -1
-} CGroupIOLimitType;
-
-extern const uint64_t cgroup_io_limit_defaults[_CGROUP_IO_LIMIT_TYPE_MAX];
-
-const char* cgroup_io_limit_type_to_string(CGroupIOLimitType t) _const_;
-CGroupIOLimitType cgroup_io_limit_type_from_string(const char *s) _pure_;
-
-/* Special values for the cpu.shares attribute */
-#define CGROUP_CPU_SHARES_INVALID ((uint64_t) -1)
-#define CGROUP_CPU_SHARES_MIN UINT64_C(2)
-#define CGROUP_CPU_SHARES_MAX UINT64_C(262144)
-#define CGROUP_CPU_SHARES_DEFAULT UINT64_C(1024)
-
-static inline bool CGROUP_CPU_SHARES_IS_OK(uint64_t x) {
- return
- x == CGROUP_CPU_SHARES_INVALID ||
- (x >= CGROUP_CPU_SHARES_MIN && x <= CGROUP_CPU_SHARES_MAX);
-}
-
-/* Special values for the blkio.weight attribute */
-#define CGROUP_BLKIO_WEIGHT_INVALID ((uint64_t) -1)
-#define CGROUP_BLKIO_WEIGHT_MIN UINT64_C(10)
-#define CGROUP_BLKIO_WEIGHT_MAX UINT64_C(1000)
-#define CGROUP_BLKIO_WEIGHT_DEFAULT UINT64_C(500)
-
-static inline bool CGROUP_BLKIO_WEIGHT_IS_OK(uint64_t x) {
- return
- x == CGROUP_BLKIO_WEIGHT_INVALID ||
- (x >= CGROUP_BLKIO_WEIGHT_MIN && x <= CGROUP_BLKIO_WEIGHT_MAX);
-}
-
-/* Default resource limits */
-#define DEFAULT_TASKS_MAX_PERCENTAGE 15U /* 15% of PIDs, 4915 on default settings */
-#define DEFAULT_USER_TASKS_MAX_PERCENTAGE 33U /* 33% of PIDs, 10813 on default settings */
-
-typedef enum CGroupUnified {
- CGROUP_UNIFIED_UNKNOWN = -1,
- CGROUP_UNIFIED_NONE = 0, /* Both systemd and controllers on legacy */
- CGROUP_UNIFIED_SYSTEMD = 1, /* Only systemd on unified */
- CGROUP_UNIFIED_ALL = 2, /* Both systemd and controllers on unified */
-} CGroupUnified;
-
-/*
- * General rules:
- *
- * We accept named hierarchies in the syntax "foo" and "name=foo".
- *
- * We expect that named hierarchies do not conflict in name with a
- * kernel hierarchy, modulo the "name=" prefix.
- *
- * We always generate "normalized" controller names, i.e. without the
- * "name=" prefix.
- *
- * We require absolute cgroup paths. When returning, we will always
- * generate paths with multiple adjacent / removed.
- */
-
-int cg_enumerate_processes(const char *controller, const char *path, FILE **_f);
-int cg_read_pid(FILE *f, pid_t *_pid);
-int cg_read_event(const char *controller, const char *path, const char *event,
- char **val);
-
-int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d);
-int cg_read_subgroup(DIR *d, char **fn);
-
-typedef enum CGroupFlags {
- CGROUP_SIGCONT = 1,
- CGROUP_IGNORE_SELF = 2,
- CGROUP_REMOVE = 4,
-} CGroupFlags;
-
-typedef void (*cg_kill_log_func_t)(pid_t pid, int sig, void *userdata);
-
-int cg_kill(const char *controller, const char *path, int sig, CGroupFlags flags, Set *s, cg_kill_log_func_t kill_log, void *userdata);
-int cg_kill_recursive(const char *controller, const char *path, int sig, CGroupFlags flags, Set *s, cg_kill_log_func_t kill_log, void *userdata);
-
-int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags);
-int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags);
-int cg_migrate_recursive_fallback(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags);
-
-int cg_split_spec(const char *spec, char **controller, char **path);
-int cg_mangle_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_pid_get_path(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);
-
-int cg_create(const char *controller, const char *path);
-int cg_attach(const char *controller, const char *path, pid_t pid);
-int cg_attach_fallback(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_attribute(const char *controller, const char *path, const char *attribute, const char *value);
-int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret);
-int cg_get_keyed_attribute(const char *controller, const char *path, const char *attribute, const char **keys, char **values);
-
-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 cg_set_xattr(const char *controller, const char *path, const char *name, const void *value, size_t size, int flags);
-int cg_get_xattr(const char *controller, const char *path, const char *name, void *value, size_t size);
-
-int cg_install_release_agent(const char *controller, const char *agent);
-int cg_uninstall_release_agent(const char *controller);
-
-int cg_is_empty(const char *controller, const char *path);
-int cg_is_empty_recursive(const char *controller, const char *path);
-
-int cg_get_root_path(char **path);
-
-int cg_path_get_session(const char *path, char **session);
-int cg_path_get_owner_uid(const char *path, uid_t *uid);
-int cg_path_get_unit(const char *path, char **unit);
-int cg_path_get_user_unit(const char *path, char **unit);
-int cg_path_get_machine_name(const char *path, char **machine);
-int cg_path_get_slice(const char *path, char **slice);
-int cg_path_get_user_slice(const char *path, char **slice);
-
-int cg_shift_path(const char *cgroup, const char *cached_root, const char **shifted);
-int cg_pid_get_path_shifted(pid_t pid, const char *cached_root, char **cgroup);
-
-int cg_pid_get_session(pid_t pid, char **session);
-int cg_pid_get_owner_uid(pid_t pid, uid_t *uid);
-int cg_pid_get_unit(pid_t pid, char **unit);
-int cg_pid_get_user_unit(pid_t pid, char **unit);
-int cg_pid_get_machine_name(pid_t pid, char **machine);
-int cg_pid_get_slice(pid_t pid, char **slice);
-int cg_pid_get_user_slice(pid_t pid, char **slice);
-
-int cg_path_decode_unit(const char *cgroup, char **unit);
-
-char *cg_escape(const char *p);
-char *cg_unescape(const char *p) _pure_;
-
-bool cg_controller_is_valid(const char *p);
-
-int cg_slice_to_path(const char *unit, char **ret);
-
-typedef const char* (*cg_migrate_callback_t)(CGroupMask mask, void *userdata);
-
-int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path);
-int cg_attach_everywhere(CGroupMask supported, const char *path, pid_t pid, cg_migrate_callback_t callback, void *userdata);
-int cg_attach_many_everywhere(CGroupMask supported, const char *path, Set* pids, cg_migrate_callback_t callback, void *userdata);
-int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to, cg_migrate_callback_t callback, void *userdata);
-int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root);
-int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p);
-
-int cg_mask_supported(CGroupMask *ret);
-
-int cg_kernel_controllers(Set *controllers);
-
-bool cg_ns_supported(void);
-
-int cg_all_unified(void);
-int cg_unified(const char *controller);
-void cg_unified_flush(void);
-
-bool cg_is_unified_wanted(void);
-bool cg_is_legacy_wanted(void);
-bool cg_is_unified_systemd_controller_wanted(void);
-bool cg_is_legacy_systemd_controller_wanted(void);
-
-const char* cgroup_controller_to_string(CGroupController c) _const_;
-CGroupController cgroup_controller_from_string(const char *s) _pure_;
-
-int cg_weight_parse(const char *s, uint64_t *ret);
-int cg_cpu_shares_parse(const char *s, uint64_t *ret);
-int cg_blkio_weight_parse(const char *s, uint64_t *ret);
-
-bool is_cgroup_fs(const struct statfs *s);
-bool fd_is_cgroup_fs(int fd);
diff --git a/src/basic/chattr-util.c b/src/basic/chattr-util.c
deleted file mode 100644
index 2896a729af..0000000000
--- a/src/basic/chattr-util.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/***
- 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 <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <linux/fs.h>
-
-#include "chattr-util.h"
-#include "fd-util.h"
-#include "macro.h"
-
-int chattr_fd(int fd, unsigned value, unsigned mask) {
- unsigned old_attr, new_attr;
- struct stat st;
-
- assert(fd >= 0);
-
- if (fstat(fd, &st) < 0)
- return -errno;
-
- /* Explicitly check whether this is a regular file or
- * directory. If it is anything else (such as a device node or
- * fifo), then the ioctl will not hit the file systems but
- * possibly drivers, where the ioctl might have different
- * effects. Notably, DRM is using the same ioctl() number. */
-
- if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
- return -ENOTTY;
-
- if (mask == 0)
- return 0;
-
- if (ioctl(fd, FS_IOC_GETFLAGS, &old_attr) < 0)
- return -errno;
-
- new_attr = (old_attr & ~mask) | (value & mask);
- if (new_attr == old_attr)
- return 0;
-
- if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) < 0)
- return -errno;
-
- return 1;
-}
-
-int chattr_path(const char *p, unsigned value, unsigned mask) {
- _cleanup_close_ int fd = -1;
-
- assert(p);
-
- if (mask == 0)
- return 0;
-
- fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
- if (fd < 0)
- return -errno;
-
- return chattr_fd(fd, value, mask);
-}
-
-int read_attr_fd(int fd, unsigned *ret) {
- struct stat st;
-
- assert(fd >= 0);
-
- if (fstat(fd, &st) < 0)
- return -errno;
-
- if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
- return -ENOTTY;
-
- if (ioctl(fd, FS_IOC_GETFLAGS, ret) < 0)
- return -errno;
-
- return 0;
-}
-
-int read_attr_path(const char *p, unsigned *ret) {
- _cleanup_close_ int fd = -1;
-
- assert(p);
- assert(ret);
-
- fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
- if (fd < 0)
- return -errno;
-
- return read_attr_fd(fd, ret);
-}
diff --git a/src/basic/chattr-util.h b/src/basic/chattr-util.h
deleted file mode 100644
index 960cf6d5b3..0000000000
--- a/src/basic/chattr-util.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#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/>.
-***/
-
-int chattr_fd(int fd, unsigned value, unsigned mask);
-int chattr_path(const char *p, unsigned value, unsigned mask);
-
-int read_attr_fd(int fd, unsigned *ret);
-int read_attr_path(const char *p, unsigned *ret);
diff --git a/src/basic/clock-util.c b/src/basic/clock-util.c
deleted file mode 100644
index 7fe8d35ea5..0000000000
--- a/src/basic/clock-util.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/***
- 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 <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <time.h>
-#include <linux/rtc.h>
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-
-#include "clock-util.h"
-#include "fd-util.h"
-#include "macro.h"
-#include "string-util.h"
-#include "util.h"
-
-int clock_get_hwclock(struct tm *tm) {
- _cleanup_close_ int fd = -1;
-
- assert(tm);
-
- fd = open("/dev/rtc", O_RDONLY|O_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- /* This leaves the timezone fields of struct tm
- * uninitialized! */
- if (ioctl(fd, RTC_RD_TIME, tm) < 0)
- return -errno;
-
- /* We don't know daylight saving, so we reset this in order not
- * to confuse mktime(). */
- tm->tm_isdst = -1;
-
- return 0;
-}
-
-int clock_set_hwclock(const struct tm *tm) {
- _cleanup_close_ int fd = -1;
-
- assert(tm);
-
- fd = open("/dev/rtc", O_RDONLY|O_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- if (ioctl(fd, RTC_SET_TIME, tm) < 0)
- return -errno;
-
- return 0;
-}
-
-int clock_is_localtime(const char* adjtime_path) {
- _cleanup_fclose_ FILE *f;
-
- if (adjtime_path == NULL)
- adjtime_path = "/etc/adjtime";
-
- /*
- * The third line of adjtime is "UTC" or "LOCAL" or nothing.
- * # /etc/adjtime
- * 0.0 0 0
- * 0
- * UTC
- */
- f = fopen(adjtime_path, "re");
- if (f) {
- char line[LINE_MAX];
- bool b;
-
- b = fgets(line, sizeof(line), f) &&
- fgets(line, sizeof(line), f) &&
- fgets(line, sizeof(line), f);
- if (!b)
- /* less than three lines -> default to UTC */
- return 0;
-
- truncate_nl(line);
- return streq(line, "LOCAL");
-
- } else if (errno != ENOENT)
- return -errno;
-
- /* adjtime not present -> default to UTC */
- return 0;
-}
-
-int clock_set_timezone(int *min) {
- const struct timeval *tv_null = NULL;
- struct timespec ts;
- struct tm *tm;
- int minutesdelta;
- struct timezone tz;
-
- assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
- assert_se(tm = localtime(&ts.tv_sec));
- minutesdelta = tm->tm_gmtoff / 60;
-
- tz.tz_minuteswest = -minutesdelta;
- tz.tz_dsttime = 0; /* DST_NONE */
-
- /*
- * If the RTC does not run in UTC but in local time, the very first
- * call to settimeofday() will set the kernel's timezone and will warp the
- * system clock, so that it runs in UTC instead of the local time we
- * have read from the RTC.
- */
- if (settimeofday(tv_null, &tz) < 0)
- return negative_errno();
-
- if (min)
- *min = minutesdelta;
- return 0;
-}
-
-int clock_reset_timewarp(void) {
- const struct timeval *tv_null = NULL;
- struct timezone tz;
-
- tz.tz_minuteswest = 0;
- tz.tz_dsttime = 0; /* DST_NONE */
-
- /*
- * The very first call to settimeofday() does time warp magic. Do a
- * dummy call here, so the time warping is sealed and all later calls
- * behave as expected.
- */
- if (settimeofday(tv_null, &tz) < 0)
- return -errno;
-
- return 0;
-}
-
-#define TIME_EPOCH_USEC ((usec_t) TIME_EPOCH * USEC_PER_SEC)
-
-int clock_apply_epoch(void) {
- struct timespec ts;
-
- if (now(CLOCK_REALTIME) >= TIME_EPOCH_USEC)
- return 0;
-
- if (clock_settime(CLOCK_REALTIME, timespec_store(&ts, TIME_EPOCH_USEC)) < 0)
- return -errno;
-
- return 1;
-}
diff --git a/src/basic/clock-util.h b/src/basic/clock-util.h
deleted file mode 100644
index 8830cd2f38..0000000000
--- a/src/basic/clock-util.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#pragma once
-
-/***
- 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 <time.h>
-
-int clock_is_localtime(const char* adjtime_path);
-int clock_set_timezone(int *min);
-int clock_reset_timewarp(void);
-int clock_get_hwclock(struct tm *tm);
-int clock_set_hwclock(const struct tm *tm);
-int clock_apply_epoch(void);
diff --git a/src/basic/conf-files.c b/src/basic/conf-files.c
deleted file mode 100644
index c781610e14..0000000000
--- a/src/basic/conf-files.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/***
- 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 <dirent.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "conf-files.h"
-#include "dirent-util.h"
-#include "fd-util.h"
-#include "hashmap.h"
-#include "log.h"
-#include "macro.h"
-#include "missing.h"
-#include "path-util.h"
-#include "string-util.h"
-#include "strv.h"
-#include "util.h"
-
-static int files_add(Hashmap *h, const char *root, const char *path, const char *suffix) {
- _cleanup_closedir_ DIR *dir = NULL;
- const char *dirpath;
- struct dirent *de;
- int r;
-
- assert(path);
- assert(suffix);
-
- dirpath = prefix_roota(root, path);
-
- dir = opendir(dirpath);
- if (!dir) {
- if (errno == ENOENT)
- return 0;
- return -errno;
- }
-
- FOREACH_DIRENT(de, dir, return -errno) {
- char *p;
-
- if (!dirent_is_file_with_suffix(de, suffix))
- continue;
-
- p = strjoin(dirpath, "/", de->d_name, NULL);
- if (!p)
- return -ENOMEM;
-
- r = hashmap_put(h, basename(p), p);
- if (r == -EEXIST) {
- log_debug("Skipping overridden file: %s.", p);
- free(p);
- } else if (r < 0) {
- free(p);
- return r;
- } else if (r == 0) {
- log_debug("Duplicate file %s", p);
- free(p);
- }
- }
-
- return 0;
-}
-
-static int base_cmp(const void *a, const void *b) {
- const char *s1, *s2;
-
- s1 = *(char * const *)a;
- s2 = *(char * const *)b;
- return strcmp(basename(s1), basename(s2));
-}
-
-static int conf_files_list_strv_internal(char ***strv, const char *suffix, const char *root, char **dirs) {
- _cleanup_hashmap_free_ Hashmap *fh = NULL;
- char **files, **p;
- int r;
-
- assert(strv);
- assert(suffix);
-
- /* This alters the dirs string array */
- if (!path_strv_resolve_uniq(dirs, root))
- return -ENOMEM;
-
- fh = hashmap_new(&string_hash_ops);
- if (!fh)
- return -ENOMEM;
-
- STRV_FOREACH(p, dirs) {
- r = files_add(fh, root, *p, suffix);
- if (r == -ENOMEM)
- return r;
- if (r < 0)
- log_debug_errno(r, "Failed to search for files in %s, ignoring: %m", *p);
- }
-
- files = hashmap_get_strv(fh);
- if (!files)
- return -ENOMEM;
-
- qsort_safe(files, hashmap_size(fh), sizeof(char *), base_cmp);
- *strv = files;
-
- return 0;
-}
-
-int conf_files_list_strv(char ***strv, const char *suffix, const char *root, const char* const* dirs) {
- _cleanup_strv_free_ char **copy = NULL;
-
- assert(strv);
- assert(suffix);
-
- copy = strv_copy((char**) dirs);
- if (!copy)
- return -ENOMEM;
-
- return conf_files_list_strv_internal(strv, suffix, root, copy);
-}
-
-int conf_files_list(char ***strv, const char *suffix, const char *root, const char *dir, ...) {
- _cleanup_strv_free_ char **dirs = NULL;
- va_list ap;
-
- assert(strv);
- assert(suffix);
-
- va_start(ap, dir);
- dirs = strv_new_ap(dir, ap);
- va_end(ap);
-
- if (!dirs)
- return -ENOMEM;
-
- return conf_files_list_strv_internal(strv, suffix, root, dirs);
-}
-
-int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, const char *d) {
- _cleanup_strv_free_ char **dirs = NULL;
-
- assert(strv);
- assert(suffix);
-
- dirs = strv_split_nulstr(d);
- if (!dirs)
- return -ENOMEM;
-
- return conf_files_list_strv_internal(strv, suffix, root, dirs);
-}
diff --git a/src/basic/conf-files.h b/src/basic/conf-files.h
deleted file mode 100644
index e00e0e81fb..0000000000
--- a/src/basic/conf-files.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-/***
- 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/>.
-***/
-
-int conf_files_list(char ***ret, const char *suffix, const char *root, const char *dir, ...);
-int conf_files_list_strv(char ***ret, const char *suffix, const char *root, const char* const* dirs);
-int conf_files_list_nulstr(char ***ret, const char *suffix, const char *root, const char *dirs);
diff --git a/src/basic/copy.c b/src/basic/copy.c
deleted file mode 100644
index 9883f5fa31..0000000000
--- a/src/basic/copy.c
+++ /dev/null
@@ -1,603 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 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 <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/sendfile.h>
-#include <sys/stat.h>
-#include <sys/xattr.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "alloc-util.h"
-#include "btrfs-util.h"
-#include "chattr-util.h"
-#include "copy.h"
-#include "dirent-util.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "fs-util.h"
-#include "io-util.h"
-#include "macro.h"
-#include "missing.h"
-#include "string-util.h"
-#include "strv.h"
-#include "time-util.h"
-#include "umask-util.h"
-#include "xattr-util.h"
-
-#define COPY_BUFFER_SIZE (16*1024u)
-
-static ssize_t try_copy_file_range(int fd_in, loff_t *off_in,
- int fd_out, loff_t *off_out,
- size_t len,
- unsigned int flags) {
- static int have = -1;
- ssize_t r;
-
- if (have == false)
- return -ENOSYS;
-
- r = copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
- if (_unlikely_(have < 0))
- have = r >= 0 || errno != ENOSYS;
- if (r >= 0)
- return r;
- else
- return -errno;
-}
-
-int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
- bool try_cfr = true, try_sendfile = true, try_splice = true;
- int r;
- size_t m = SSIZE_MAX; /* that is the maximum that sendfile and c_f_r accept */
-
- assert(fdf >= 0);
- assert(fdt >= 0);
-
- /* Try btrfs reflinks first. */
- if (try_reflink &&
- max_bytes == (uint64_t) -1 &&
- lseek(fdf, 0, SEEK_CUR) == 0 &&
- lseek(fdt, 0, SEEK_CUR) == 0) {
-
- r = btrfs_reflink(fdf, fdt);
- if (r >= 0)
- return 0; /* we copied the whole thing, hence hit EOF, return 0 */
- }
-
- for (;;) {
- ssize_t n;
-
- if (max_bytes != (uint64_t) -1) {
- if (max_bytes <= 0)
- return 1; /* return > 0 if we hit the max_bytes limit */
-
- if (m > max_bytes)
- m = max_bytes;
- }
-
- /* First try copy_file_range(), unless we already tried */
- if (try_cfr) {
- n = try_copy_file_range(fdf, NULL, fdt, NULL, m, 0u);
- if (n < 0) {
- if (!IN_SET(n, -EINVAL, -ENOSYS, -EXDEV, -EBADF))
- return n;
-
- try_cfr = false;
- /* use fallback below */
- } else if (n == 0) /* EOF */
- break;
- else
- /* Success! */
- goto next;
- }
-
- /* First try sendfile(), unless we already tried */
- if (try_sendfile) {
- n = sendfile(fdt, fdf, NULL, m);
- if (n < 0) {
- if (!IN_SET(errno, EINVAL, ENOSYS))
- return -errno;
-
- try_sendfile = false;
- /* use fallback below */
- } else if (n == 0) /* EOF */
- break;
- else
- /* Success! */
- goto next;
- }
-
- /* Then try splice, unless we already tried */
- if (try_splice) {
- n = splice(fdf, NULL, fdt, NULL, m, 0);
- if (n < 0) {
- if (!IN_SET(errno, EINVAL, ENOSYS))
- return -errno;
-
- try_splice = false;
- /* use fallback below */
- } else if (n == 0) /* EOF */
- break;
- else
- /* Success! */
- goto next;
- }
-
- /* As a fallback just copy bits by hand */
- {
- uint8_t buf[MIN(m, COPY_BUFFER_SIZE)];
-
- n = read(fdf, buf, sizeof buf);
- if (n < 0)
- return -errno;
- if (n == 0) /* EOF */
- break;
-
- r = loop_write(fdt, buf, (size_t) n, false);
- if (r < 0)
- return r;
- }
-
- next:
- if (max_bytes != (uint64_t) -1) {
- assert(max_bytes >= (uint64_t) n);
- max_bytes -= n;
- }
- /* sendfile accepts at most SSIZE_MAX-offset bytes to copy,
- * so reduce our maximum by the amount we already copied,
- * but don't go below our copy buffer size, unless we are
- * close the limit of bytes we are allowed to copy. */
- m = MAX(MIN(COPY_BUFFER_SIZE, max_bytes), m - n);
- }
-
- return 0; /* return 0 if we hit EOF earlier than the size limit */
-}
-
-static int fd_copy_symlink(int df, const char *from, const struct stat *st, int dt, const char *to) {
- _cleanup_free_ char *target = NULL;
- int r;
-
- assert(from);
- assert(st);
- assert(to);
-
- r = readlinkat_malloc(df, from, &target);
- if (r < 0)
- return r;
-
- if (symlinkat(target, dt, to) < 0)
- return -errno;
-
- if (fchownat(dt, to, st->st_uid, st->st_gid, AT_SYMLINK_NOFOLLOW) < 0)
- return -errno;
-
- return 0;
-}
-
-static int fd_copy_regular(int df, const char *from, const struct stat *st, int dt, const char *to) {
- _cleanup_close_ int fdf = -1, fdt = -1;
- struct timespec ts[2];
- int r, q;
-
- assert(from);
- assert(st);
- assert(to);
-
- fdf = openat(df, from, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
- if (fdf < 0)
- return -errno;
-
- fdt = openat(dt, to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, st->st_mode & 07777);
- if (fdt < 0)
- return -errno;
-
- r = copy_bytes(fdf, fdt, (uint64_t) -1, true);
- if (r < 0) {
- unlinkat(dt, to, 0);
- return r;
- }
-
- if (fchown(fdt, st->st_uid, st->st_gid) < 0)
- r = -errno;
-
- if (fchmod(fdt, st->st_mode & 07777) < 0)
- r = -errno;
-
- ts[0] = st->st_atim;
- ts[1] = st->st_mtim;
- (void) futimens(fdt, ts);
-
- (void) copy_xattr(fdf, fdt);
-
- q = close(fdt);
- fdt = -1;
-
- if (q < 0) {
- r = -errno;
- unlinkat(dt, to, 0);
- }
-
- return r;
-}
-
-static int fd_copy_fifo(int df, const char *from, const struct stat *st, int dt, const char *to) {
- int r;
-
- assert(from);
- assert(st);
- assert(to);
-
- r = mkfifoat(dt, to, st->st_mode & 07777);
- if (r < 0)
- return -errno;
-
- if (fchownat(dt, to, st->st_uid, st->st_gid, AT_SYMLINK_NOFOLLOW) < 0)
- r = -errno;
-
- if (fchmodat(dt, to, st->st_mode & 07777, 0) < 0)
- r = -errno;
-
- return r;
-}
-
-static int fd_copy_node(int df, const char *from, const struct stat *st, int dt, const char *to) {
- int r;
-
- assert(from);
- assert(st);
- assert(to);
-
- r = mknodat(dt, to, st->st_mode, st->st_rdev);
- if (r < 0)
- return -errno;
-
- if (fchownat(dt, to, st->st_uid, st->st_gid, AT_SYMLINK_NOFOLLOW) < 0)
- r = -errno;
-
- if (fchmodat(dt, to, st->st_mode & 07777, 0) < 0)
- r = -errno;
-
- return r;
-}
-
-static int fd_copy_directory(
- int df,
- const char *from,
- const struct stat *st,
- int dt,
- const char *to,
- dev_t original_device,
- bool merge) {
-
- _cleanup_close_ int fdf = -1, fdt = -1;
- _cleanup_closedir_ DIR *d = NULL;
- struct dirent *de;
- bool created;
- int r;
-
- assert(st);
- assert(to);
-
- if (from)
- fdf = openat(df, from, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
- else
- fdf = fcntl(df, F_DUPFD_CLOEXEC, 3);
- if (fdf < 0)
- return -errno;
-
- d = fdopendir(fdf);
- if (!d)
- return -errno;
- fdf = -1;
-
- r = mkdirat(dt, to, st->st_mode & 07777);
- if (r >= 0)
- created = true;
- else if (errno == EEXIST && merge)
- created = false;
- else
- return -errno;
-
- fdt = openat(dt, to, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
- if (fdt < 0)
- return -errno;
-
- r = 0;
-
- FOREACH_DIRENT_ALL(de, d, return -errno) {
- struct stat buf;
- int q;
-
- if (STR_IN_SET(de->d_name, ".", ".."))
- continue;
-
- if (fstatat(dirfd(d), de->d_name, &buf, AT_SYMLINK_NOFOLLOW) < 0) {
- r = -errno;
- continue;
- }
-
- if (buf.st_dev != original_device)
- continue;
-
- if (S_ISREG(buf.st_mode))
- q = fd_copy_regular(dirfd(d), de->d_name, &buf, fdt, de->d_name);
- else if (S_ISDIR(buf.st_mode))
- q = fd_copy_directory(dirfd(d), de->d_name, &buf, fdt, de->d_name, original_device, merge);
- else if (S_ISLNK(buf.st_mode))
- q = fd_copy_symlink(dirfd(d), de->d_name, &buf, fdt, de->d_name);
- else if (S_ISFIFO(buf.st_mode))
- q = fd_copy_fifo(dirfd(d), de->d_name, &buf, fdt, de->d_name);
- else if (S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode) || S_ISSOCK(buf.st_mode))
- q = fd_copy_node(dirfd(d), de->d_name, &buf, fdt, de->d_name);
- else
- q = -EOPNOTSUPP;
-
- if (q == -EEXIST && merge)
- q = 0;
-
- if (q < 0)
- r = q;
- }
-
- if (created) {
- struct timespec ut[2] = {
- st->st_atim,
- st->st_mtim
- };
-
- if (fchown(fdt, st->st_uid, st->st_gid) < 0)
- r = -errno;
-
- if (fchmod(fdt, st->st_mode & 07777) < 0)
- r = -errno;
-
- (void) copy_xattr(dirfd(d), fdt);
- (void) futimens(fdt, ut);
- }
-
- return r;
-}
-
-int copy_tree_at(int fdf, const char *from, int fdt, const char *to, bool merge) {
- struct stat st;
-
- assert(from);
- assert(to);
-
- if (fstatat(fdf, from, &st, AT_SYMLINK_NOFOLLOW) < 0)
- return -errno;
-
- if (S_ISREG(st.st_mode))
- return fd_copy_regular(fdf, from, &st, fdt, to);
- else if (S_ISDIR(st.st_mode))
- return fd_copy_directory(fdf, from, &st, fdt, to, st.st_dev, merge);
- else if (S_ISLNK(st.st_mode))
- return fd_copy_symlink(fdf, from, &st, fdt, to);
- else if (S_ISFIFO(st.st_mode))
- return fd_copy_fifo(fdf, from, &st, fdt, to);
- else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode) || S_ISSOCK(st.st_mode))
- return fd_copy_node(fdf, from, &st, fdt, to);
- else
- return -EOPNOTSUPP;
-}
-
-int copy_tree(const char *from, const char *to, bool merge) {
- return copy_tree_at(AT_FDCWD, from, AT_FDCWD, to, merge);
-}
-
-int copy_directory_fd(int dirfd, const char *to, bool merge) {
- struct stat st;
-
- assert(dirfd >= 0);
- assert(to);
-
- if (fstat(dirfd, &st) < 0)
- return -errno;
-
- if (!S_ISDIR(st.st_mode))
- return -ENOTDIR;
-
- return fd_copy_directory(dirfd, NULL, &st, AT_FDCWD, to, st.st_dev, merge);
-}
-
-int copy_directory(const char *from, const char *to, bool merge) {
- struct stat st;
-
- assert(from);
- assert(to);
-
- if (lstat(from, &st) < 0)
- return -errno;
-
- if (!S_ISDIR(st.st_mode))
- return -ENOTDIR;
-
- return fd_copy_directory(AT_FDCWD, from, &st, AT_FDCWD, to, st.st_dev, merge);
-}
-
-int copy_file_fd(const char *from, int fdt, bool try_reflink) {
- _cleanup_close_ int fdf = -1;
- int r;
-
- assert(from);
- assert(fdt >= 0);
-
- fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fdf < 0)
- return -errno;
-
- r = copy_bytes(fdf, fdt, (uint64_t) -1, try_reflink);
-
- (void) copy_times(fdf, fdt);
- (void) copy_xattr(fdf, fdt);
-
- return r;
-}
-
-int copy_file(const char *from, const char *to, int flags, mode_t mode, unsigned chattr_flags) {
- int fdt = -1, r;
-
- assert(from);
- assert(to);
-
- RUN_WITH_UMASK(0000) {
- fdt = open(to, flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode);
- if (fdt < 0)
- return -errno;
- }
-
- if (chattr_flags != 0)
- (void) chattr_fd(fdt, chattr_flags, (unsigned) -1);
-
- r = copy_file_fd(from, fdt, true);
- if (r < 0) {
- close(fdt);
- unlink(to);
- return r;
- }
-
- if (close(fdt) < 0) {
- unlink_noerrno(to);
- return -errno;
- }
-
- return 0;
-}
-
-int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace, unsigned chattr_flags) {
- _cleanup_free_ char *t = NULL;
- int r;
-
- assert(from);
- assert(to);
-
- r = tempfn_random(to, NULL, &t);
- if (r < 0)
- return r;
-
- r = copy_file(from, t, O_NOFOLLOW|O_EXCL, mode, chattr_flags);
- if (r < 0)
- return r;
-
- if (replace) {
- r = renameat(AT_FDCWD, t, AT_FDCWD, to);
- if (r < 0)
- r = -errno;
- } else
- r = rename_noreplace(AT_FDCWD, t, AT_FDCWD, to);
- if (r < 0) {
- (void) unlink_noerrno(t);
- return r;
- }
-
- return 0;
-}
-
-int copy_times(int fdf, int fdt) {
- struct timespec ut[2];
- struct stat st;
- usec_t crtime = 0;
-
- assert(fdf >= 0);
- assert(fdt >= 0);
-
- if (fstat(fdf, &st) < 0)
- return -errno;
-
- ut[0] = st.st_atim;
- ut[1] = st.st_mtim;
-
- if (futimens(fdt, ut) < 0)
- return -errno;
-
- if (fd_getcrtime(fdf, &crtime) >= 0)
- (void) fd_setcrtime(fdt, crtime);
-
- return 0;
-}
-
-int copy_xattr(int fdf, int fdt) {
- _cleanup_free_ char *bufa = NULL, *bufb = NULL;
- size_t sza = 100, szb = 100;
- ssize_t n;
- int ret = 0;
- const char *p;
-
- for (;;) {
- bufa = malloc(sza);
- if (!bufa)
- return -ENOMEM;
-
- n = flistxattr(fdf, bufa, sza);
- if (n == 0)
- return 0;
- if (n > 0)
- break;
- if (errno != ERANGE)
- return -errno;
-
- sza *= 2;
-
- bufa = mfree(bufa);
- }
-
- p = bufa;
- while (n > 0) {
- size_t l;
-
- l = strlen(p);
- assert(l < (size_t) n);
-
- if (startswith(p, "user.")) {
- ssize_t m;
-
- if (!bufb) {
- bufb = malloc(szb);
- if (!bufb)
- return -ENOMEM;
- }
-
- m = fgetxattr(fdf, p, bufb, szb);
- if (m < 0) {
- if (errno == ERANGE) {
- szb *= 2;
- bufb = mfree(bufb);
- continue;
- }
-
- return -errno;
- }
-
- if (fsetxattr(fdt, p, bufb, m, 0) < 0)
- ret = -errno;
- }
-
- p += l + 1;
- n -= l + 1;
- }
-
- return ret;
-}
diff --git a/src/basic/copy.h b/src/basic/copy.h
deleted file mode 100644
index b5d08ebafe..0000000000
--- a/src/basic/copy.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 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 <stdbool.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-int copy_file_fd(const char *from, int to, bool try_reflink);
-int copy_file(const char *from, const char *to, int flags, mode_t mode, unsigned chattr_flags);
-int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace, unsigned chattr_flags);
-int copy_tree(const char *from, const char *to, bool merge);
-int copy_tree_at(int fdf, const char *from, int fdt, const char *to, bool merge);
-int copy_directory_fd(int dirfd, const char *to, bool merge);
-int copy_directory(const char *from, const char *to, bool merge);
-int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink);
-int copy_times(int fdf, int fdt);
-int copy_xattr(int fdf, int fdt);
diff --git a/src/basic/cpu-set-util.c b/src/basic/cpu-set-util.c
deleted file mode 100644
index 95ed6928ff..0000000000
--- a/src/basic/cpu-set-util.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010-2015 Lennart Poettering
- Copyright 2015 Filipe Brandenburger
-
- 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 <stddef.h>
-#include <syslog.h>
-
-#include "alloc-util.h"
-#include "cpu-set-util.h"
-#include "extract-word.h"
-#include "log.h"
-#include "macro.h"
-#include "parse-util.h"
-#include "string-util.h"
-
-cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
- cpu_set_t *c;
- unsigned n = 1024;
-
- /* Allocates the cpuset in the right size */
-
- for (;;) {
- c = CPU_ALLOC(n);
- if (!c)
- return NULL;
-
- if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), c) >= 0) {
- CPU_ZERO_S(CPU_ALLOC_SIZE(n), c);
-
- if (ncpus)
- *ncpus = n;
-
- return c;
- }
-
- CPU_FREE(c);
-
- if (errno != EINVAL)
- return NULL;
-
- n *= 2;
- }
-}
-
-int parse_cpu_set_and_warn(
- const char *rvalue,
- cpu_set_t **cpu_set,
- const char *unit,
- const char *filename,
- unsigned line,
- const char *lvalue) {
-
- const char *whole_rvalue = rvalue;
- _cleanup_cpu_free_ cpu_set_t *c = NULL;
- unsigned ncpus = 0;
-
- assert(lvalue);
- assert(rvalue);
-
- for (;;) {
- _cleanup_free_ char *word = NULL;
- unsigned cpu, cpu_lower, cpu_upper;
- int r;
-
- r = extract_first_word(&rvalue, &word, WHITESPACE ",", EXTRACT_QUOTES);
- if (r < 0)
- return log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, whole_rvalue);
- if (r == 0)
- break;
-
- if (!c) {
- c = cpu_set_malloc(&ncpus);
- if (!c)
- return log_oom();
- }
-
- r = parse_range(word, &cpu_lower, &cpu_upper);
- if (r < 0)
- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU affinity '%s'", word);
- if (cpu_lower >= ncpus || cpu_upper >= ncpus)
- return log_syntax(unit, LOG_ERR, filename, line, EINVAL, "CPU out of range '%s' ncpus is %u", word, ncpus);
-
- if (cpu_lower > cpu_upper)
- log_syntax(unit, LOG_WARNING, filename, line, 0, "Range '%s' is invalid, %u > %u", word, cpu_lower, cpu_upper);
- else
- for (cpu = cpu_lower; cpu <= cpu_upper; cpu++)
- CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c);
- }
-
- /* On success, sets *cpu_set and returns ncpus for the system. */
- if (c) {
- *cpu_set = c;
- c = NULL;
- }
-
- return (int) ncpus;
-}
diff --git a/src/basic/cpu-set-util.h b/src/basic/cpu-set-util.h
deleted file mode 100644
index 6f49d9afb0..0000000000
--- a/src/basic/cpu-set-util.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010-2015 Lennart Poettering
- Copyright 2015 Filipe Brandenburger
-
- 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 <sched.h>
-
-#include "macro.h"
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(cpu_set_t*, CPU_FREE);
-#define _cleanup_cpu_free_ _cleanup_(CPU_FREEp)
-
-cpu_set_t* cpu_set_malloc(unsigned *ncpus);
-
-int parse_cpu_set_and_warn(const char *rvalue, cpu_set_t **cpu_set, const char *unit, const char *filename, unsigned line, const char *lvalue);
diff --git a/src/basic/def.h b/src/basic/def.h
deleted file mode 100644
index 2266eff650..0000000000
--- a/src/basic/def.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#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_START_LIMIT_INTERVAL (10*USEC_PER_SEC)
-#define DEFAULT_START_LIMIT_BURST 5
-
-/* The default time after which exit-on-idle services exit. This
- * should be kept lower than the watchdog timeout, because otherwise
- * the watchdog pings will keep the loop busy. */
-#define DEFAULT_EXIT_USEC (30*USEC_PER_SEC)
-
-/* The default value for the net.unix.max_dgram_qlen sysctl */
-#define DEFAULT_UNIX_MAX_DGRAM_QLEN 512UL
-
-#define SYSTEMD_CGROUP_CONTROLLER "name=systemd"
-
-#define SIGNALS_CRASH_HANDLER SIGSEGV,SIGILL,SIGFPE,SIGBUS,SIGQUIT,SIGABRT
-#define SIGNALS_IGNORE SIGPIPE
-
-#ifdef HAVE_SPLIT_USR
-#define KBD_KEYMAP_DIRS \
- "/usr/share/keymaps/\0" \
- "/usr/share/kbd/keymaps/\0" \
- "/usr/lib/kbd/keymaps/\0" \
- "/lib/kbd/keymaps/\0"
-#else
-#define KBD_KEYMAP_DIRS \
- "/usr/share/keymaps/\0" \
- "/usr/share/kbd/keymaps/\0" \
- "/usr/lib/kbd/keymaps/\0"
-#endif
-
-#define UNIX_SYSTEM_BUS_ADDRESS "unix:path=/var/run/dbus/system_bus_socket"
-#define KERNEL_SYSTEM_BUS_ADDRESS "kernel:path=/sys/fs/kdbus/0-system/bus"
-#define DEFAULT_SYSTEM_BUS_ADDRESS KERNEL_SYSTEM_BUS_ADDRESS ";" UNIX_SYSTEM_BUS_ADDRESS
-#define UNIX_USER_BUS_ADDRESS_FMT "unix:path=%s/bus"
-#define KERNEL_USER_BUS_ADDRESS_FMT "kernel:path=/sys/fs/kdbus/"UID_FMT"-user/bus"
-
-#define PLYMOUTH_SOCKET { \
- .un.sun_family = AF_UNIX, \
- .un.sun_path = "\0/org/freedesktop/plymouthd", \
- }
-
-#ifndef TTY_GID
-#define TTY_GID 5
-#endif
-
-#define NOTIFY_FD_MAX 768
-#define NOTIFY_BUFFER_MAX PIPE_BUF
-
-#ifdef HAVE_SPLIT_USR
-#define _CONF_PATHS_SPLIT_USR(n) "/lib/" n "\0"
-#else
-#define _CONF_PATHS_SPLIT_USR(n)
-#endif
-
-/* Return a nulstr for a standard cascade of configuration paths,
- * suitable to pass to conf_files_list_nulstr() or config_parse_many_nulstr()
- * to implement drop-in directories for extending configuration
- * files. */
-#define CONF_PATHS_NULSTR(n) \
- "/etc/" n "\0" \
- "/run/" n "\0" \
- "/usr/local/lib/" n "\0" \
- "/usr/lib/" n "\0" \
- _CONF_PATHS_SPLIT_USR(n)
diff --git a/src/basic/device-nodes.c b/src/basic/device-nodes.c
deleted file mode 100644
index 38c0628a90..0000000000
--- a/src/basic/device-nodes.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2008-2011 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 <errno.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "device-nodes.h"
-#include "utf8.h"
-
-int whitelisted_char_for_devnode(char c, const char *white) {
-
- if ((c >= '0' && c <= '9') ||
- (c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z') ||
- strchr("#+-.:=@_", c) != NULL ||
- (white != NULL && strchr(white, c) != NULL))
- return 1;
-
- return 0;
-}
-
-int encode_devnode_name(const char *str, char *str_enc, size_t len) {
- size_t i, j;
-
- if (str == NULL || str_enc == NULL)
- return -EINVAL;
-
- for (i = 0, j = 0; str[i] != '\0'; i++) {
- int seqlen;
-
- seqlen = utf8_encoded_valid_unichar(&str[i]);
- if (seqlen > 1) {
-
- if (len-j < (size_t)seqlen)
- return -EINVAL;
-
- memcpy(&str_enc[j], &str[i], seqlen);
- j += seqlen;
- i += (seqlen-1);
-
- } else if (str[i] == '\\' || !whitelisted_char_for_devnode(str[i], NULL)) {
-
- if (len-j < 4)
- return -EINVAL;
-
- sprintf(&str_enc[j], "\\x%02x", (unsigned char) str[i]);
- j += 4;
-
- } else {
- if (len-j < 1)
- return -EINVAL;
-
- str_enc[j] = str[i];
- j++;
- }
- }
-
- if (len-j < 1)
- return -EINVAL;
-
- str_enc[j] = '\0';
- return 0;
-}
diff --git a/src/basic/device-nodes.h b/src/basic/device-nodes.h
deleted file mode 100644
index 94f385abcb..0000000000
--- a/src/basic/device-nodes.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 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 <stddef.h>
-#include <sys/types.h>
-
-int encode_devnode_name(const char *str, char *str_enc, size_t len);
-int whitelisted_char_for_devnode(char c, const char *additional);
diff --git a/src/basic/dirent-util.c b/src/basic/dirent-util.c
deleted file mode 100644
index 59067121b7..0000000000
--- a/src/basic/dirent-util.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/***
- 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 <fcntl.h>
-#include <sys/stat.h>
-
-#include "dirent-util.h"
-#include "path-util.h"
-#include "string-util.h"
-
-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;
-}
-
-bool dirent_is_file(const struct dirent *de) {
- assert(de);
-
- if (!IN_SET(de->d_type, DT_REG, DT_LNK, DT_UNKNOWN))
- return false;
-
- if (hidden_or_backup_file(de->d_name))
- return false;
-
- return true;
-}
-
-bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
- assert(de);
-
- if (!IN_SET(de->d_type, DT_REG, DT_LNK, DT_UNKNOWN))
- return false;
-
- if (de->d_name[0] == '.')
- return false;
-
- return endswith(de->d_name, suffix);
-}
diff --git a/src/basic/dirent-util.h b/src/basic/dirent-util.h
deleted file mode 100644
index b91d04908f..0000000000
--- a/src/basic/dirent-util.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#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 <dirent.h>
-#include <errno.h>
-#include <stdbool.h>
-
-#include "macro.h"
-#include "path-util.h"
-
-int dirent_ensure_type(DIR *d, struct dirent *de);
-
-bool dirent_is_file(const struct dirent *de) _pure_;
-bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_;
-
-#define FOREACH_DIRENT(de, d, on_error) \
- for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \
- if (!de) { \
- if (errno > 0) { \
- on_error; \
- } \
- break; \
- } else if (hidden_or_backup_file((de)->d_name)) \
- continue; \
- else
-
-#define FOREACH_DIRENT_ALL(de, d, on_error) \
- for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \
- if (!de) { \
- if (errno > 0) { \
- on_error; \
- } \
- break; \
- } else
diff --git a/src/basic/env-util.c b/src/basic/env-util.c
deleted file mode 100644
index b74290d6fd..0000000000
--- a/src/basic/env-util.c
+++ /dev/null
@@ -1,623 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 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 <errno.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "alloc-util.h"
-#include "env-util.h"
-#include "extract-word.h"
-#include "macro.h"
-#include "parse-util.h"
-#include "string-util.h"
-#include "strv.h"
-#include "utf8.h"
-
-#define VALID_CHARS_ENV_NAME \
- DIGITS LETTERS \
- "_"
-
-#ifndef ARG_MAX
-#define ARG_MAX ((size_t) sysconf(_SC_ARG_MAX))
-#endif
-
-static bool env_name_is_valid_n(const char *e, size_t n) {
- const char *p;
-
- if (!e)
- return false;
-
- if (n <= 0)
- return false;
-
- if (e[0] >= '0' && e[0] <= '9')
- return false;
-
- /* POSIX says the overall size of the environment block cannot
- * be > ARG_MAX, an individual assignment hence cannot be
- * either. Discounting the equal sign and trailing NUL this
- * hence leaves ARG_MAX-2 as longest possible variable
- * name. */
- if (n > ARG_MAX - 2)
- return false;
-
- for (p = e; p < e + n; p++)
- if (!strchr(VALID_CHARS_ENV_NAME, *p))
- return false;
-
- return true;
-}
-
-bool env_name_is_valid(const char *e) {
- if (!e)
- return false;
-
- return env_name_is_valid_n(e, strlen(e));
-}
-
-bool env_value_is_valid(const char *e) {
- if (!e)
- return false;
-
- if (!utf8_is_valid(e))
- return false;
-
- /* bash allows tabs in environment variables, and so should
- * we */
- if (string_has_cc(e, "\t"))
- return false;
-
- /* POSIX says the overall size of the environment block cannot
- * be > ARG_MAX, an individual assignment hence cannot be
- * either. Discounting the shortest possible variable name of
- * length 1, the equal sign and trailing NUL this hence leaves
- * ARG_MAX-3 as longest possible variable value. */
- if (strlen(e) > ARG_MAX - 3)
- return false;
-
- return true;
-}
-
-bool env_assignment_is_valid(const char *e) {
- const char *eq;
-
- eq = strchr(e, '=');
- if (!eq)
- return false;
-
- if (!env_name_is_valid_n(e, eq - e))
- return false;
-
- if (!env_value_is_valid(eq + 1))
- return false;
-
- /* POSIX says the overall size of the environment block cannot
- * be > ARG_MAX, hence the individual variable assignments
- * cannot be either, but let's leave room for one trailing NUL
- * byte. */
- if (strlen(e) > ARG_MAX - 1)
- return false;
-
- return true;
-}
-
-bool strv_env_is_valid(char **e) {
- char **p, **q;
-
- STRV_FOREACH(p, e) {
- size_t k;
-
- if (!env_assignment_is_valid(*p))
- return false;
-
- /* Check if there are duplicate assginments */
- k = strcspn(*p, "=");
- STRV_FOREACH(q, p + 1)
- if (strneq(*p, *q, k) && (*q)[k] == '=')
- return false;
- }
-
- return true;
-}
-
-bool strv_env_name_is_valid(char **l) {
- char **p, **q;
-
- STRV_FOREACH(p, l) {
- if (!env_name_is_valid(*p))
- return false;
-
- STRV_FOREACH(q, p + 1)
- if (streq(*p, *q))
- return false;
- }
-
- return true;
-}
-
-bool strv_env_name_or_assignment_is_valid(char **l) {
- char **p, **q;
-
- STRV_FOREACH(p, l) {
- if (!env_assignment_is_valid(*p) && !env_name_is_valid(*p))
- return false;
-
- STRV_FOREACH(q, p + 1)
- if (streq(*p, *q))
- return false;
- }
-
- return true;
-}
-
-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 (strneq(*j, *a, n))
- 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;
-}
-
-_pure_ 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 strneq(t, pattern, l) && 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_unset_many(char **l, ...) {
-
- char **f, **t;
-
- if (!l)
- return NULL;
-
- /* Like strv_env_unset() but applies many at once. Edits in-place. */
-
- for (f = t = l; *f; f++) {
- bool found = false;
- const char *p;
- va_list ap;
-
- va_start(ap, l);
-
- while ((p = va_arg(ap, const char*))) {
- if (env_match(*f, p)) {
- found = true;
- break;
- }
- }
-
- va_end(ap);
-
- if (found) {
- 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_n(char **l, const char *name, size_t k) {
- char **i;
-
- assert(name);
-
- if (k <= 0)
- return NULL;
-
- STRV_FOREACH(i, l)
- if (strneq(*i, name, k) &&
- (*i)[k] == '=')
- return *i + k + 1;
-
- return NULL;
-}
-
-char *strv_env_get(char **l, const char *name) {
- assert(name);
-
- return strv_env_get_n(l, name, strlen(name));
-}
-
-char **strv_env_clean_with_callback(char **e, void (*invalid_callback)(const char *p, void *userdata), void *userdata) {
- char **p, **q;
- int k = 0;
-
- STRV_FOREACH(p, e) {
- size_t n;
- bool duplicate = false;
-
- if (!env_assignment_is_valid(*p)) {
- if (invalid_callback)
- invalid_callback(*p, userdata);
- free(*p);
- continue;
- }
-
- n = strcspn(*p, "=");
- STRV_FOREACH(q, p + 1)
- if (strneq(*p, *q, n) && (*q)[n] == '=') {
- duplicate = true;
- break;
- }
-
- if (duplicate) {
- free(*p);
- continue;
- }
-
- e[k++] = *p;
- }
-
- if (e)
- e[k] = NULL;
-
- return e;
-}
-
-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 == '{') {
- k = strnappend(r, word, e-word-1);
- if (!k)
- goto fail;
-
- free(r);
- r = k;
-
- word = e-1;
- state = VARIABLE;
-
- } else if (*e == '$') {
- k = strnappend(r, word, e-word);
- if (!k)
- goto fail;
-
- free(r);
- r = k;
-
- word = e+1;
- state = WORD;
- } else
- state = WORD;
- break;
-
- case VARIABLE:
- if (*e == '}') {
- const char *t;
-
- t = strempty(strv_env_get_n(env, word+2, e-word-2));
-
- k = strappend(r, t);
- if (!k)
- goto fail;
-
- free(r);
- r = k;
-
- word = e+1;
- state = WORD;
- }
- break;
- }
- }
-
- k = strnappend(r, word, e-word);
- if (!k)
- goto fail;
-
- free(r);
- return k;
-
-fail:
- return mfree(r);
-}
-
-char **replace_env_argv(char **argv, char **env) {
- char **ret, **i;
- unsigned k = 0, l = 0;
-
- l = strv_length(argv);
-
- ret = new(char*, l+1);
- if (!ret)
- return NULL;
-
- STRV_FOREACH(i, argv) {
-
- /* If $FOO appears as single word, replace it by the split up variable */
- if ((*i)[0] == '$' && (*i)[1] != '{' && (*i)[1] != '$') {
- char *e;
- char **w, **m = NULL;
- unsigned q;
-
- e = strv_env_get(env, *i+1);
- if (e) {
- int r;
-
- r = strv_split_extract(&m, e, WHITESPACE, EXTRACT_RELAX|EXTRACT_QUOTES);
- if (r < 0) {
- ret[k] = NULL;
- strv_free(ret);
- return NULL;
- }
- } else
- m = NULL;
-
- q = strv_length(m);
- l = l + q - 1;
-
- w = realloc(ret, sizeof(char*) * (l+1));
- if (!w) {
- ret[k] = NULL;
- strv_free(ret);
- strv_free(m);
- return NULL;
- }
-
- ret = w;
- if (m) {
- memcpy(ret + 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 */
- ret[k] = replace_env(*i, env);
- if (!ret[k]) {
- strv_free(ret);
- return NULL;
- }
- k++;
- }
-
- ret[k] = NULL;
- return ret;
-}
-
-int getenv_bool(const char *p) {
- const char *e;
-
- e = getenv(p);
- if (!e)
- return -ENXIO;
-
- return parse_boolean(e);
-}
diff --git a/src/basic/env-util.h b/src/basic/env-util.h
deleted file mode 100644
index b1fef704c2..0000000000
--- a/src/basic/env-util.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 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 <stddef.h>
-
-#include "macro.h"
-
-bool env_name_is_valid(const char *e);
-bool env_value_is_valid(const char *e);
-bool env_assignment_is_valid(const char *e);
-
-char *replace_env(const char *format, char **env);
-char **replace_env_argv(char **argv, char **env);
-
-bool strv_env_is_valid(char **e);
-#define strv_env_clean(l) strv_env_clean_with_callback(l, NULL, NULL)
-char **strv_env_clean_with_callback(char **l, void (*invalid_callback)(const char *p, void *userdata), void *userdata);
-
-bool strv_env_name_is_valid(char **l);
-bool strv_env_name_or_assignment_is_valid(char **l);
-
-char **strv_env_merge(unsigned n_lists, ...);
-char **strv_env_delete(char **x, unsigned n_lists, ...); /* New copy */
-
-char **strv_env_set(char **x, const char *p); /* New copy ... */
-char **strv_env_unset(char **l, const char *p); /* In place ... */
-char **strv_env_unset_many(char **l, ...) _sentinel_;
-
-char *strv_env_get_n(char **l, const char *name, size_t k) _pure_;
-char *strv_env_get(char **x, const char *n) _pure_;
-
-int getenv_bool(const char *p);
diff --git a/src/basic/errno-list.c b/src/basic/errno-list.c
deleted file mode 100644
index c6a01eec8b..0000000000
--- a/src/basic/errno-list.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 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 <string.h>
-
-#include "errno-list.h"
-#include "macro.h"
-
-static const struct errno_name* lookup_errno(register const char *str,
- register GPERF_LEN_TYPE len);
-
-#include "errno-from-name.h"
-#include "errno-to-name.h"
-
-const char *errno_to_name(int id) {
-
- if (id < 0)
- id = -id;
-
- if (id >= (int) ELEMENTSOF(errno_names))
- return NULL;
-
- return errno_names[id];
-}
-
-int errno_from_name(const char *name) {
- const struct errno_name *sc;
-
- assert(name);
-
- sc = lookup_errno(name, strlen(name));
- if (!sc)
- return -EINVAL;
-
- assert(sc->id > 0);
- return sc->id;
-}
-
-int errno_max(void) {
- return ELEMENTSOF(errno_names);
-}
diff --git a/src/basic/errno-list.h b/src/basic/errno-list.h
deleted file mode 100644
index 4eec0cc786..0000000000
--- a/src/basic/errno-list.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 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/>.
-***/
-
-const char *errno_to_name(int id);
-int errno_from_name(const char *name);
-
-int errno_max(void);
diff --git a/src/basic/escape.c b/src/basic/escape.c
deleted file mode 100644
index 4a1ec4505e..0000000000
--- a/src/basic/escape.c
+++ /dev/null
@@ -1,502 +0,0 @@
-/***
- 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 <stdlib.h>
-#include <string.h>
-
-#include "alloc-util.h"
-#include "escape.h"
-#include "hexdecoct.h"
-#include "macro.h"
-#include "utf8.h"
-
-size_t cescape_char(char c, char *buf) {
- char * buf_old = buf;
-
- switch (c) {
-
- case '\a':
- *(buf++) = '\\';
- *(buf++) = 'a';
- break;
- case '\b':
- *(buf++) = '\\';
- *(buf++) = 'b';
- break;
- case '\f':
- *(buf++) = '\\';
- *(buf++) = 'f';
- break;
- case '\n':
- *(buf++) = '\\';
- *(buf++) = 'n';
- break;
- case '\r':
- *(buf++) = '\\';
- *(buf++) = 'r';
- break;
- case '\t':
- *(buf++) = '\\';
- *(buf++) = 't';
- break;
- case '\v':
- *(buf++) = '\\';
- *(buf++) = 'v';
- break;
- case '\\':
- *(buf++) = '\\';
- *(buf++) = '\\';
- break;
- case '"':
- *(buf++) = '\\';
- *(buf++) = '"';
- break;
- case '\'':
- *(buf++) = '\\';
- *(buf++) = '\'';
- break;
-
- default:
- /* For special chars we prefer octal over
- * hexadecimal encoding, simply because glib's
- * g_strescape() does the same */
- if ((c < ' ') || (c >= 127)) {
- *(buf++) = '\\';
- *(buf++) = octchar((unsigned char) c >> 6);
- *(buf++) = octchar((unsigned char) c >> 3);
- *(buf++) = octchar((unsigned char) c);
- } else
- *(buf++) = c;
- break;
- }
-
- return buf - buf_old;
-}
-
-char *cescape_length(const char *s, size_t n) {
- const char *f;
- char *r, *t;
-
- assert(s || n == 0);
-
- /* Does C style string escaping. May be reversed with
- * cunescape(). */
-
- r = new(char, n*4 + 1);
- if (!r)
- return NULL;
-
- for (f = s, t = r; f < s + n; f++)
- t += cescape_char(*f, t);
-
- *t = 0;
-
- return r;
-}
-
-char *cescape(const char *s) {
- assert(s);
-
- return cescape_length(s, strlen(s));
-}
-
-int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit) {
- int r = 1;
-
- assert(p);
- assert(*p);
- assert(ret);
-
- /* Unescapes C style. Returns the unescaped character in ret.
- * Sets *eight_bit to true if the escaped sequence either fits in
- * one byte in UTF-8 or is a non-unicode literal byte and should
- * instead be copied directly.
- */
-
- if (length != (size_t) -1 && length < 1)
- return -EINVAL;
-
- switch (p[0]) {
-
- case 'a':
- *ret = '\a';
- break;
- case 'b':
- *ret = '\b';
- break;
- case 'f':
- *ret = '\f';
- break;
- case 'n':
- *ret = '\n';
- break;
- case 'r':
- *ret = '\r';
- break;
- case 't':
- *ret = '\t';
- break;
- case 'v':
- *ret = '\v';
- break;
- case '\\':
- *ret = '\\';
- break;
- case '"':
- *ret = '"';
- break;
- case '\'':
- *ret = '\'';
- break;
-
- case 's':
- /* This is an extension of the XDG syntax files */
- *ret = ' ';
- break;
-
- case 'x': {
- /* hexadecimal encoding */
- int a, b;
-
- if (length != (size_t) -1 && length < 3)
- return -EINVAL;
-
- a = unhexchar(p[1]);
- if (a < 0)
- return -EINVAL;
-
- b = unhexchar(p[2]);
- if (b < 0)
- return -EINVAL;
-
- /* Don't allow NUL bytes */
- if (a == 0 && b == 0)
- return -EINVAL;
-
- *ret = (a << 4U) | b;
- *eight_bit = true;
- r = 3;
- break;
- }
-
- case 'u': {
- /* C++11 style 16bit unicode */
-
- int a[4];
- unsigned i;
- uint32_t c;
-
- if (length != (size_t) -1 && length < 5)
- return -EINVAL;
-
- for (i = 0; i < 4; i++) {
- a[i] = unhexchar(p[1 + i]);
- if (a[i] < 0)
- return a[i];
- }
-
- c = ((uint32_t) a[0] << 12U) | ((uint32_t) a[1] << 8U) | ((uint32_t) a[2] << 4U) | (uint32_t) a[3];
-
- /* Don't allow 0 chars */
- if (c == 0)
- return -EINVAL;
-
- *ret = c;
- r = 5;
- break;
- }
-
- case 'U': {
- /* C++11 style 32bit unicode */
-
- int a[8];
- unsigned i;
- char32_t c;
-
- if (length != (size_t) -1 && length < 9)
- return -EINVAL;
-
- for (i = 0; i < 8; i++) {
- a[i] = unhexchar(p[1 + i]);
- if (a[i] < 0)
- return a[i];
- }
-
- c = ((uint32_t) a[0] << 28U) | ((uint32_t) a[1] << 24U) | ((uint32_t) a[2] << 20U) | ((uint32_t) a[3] << 16U) |
- ((uint32_t) a[4] << 12U) | ((uint32_t) a[5] << 8U) | ((uint32_t) a[6] << 4U) | (uint32_t) a[7];
-
- /* Don't allow 0 chars */
- if (c == 0)
- return -EINVAL;
-
- /* Don't allow invalid code points */
- if (!unichar_is_valid(c))
- return -EINVAL;
-
- *ret = c;
- r = 9;
- break;
- }
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7': {
- /* octal encoding */
- int a, b, c;
- char32_t m;
-
- if (length != (size_t) -1 && length < 3)
- return -EINVAL;
-
- a = unoctchar(p[0]);
- if (a < 0)
- return -EINVAL;
-
- b = unoctchar(p[1]);
- if (b < 0)
- return -EINVAL;
-
- c = unoctchar(p[2]);
- if (c < 0)
- return -EINVAL;
-
- /* don't allow NUL bytes */
- if (a == 0 && b == 0 && c == 0)
- return -EINVAL;
-
- /* Don't allow bytes above 255 */
- m = ((uint32_t) a << 6U) | ((uint32_t) b << 3U) | (uint32_t) c;
- if (m > 255)
- return -EINVAL;
-
- *ret = m;
- *eight_bit = true;
- r = 3;
- break;
- }
-
- default:
- return -EINVAL;
- }
-
- return r;
-}
-
-int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret) {
- char *r, *t;
- const char *f;
- size_t pl;
-
- assert(s);
- assert(ret);
-
- /* Undoes C style string escaping, and optionally prefixes it. */
-
- pl = prefix ? strlen(prefix) : 0;
-
- r = new(char, pl+length+1);
- if (!r)
- return -ENOMEM;
-
- if (prefix)
- memcpy(r, prefix, pl);
-
- for (f = s, t = r + pl; f < s + length; f++) {
- size_t remaining;
- bool eight_bit = false;
- char32_t u;
- int k;
-
- remaining = s + length - f;
- assert(remaining > 0);
-
- if (*f != '\\') {
- /* A literal, copy verbatim */
- *(t++) = *f;
- continue;
- }
-
- if (remaining == 1) {
- if (flags & UNESCAPE_RELAX) {
- /* A trailing backslash, copy verbatim */
- *(t++) = *f;
- continue;
- }
-
- free(r);
- return -EINVAL;
- }
-
- k = cunescape_one(f + 1, remaining - 1, &u, &eight_bit);
- if (k < 0) {
- if (flags & UNESCAPE_RELAX) {
- /* Invalid escape code, let's take it literal then */
- *(t++) = '\\';
- continue;
- }
-
- free(r);
- return k;
- }
-
- f += k;
- if (eight_bit)
- /* One byte? Set directly as specified */
- *(t++) = u;
- else
- /* Otherwise encode as multi-byte UTF-8 */
- t += utf8_encode_unichar(t, u);
- }
-
- *t = 0;
-
- *ret = r;
- return t - r;
-}
-
-int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret) {
- return cunescape_length_with_prefix(s, length, NULL, flags, ret);
-}
-
-int cunescape(const char *s, UnescapeFlags flags, char **ret) {
- return cunescape_length(s, strlen(s), flags, ret);
-}
-
-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 *octescape(const char *s, size_t len) {
- char *r, *t;
- const char *f;
-
- /* Escapes all chars in bad, in addition to \ and " chars,
- * in \nnn style escaping. */
-
- r = new(char, len * 4 + 1);
- if (!r)
- return NULL;
-
- for (f = s, t = r; f < s + len; f++) {
-
- if (*f < ' ' || *f >= 127 || *f == '\\' || *f == '"') {
- *(t++) = '\\';
- *(t++) = '0' + (*f >> 6);
- *(t++) = '0' + ((*f >> 3) & 8);
- *(t++) = '0' + (*f & 8);
- } else
- *(t++) = *f;
- }
-
- *t = 0;
-
- return r;
-
-}
-
-static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
- assert(bad);
-
- for (; *s; s++) {
- if (*s == '\\' || strchr(bad, *s))
- *(t++) = '\\';
-
- *(t++) = *s;
- }
-
- return t;
-}
-
-char *shell_escape(const char *s, const char *bad) {
- char *r, *t;
-
- r = new(char, strlen(s)*2+1);
- if (!r)
- return NULL;
-
- t = strcpy_backslash_escaped(r, s, bad);
- *t = 0;
-
- return r;
-}
-
-char *shell_maybe_quote(const char *s) {
- const char *p;
- char *r, *t;
-
- assert(s);
-
- /* Encloses a string in double quotes if necessary to make it
- * OK as shell string. */
-
- for (p = s; *p; p++)
- if (*p <= ' ' ||
- *p >= 127 ||
- strchr(SHELL_NEED_QUOTES, *p))
- break;
-
- if (!*p)
- return strdup(s);
-
- r = new(char, 1+strlen(s)*2+1+1);
- if (!r)
- return NULL;
-
- t = r;
- *(t++) = '"';
- t = mempcpy(t, s, p - s);
-
- t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE);
-
- *(t++)= '"';
- *t = 0;
-
- return r;
-}
diff --git a/src/basic/escape.h b/src/basic/escape.h
deleted file mode 100644
index deaa4def28..0000000000
--- a/src/basic/escape.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#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 <stddef.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <uchar.h>
-
-#include "string-util.h"
-#include "missing.h"
-
-/* What characters are special in the shell? */
-/* must be escaped outside and inside double-quotes */
-#define SHELL_NEED_ESCAPE "\"\\`$"
-/* can be escaped or double-quoted */
-#define SHELL_NEED_QUOTES SHELL_NEED_ESCAPE GLOB_CHARS "'()<>|&;"
-
-typedef enum UnescapeFlags {
- UNESCAPE_RELAX = 1,
-} UnescapeFlags;
-
-char *cescape(const char *s);
-char *cescape_length(const char *s, size_t n);
-size_t cescape_char(char c, char *buf);
-
-int cunescape(const char *s, UnescapeFlags flags, char **ret);
-int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret);
-int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret);
-int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit);
-
-char *xescape(const char *s, const char *bad);
-char *octescape(const char *s, size_t len);
-
-char *shell_escape(const char *s, const char *bad);
-char *shell_maybe_quote(const char *s);
diff --git a/src/basic/ether-addr-util.c b/src/basic/ether-addr-util.c
deleted file mode 100644
index 5697e8d132..0000000000
--- a/src/basic/ether-addr-util.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen
-
- 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 <net/ethernet.h>
-#include <stdio.h>
-#include <sys/types.h>
-
-#include "ether-addr-util.h"
-#include "macro.h"
-#include "string-util.h"
-
-char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]) {
- assert(addr);
- assert(buffer);
-
- /* Like ether_ntoa() but uses %02x instead of %x to print
- * ethernet addresses, which makes them look less funny. Also,
- * doesn't use a static buffer. */
-
- sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x",
- addr->ether_addr_octet[0],
- addr->ether_addr_octet[1],
- addr->ether_addr_octet[2],
- addr->ether_addr_octet[3],
- addr->ether_addr_octet[4],
- addr->ether_addr_octet[5]);
-
- return buffer;
-}
-
-bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) {
- assert(a);
- assert(b);
-
- return a->ether_addr_octet[0] == b->ether_addr_octet[0] &&
- a->ether_addr_octet[1] == b->ether_addr_octet[1] &&
- a->ether_addr_octet[2] == b->ether_addr_octet[2] &&
- a->ether_addr_octet[3] == b->ether_addr_octet[3] &&
- a->ether_addr_octet[4] == b->ether_addr_octet[4] &&
- a->ether_addr_octet[5] == b->ether_addr_octet[5];
-}
-
-int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset) {
- size_t pos = 0, n, field;
- char sep = '\0';
- const char *hex = HEXDIGITS, *hexoff;
- size_t x;
- bool touched;
-
-#define parse_fields(v) \
- for (field = 0; field < ELEMENTSOF(v); field++) { \
- touched = false; \
- for (n = 0; n < (2 * sizeof(v[0])); n++) { \
- if (s[pos] == '\0') \
- break; \
- hexoff = strchr(hex, s[pos]); \
- if (hexoff == NULL) \
- break; \
- assert(hexoff >= hex); \
- x = hexoff - hex; \
- if (x >= 16) \
- x -= 6; /* A-F */ \
- assert(x < 16); \
- touched = true; \
- v[field] <<= 4; \
- v[field] += x; \
- pos++; \
- } \
- if (!touched) \
- return -EINVAL; \
- if (field < (ELEMENTSOF(v)-1)) { \
- if (s[pos] != sep) \
- return -EINVAL; \
- else \
- pos++; \
- } \
- }
-
- assert(s);
- assert(ret);
-
- sep = s[strspn(s, hex)];
- if (sep == '\n')
- return -EINVAL;
- if (strchr(":.-", sep) == NULL)
- return -EINVAL;
-
- if (sep == '.') {
- uint16_t shorts[3] = { 0 };
-
- parse_fields(shorts);
-
- for (n = 0; n < ELEMENTSOF(shorts); n++) {
- ret->ether_addr_octet[2*n] = ((shorts[n] & (uint16_t)0xff00) >> 8);
- ret->ether_addr_octet[2*n + 1] = (shorts[n] & (uint16_t)0x00ff);
- }
- } else {
- struct ether_addr out = { .ether_addr_octet = { 0 } };
-
- parse_fields(out.ether_addr_octet);
-
- for (n = 0; n < ELEMENTSOF(out.ether_addr_octet); n++)
- ret->ether_addr_octet[n] = out.ether_addr_octet[n];
- }
-
- if (offset)
- *offset = pos;
- return 0;
-}
diff --git a/src/basic/ether-addr-util.h b/src/basic/ether-addr-util.h
deleted file mode 100644
index 74e125a95f..0000000000
--- a/src/basic/ether-addr-util.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen
-
- 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 <net/ethernet.h>
-#include <stdbool.h>
-
-#define ETHER_ADDR_FORMAT_STR "%02X%02X%02X%02X%02X%02X"
-#define ETHER_ADDR_FORMAT_VAL(x) (x).ether_addr_octet[0], (x).ether_addr_octet[1], (x).ether_addr_octet[2], (x).ether_addr_octet[3], (x).ether_addr_octet[4], (x).ether_addr_octet[5]
-
-#define ETHER_ADDR_TO_STRING_MAX (3*6)
-char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]);
-
-bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b);
-
-#define ETHER_ADDR_NULL ((const struct ether_addr){})
-
-static inline bool ether_addr_is_null(const struct ether_addr *addr) {
- return ether_addr_equal(addr, &ETHER_ADDR_NULL);
-}
-
-int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset);
diff --git a/src/basic/exit-status.c b/src/basic/exit-status.c
deleted file mode 100644
index 59557f8afe..0000000000
--- a/src/basic/exit-status.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/***
- 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 <signal.h>
-#include <stdlib.h>
-
-#include "exit-status.h"
-#include "macro.h"
-#include "set.h"
-
-const char* exit_status_to_string(int 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 (status) {
-
- case EXIT_SUCCESS:
- return "SUCCESS";
-
- case EXIT_FAILURE:
- return "FAILURE";
- }
-
- if (IN_SET(level, EXIT_STATUS_SYSTEMD, EXIT_STATUS_LSB)) {
- switch (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_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";
-
- case EXIT_SELINUX_CONTEXT:
- return "SELINUX_CONTEXT";
-
- case EXIT_PERSONALITY:
- return "PERSONALITY";
-
- case EXIT_APPARMOR_PROFILE:
- return "APPARMOR";
-
- case EXIT_ADDRESS_FAMILIES:
- return "ADDRESS_FAMILIES";
-
- case EXIT_RUNTIME_DIRECTORY:
- return "RUNTIME_DIRECTORY";
-
- case EXIT_MAKE_STARTER:
- return "MAKE_STARTER";
-
- case EXIT_CHOWN:
- return "CHOWN";
-
- case EXIT_SMACK_PROCESS_LABEL:
- return "SMACK_PROCESS_LABEL";
- }
- }
-
- if (level == EXIT_STATUS_LSB) {
- switch (status) {
-
- case EXIT_INVALIDARGUMENT:
- return "INVALIDARGUMENT";
-
- case EXIT_NOTIMPLEMENTED:
- return "NOTIMPLEMENTED";
-
- case EXIT_NOPERMISSION:
- return "NOPERMISSION";
-
- case EXIT_NOTINSTALLED:
- return "NOTINSTALLED";
-
- case EXIT_NOTCONFIGURED:
- return "NOTCONFIGURED";
-
- case EXIT_NOTRUNNING:
- return "NOTRUNNING";
- }
- }
-
- return NULL;
-}
-
-bool is_clean_exit(int code, int status, ExitClean clean, ExitStatusSet *success_status) {
-
- if (code == CLD_EXITED)
- return status == 0 ||
- (success_status &&
- set_contains(success_status->status, 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
- (clean == EXIT_CLEAN_DAEMON && IN_SET(status, SIGHUP, SIGINT, SIGTERM, SIGPIPE)) ||
- (success_status &&
- set_contains(success_status->signal, INT_TO_PTR(status)));
-
- return false;
-}
-
-void exit_status_set_free(ExitStatusSet *x) {
- assert(x);
-
- x->status = set_free(x->status);
- x->signal = set_free(x->signal);
-}
-
-bool exit_status_set_is_empty(ExitStatusSet *x) {
- if (!x)
- return true;
-
- return set_isempty(x->status) && set_isempty(x->signal);
-}
-
-bool exit_status_set_test(ExitStatusSet *x, int code, int status) {
-
- if (exit_status_set_is_empty(x))
- return false;
-
- if (code == CLD_EXITED && set_contains(x->status, INT_TO_PTR(status)))
- return true;
-
- if (IN_SET(code, CLD_KILLED, CLD_DUMPED) && set_contains(x->signal, INT_TO_PTR(status)))
- return true;
-
- return false;
-}
diff --git a/src/basic/exit-status.h b/src/basic/exit-status.h
deleted file mode 100644
index 0cfdfd7891..0000000000
--- a/src/basic/exit-status.h
+++ /dev/null
@@ -1,110 +0,0 @@
-#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 "hashmap.h"
-#include "macro.h"
-#include "set.h"
-
-/* This defines pretty names for the LSB 'start' verb exit codes. Note that they shouldn't be confused with the LSB
- * 'status' verb exit codes which are defined very differently. For details see:
- *
- * https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
- */
-
-enum {
- /* 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. */
-
- 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_RESERVED, /* used to be tcpwrap, don't reuse! */
- EXIT_PAM,
- EXIT_NETWORK,
- EXIT_NAMESPACE,
- EXIT_NO_NEW_PRIVILEGES,
- EXIT_SECCOMP,
- EXIT_SELINUX_CONTEXT,
- EXIT_PERSONALITY, /* 230 */
- EXIT_APPARMOR_PROFILE,
- EXIT_ADDRESS_FAMILIES,
- EXIT_RUNTIME_DIRECTORY,
- EXIT_MAKE_STARTER,
- EXIT_CHOWN,
- EXIT_SMACK_PROCESS_LABEL,
-};
-
-typedef enum ExitStatusLevel {
- EXIT_STATUS_MINIMAL, /* only cover libc EXIT_STATUS/EXIT_FAILURE */
- EXIT_STATUS_SYSTEMD, /* cover libc and systemd's own exit codes */
- EXIT_STATUS_LSB, /* cover libc, systemd's own and LSB exit codes */
- EXIT_STATUS_FULL = EXIT_STATUS_LSB
-} ExitStatusLevel;
-
-typedef struct ExitStatusSet {
- Set *status;
- Set *signal;
-} ExitStatusSet;
-
-const char* exit_status_to_string(int status, ExitStatusLevel level) _const_;
-
-typedef enum ExitClean {
- EXIT_CLEAN_DAEMON,
- EXIT_CLEAN_COMMAND,
-} ExitClean;
-
-bool is_clean_exit(int code, int status, ExitClean clean, ExitStatusSet *success_status);
-
-void exit_status_set_free(ExitStatusSet *x);
-bool exit_status_set_is_empty(ExitStatusSet *x);
-bool exit_status_set_test(ExitStatusSet *x, int code, int status);
diff --git a/src/basic/extract-word.c b/src/basic/extract-word.c
deleted file mode 100644
index d6c1228463..0000000000
--- a/src/basic/extract-word.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/***
- 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 <stdarg.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-
-#include "alloc-util.h"
-#include "escape.h"
-#include "extract-word.h"
-#include "log.h"
-#include "macro.h"
-#include "string-util.h"
-#include "utf8.h"
-
-int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) {
- _cleanup_free_ char *s = NULL;
- size_t allocated = 0, sz = 0;
- char c;
- int r;
-
- char quote = 0; /* 0 or ' or " */
- bool backslash = false; /* whether we've just seen a backslash */
-
- assert(p);
- assert(ret);
-
- /* Bail early if called after last value or with no input */
- if (!*p)
- goto finish_force_terminate;
- c = **p;
-
- if (!separators)
- separators = WHITESPACE;
-
- /* Parses the first word of a string, and returns it in
- * *ret. Removes all quotes in the process. When parsing fails
- * (because of an uneven number of quotes or similar), leaves
- * the pointer *p at the first invalid character. */
-
- if (flags & EXTRACT_DONT_COALESCE_SEPARATORS)
- if (!GREEDY_REALLOC(s, allocated, sz+1))
- return -ENOMEM;
-
- for (;; (*p)++, c = **p) {
- if (c == 0)
- goto finish_force_terminate;
- else if (strchr(separators, c)) {
- if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
- (*p)++;
- goto finish_force_next;
- }
- } else {
- /* We found a non-blank character, so we will always
- * want to return a string (even if it is empty),
- * allocate it here. */
- if (!GREEDY_REALLOC(s, allocated, sz+1))
- return -ENOMEM;
- break;
- }
- }
-
- for (;; (*p)++, c = **p) {
- if (backslash) {
- if (!GREEDY_REALLOC(s, allocated, sz+7))
- return -ENOMEM;
-
- if (c == 0) {
- if ((flags & EXTRACT_CUNESCAPE_RELAX) &&
- (!quote || flags & EXTRACT_RELAX)) {
- /* If we find an unquoted trailing backslash and we're in
- * EXTRACT_CUNESCAPE_RELAX mode, keep it verbatim in the
- * output.
- *
- * Unbalanced quotes will only be allowed in EXTRACT_RELAX
- * mode, EXTRACT_CUNESCAPE_RELAX mode does not allow them.
- */
- s[sz++] = '\\';
- goto finish_force_terminate;
- }
- if (flags & EXTRACT_RELAX)
- goto finish_force_terminate;
- return -EINVAL;
- }
-
- if (flags & EXTRACT_CUNESCAPE) {
- bool eight_bit = false;
- char32_t u;
-
- r = cunescape_one(*p, (size_t) -1, &u, &eight_bit);
- if (r < 0) {
- if (flags & EXTRACT_CUNESCAPE_RELAX) {
- s[sz++] = '\\';
- s[sz++] = c;
- } else
- return -EINVAL;
- } else {
- (*p) += r - 1;
-
- if (eight_bit)
- s[sz++] = u;
- else
- sz += utf8_encode_unichar(s + sz, u);
- }
- } else
- s[sz++] = c;
-
- backslash = false;
-
- } else if (quote) { /* inside either single or double quotes */
- for (;; (*p)++, c = **p) {
- if (c == 0) {
- if (flags & EXTRACT_RELAX)
- goto finish_force_terminate;
- return -EINVAL;
- } else if (c == quote) { /* found the end quote */
- quote = 0;
- break;
- } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
- backslash = true;
- break;
- } else {
- if (!GREEDY_REALLOC(s, allocated, sz+2))
- return -ENOMEM;
-
- s[sz++] = c;
- }
- }
-
- } else {
- for (;; (*p)++, c = **p) {
- if (c == 0)
- goto finish_force_terminate;
- else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES)) {
- quote = c;
- break;
- } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
- backslash = true;
- break;
- } else if (strchr(separators, c)) {
- if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
- (*p)++;
- goto finish_force_next;
- }
- /* Skip additional coalesced separators. */
- for (;; (*p)++, c = **p) {
- if (c == 0)
- goto finish_force_terminate;
- if (!strchr(separators, c))
- break;
- }
- goto finish;
-
- } else {
- if (!GREEDY_REALLOC(s, allocated, sz+2))
- return -ENOMEM;
-
- s[sz++] = c;
- }
- }
- }
- }
-
-finish_force_terminate:
- *p = NULL;
-finish:
- if (!s) {
- *p = NULL;
- *ret = NULL;
- return 0;
- }
-
-finish_force_next:
- s[sz] = 0;
- *ret = s;
- s = NULL;
-
- return 1;
-}
-
-int extract_first_word_and_warn(
- const char **p,
- char **ret,
- const char *separators,
- ExtractFlags flags,
- const char *unit,
- const char *filename,
- unsigned line,
- const char *rvalue) {
-
- /* Try to unquote it, if it fails, warn about it and try again
- * but this time using EXTRACT_CUNESCAPE_RELAX to keep the
- * backslashes verbatim in invalid escape sequences. */
-
- const char *save;
- int r;
-
- save = *p;
- r = extract_first_word(p, ret, separators, flags);
- if (r >= 0)
- return r;
-
- if (r == -EINVAL && !(flags & EXTRACT_CUNESCAPE_RELAX)) {
-
- /* Retry it with EXTRACT_CUNESCAPE_RELAX. */
- *p = save;
- r = extract_first_word(p, ret, separators, flags|EXTRACT_CUNESCAPE_RELAX);
- if (r >= 0) {
- /* It worked this time, hence it must have been an invalid escape sequence we could correct. */
- log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "Invalid escape sequences in line, correcting: \"%s\"", rvalue);
- return r;
- }
-
- /* If it's still EINVAL; then it must be unbalanced quoting, report this. */
- if (r == -EINVAL)
- return log_syntax(unit, LOG_ERR, filename, line, r, "Unbalanced quoting, ignoring: \"%s\"", rvalue);
- }
-
- /* Can be any error, report it */
- return log_syntax(unit, LOG_ERR, filename, line, r, "Unable to decode word \"%s\", ignoring: %m", rvalue);
-}
-
-int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) {
- va_list ap;
- char **l;
- int n = 0, i, c, r;
-
- /* Parses a number of words from a string, stripping any
- * quotes if necessary. */
-
- assert(p);
-
- /* Count how many words are expected */
- va_start(ap, flags);
- for (;;) {
- if (!va_arg(ap, char **))
- break;
- n++;
- }
- va_end(ap);
-
- if (n <= 0)
- return 0;
-
- /* Read all words into a temporary array */
- l = newa0(char*, n);
- for (c = 0; c < n; c++) {
-
- r = extract_first_word(p, &l[c], separators, flags);
- if (r < 0) {
- int j;
-
- for (j = 0; j < c; j++)
- free(l[j]);
-
- return r;
- }
-
- if (r == 0)
- break;
- }
-
- /* If we managed to parse all words, return them in the passed
- * in parameters */
- va_start(ap, flags);
- for (i = 0; i < n; i++) {
- char **v;
-
- v = va_arg(ap, char **);
- assert(v);
-
- *v = l[i];
- }
- va_end(ap);
-
- return c;
-}
diff --git a/src/basic/extract-word.h b/src/basic/extract-word.h
deleted file mode 100644
index 21db5ef33f..0000000000
--- a/src/basic/extract-word.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#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 "macro.h"
-
-typedef enum ExtractFlags {
- EXTRACT_RELAX = 1,
- EXTRACT_CUNESCAPE = 2,
- EXTRACT_CUNESCAPE_RELAX = 4,
- EXTRACT_QUOTES = 8,
- EXTRACT_DONT_COALESCE_SEPARATORS = 16,
- EXTRACT_RETAIN_ESCAPE = 32,
-} ExtractFlags;
-
-int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags);
-int extract_first_word_and_warn(const char **p, char **ret, const char *separators, ExtractFlags flags, const char *unit, const char *filename, unsigned line, const char *rvalue);
-int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) _sentinel_;
diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c
deleted file mode 100644
index 5c820332a5..0000000000
--- a/src/basic/fd-util.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/***
- 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 <fcntl.h>
-#include <sys/resource.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include "fd-util.h"
-#include "fs-util.h"
-#include "macro.h"
-#include "missing.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "socket-util.h"
-#include "stdio-util.h"
-#include "util.h"
-
-int close_nointr(int fd) {
- assert(fd >= 0);
-
- if (close(fd) >= 0)
- return 0;
-
- /*
- * Just ignore EINTR; a retry loop is the wrong thing to do on
- * Linux.
- *
- * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
- * https://bugzilla.gnome.org/show_bug.cgi?id=682819
- * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
- * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
- */
- if (errno == EINTR)
- return 0;
-
- return -errno;
-}
-
-int safe_close(int fd) {
-
- /*
- * Like close_nointr() but cannot fail. Guarantees errno is
- * unchanged. Is a NOP with negative fds passed, and returns
- * -1, so that it can be used in this syntax:
- *
- * fd = safe_close(fd);
- */
-
- if (fd >= 0) {
- PROTECT_ERRNO;
-
- /* The kernel might return pretty much any error code
- * via close(), but the fd will be closed anyway. The
- * only condition we want to check for here is whether
- * the fd was invalid at all... */
-
- assert_se(close_nointr(fd) != -EBADF);
- }
-
- return -1;
-}
-
-void safe_close_pair(int p[]) {
- assert(p);
-
- if (p[0] == p[1]) {
- /* Special case pairs which use the same fd in both
- * directions... */
- p[0] = p[1] = safe_close(p[0]);
- return;
- }
-
- p[0] = safe_close(p[0]);
- p[1] = safe_close(p[1]);
-}
-
-void close_many(const int fds[], unsigned n_fd) {
- unsigned i;
-
- assert(fds || n_fd <= 0);
-
- for (i = 0; i < n_fd; i++)
- safe_close(fds[i]);
-}
-
-int fclose_nointr(FILE *f) {
- assert(f);
-
- /* Same as close_nointr(), but for fclose() */
-
- if (fclose(f) == 0)
- return 0;
-
- if (errno == EINTR)
- return 0;
-
- return -errno;
-}
-
-FILE* safe_fclose(FILE *f) {
-
- /* Same as safe_close(), but for fclose() */
-
- if (f) {
- PROTECT_ERRNO;
-
- assert_se(fclose_nointr(f) != EBADF);
- }
-
- return NULL;
-}
-
-DIR* safe_closedir(DIR *d) {
-
- if (d) {
- PROTECT_ERRNO;
-
- assert_se(closedir(d) >= 0 || errno != EBADF);
- }
-
- return NULL;
-}
-
-int fd_nonblock(int fd, bool nonblock) {
- int flags, nflags;
-
- assert(fd >= 0);
-
- flags = fcntl(fd, F_GETFL, 0);
- if (flags < 0)
- return -errno;
-
- if (nonblock)
- nflags = flags | O_NONBLOCK;
- else
- nflags = flags & ~O_NONBLOCK;
-
- if (nflags == flags)
- return 0;
-
- if (fcntl(fd, F_SETFL, nflags) < 0)
- return -errno;
-
- return 0;
-}
-
-int fd_cloexec(int fd, bool cloexec) {
- int flags, nflags;
-
- assert(fd >= 0);
-
- flags = fcntl(fd, F_GETFD, 0);
- if (flags < 0)
- return -errno;
-
- if (cloexec)
- nflags = flags | FD_CLOEXEC;
- else
- nflags = flags & ~FD_CLOEXEC;
-
- if (nflags == flags)
- return 0;
-
- if (fcntl(fd, F_SETFD, nflags) < 0)
- return -errno;
-
- return 0;
-}
-
-void stdio_unset_cloexec(void) {
- fd_cloexec(STDIN_FILENO, false);
- fd_cloexec(STDOUT_FILENO, false);
- fd_cloexec(STDERR_FILENO, false);
-}
-
-_pure_ 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) {
- _cleanup_closedir_ DIR *d = NULL;
- 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 (hidden_or_backup_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;
- }
- }
-
- return r;
-}
-
-int same_fd(int a, int b) {
- struct stat sta, stb;
- pid_t pid;
- int r, fa, fb;
-
- assert(a >= 0);
- assert(b >= 0);
-
- /* Compares two file descriptors. Note that semantics are
- * quite different depending on whether we have kcmp() or we
- * don't. If we have kcmp() this will only return true for
- * dup()ed file descriptors, but not otherwise. If we don't
- * have kcmp() this will also return true for two fds of the same
- * file, created by separate open() calls. Since we use this
- * call mostly for filtering out duplicates in the fd store
- * this difference hopefully doesn't matter too much. */
-
- if (a == b)
- return true;
-
- /* Try to use kcmp() if we have it. */
- pid = getpid();
- r = kcmp(pid, pid, KCMP_FILE, a, b);
- if (r == 0)
- return true;
- if (r > 0)
- return false;
- if (errno != ENOSYS)
- return -errno;
-
- /* We don't have kcmp(), use fstat() instead. */
- if (fstat(a, &sta) < 0)
- return -errno;
-
- if (fstat(b, &stb) < 0)
- return -errno;
-
- if ((sta.st_mode & S_IFMT) != (stb.st_mode & S_IFMT))
- return false;
-
- /* We consider all device fds different, since two device fds
- * might refer to quite different device contexts even though
- * they share the same inode and backing dev_t. */
-
- if (S_ISCHR(sta.st_mode) || S_ISBLK(sta.st_mode))
- return false;
-
- if (sta.st_dev != stb.st_dev || sta.st_ino != stb.st_ino)
- return false;
-
- /* The fds refer to the same inode on disk, let's also check
- * if they have the same fd flags. This is useful to
- * distinguish the read and write side of a pipe created with
- * pipe(). */
- fa = fcntl(a, F_GETFL);
- if (fa < 0)
- return -errno;
-
- fb = fcntl(b, F_GETFL);
- if (fb < 0)
- return -errno;
-
- return fa == fb;
-}
-
-void cmsg_close_all(struct msghdr *mh) {
- struct cmsghdr *cmsg;
-
- assert(mh);
-
- CMSG_FOREACH(cmsg, mh)
- if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
- close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int));
-}
-
-bool fdname_is_valid(const char *s) {
- const char *p;
-
- /* Validates a name for $LISTEN_FDNAMES. We basically allow
- * everything ASCII that's not a control character. Also, as
- * special exception the ":" character is not allowed, as we
- * use that as field separator in $LISTEN_FDNAMES.
- *
- * Note that the empty string is explicitly allowed
- * here. However, we limit the length of the names to 255
- * characters. */
-
- if (!s)
- return false;
-
- for (p = s; *p; p++) {
- if (*p < ' ')
- return false;
- if (*p >= 127)
- return false;
- if (*p == ':')
- return false;
- }
-
- return p - s < 256;
-}
-
-int fd_get_path(int fd, char **ret) {
- char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
- int r;
-
- xsprintf(procfs_path, "/proc/self/fd/%i", fd);
-
- r = readlink_malloc(procfs_path, ret);
-
- if (r == -ENOENT) /* If the file doesn't exist the fd is invalid */
- return -EBADF;
-
- return r;
-}
diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h
deleted file mode 100644
index 34b98d4aec..0000000000
--- a/src/basic/fd-util.h
+++ /dev/null
@@ -1,80 +0,0 @@
-#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 <dirent.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <sys/socket.h>
-
-#include "macro.h"
-
-/* Make sure we can distinguish fd 0 and NULL */
-#define FD_TO_PTR(fd) INT_TO_PTR((fd)+1)
-#define PTR_TO_FD(p) (PTR_TO_INT(p)-1)
-
-int close_nointr(int fd);
-int safe_close(int fd);
-void safe_close_pair(int p[]);
-
-void close_many(const int fds[], unsigned n_fd);
-
-int fclose_nointr(FILE *f);
-FILE* safe_fclose(FILE *f);
-DIR* safe_closedir(DIR *f);
-
-static inline void closep(int *fd) {
- safe_close(*fd);
-}
-
-static inline void close_pairp(int (*p)[2]) {
- safe_close_pair(*p);
-}
-
-static inline void fclosep(FILE **f) {
- safe_fclose(*f);
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, pclose);
-DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
-
-#define _cleanup_close_ _cleanup_(closep)
-#define _cleanup_fclose_ _cleanup_(fclosep)
-#define _cleanup_pclose_ _cleanup_(pclosep)
-#define _cleanup_closedir_ _cleanup_(closedirp)
-#define _cleanup_close_pair_ _cleanup_(close_pairp)
-
-int fd_nonblock(int fd, bool nonblock);
-int fd_cloexec(int fd, bool cloexec);
-void stdio_unset_cloexec(void);
-
-int close_all_fds(const int except[], unsigned n_except);
-
-int same_fd(int a, int b);
-
-void cmsg_close_all(struct msghdr *mh);
-
-bool fdname_is_valid(const char *s);
-
-int fd_get_path(int fd, char **ret);
-
-/* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */
-#define ERRNO_IS_DISCONNECT(r) \
- IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH)
diff --git a/src/basic/fileio-label.c b/src/basic/fileio-label.c
deleted file mode 100644
index 66dbc0fe1e..0000000000
--- a/src/basic/fileio-label.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2010 Harald Hoyer
-
- 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/stat.h>
-
-#include "fileio-label.h"
-#include "fileio.h"
-#include "selinux-util.h"
-
-int write_string_file_atomic_label(const char *fn, const char *line) {
- int r;
-
- r = mac_selinux_create_file_prepare(fn, S_IFREG);
- if (r < 0)
- return r;
-
- r = write_string_file(fn, line, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
-
- mac_selinux_create_file_clear();
-
- return r;
-}
-
-int write_env_file_label(const char *fname, char **l) {
- int r;
-
- r = mac_selinux_create_file_prepare(fname, S_IFREG);
- if (r < 0)
- return r;
-
- r = write_env_file(fname, l);
-
- mac_selinux_create_file_clear();
-
- return r;
-}
-
-int fopen_temporary_label(const char *target,
- const char *path, FILE **f, char **temp_path) {
- int r;
-
- r = mac_selinux_create_file_prepare(target, S_IFREG);
- if (r < 0)
- return r;
-
- r = fopen_temporary(path, f, temp_path);
-
- mac_selinux_create_file_clear();
-
- return r;
-}
diff --git a/src/basic/fileio-label.h b/src/basic/fileio-label.h
deleted file mode 100644
index fe7543013d..0000000000
--- a/src/basic/fileio-label.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2010 Harald Hoyer
-
- 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 <stdio.h>
-
-#include "fileio.h"
-
-int write_string_file_atomic_label(const char *fn, const char *line);
-int write_env_file_label(const char *fname, char **l);
-int fopen_temporary_label(const char *target,
- const char *path, FILE **f, char **temp_path);
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
deleted file mode 100644
index 1cfb7a98f5..0000000000
--- a/src/basic/fileio.c
+++ /dev/null
@@ -1,1411 +0,0 @@
-/***
- 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 <fcntl.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "alloc-util.h"
-#include "ctype.h"
-#include "escape.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "fs-util.h"
-#include "hexdecoct.h"
-#include "log.h"
-#include "macro.h"
-#include "missing.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "random-util.h"
-#include "stdio-util.h"
-#include "string-util.h"
-#include "strv.h"
-#include "time-util.h"
-#include "umask-util.h"
-#include "utf8.h"
-
-#define READ_FULL_BYTES_MAX (4U*1024U*1024U)
-
-int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
-
- assert(f);
- assert(line);
-
- fputs(line, f);
- if (enforce_newline && !endswith(line, "\n"))
- fputc('\n', f);
-
- return fflush_and_check(f);
-}
-
-static int write_string_file_atomic(const char *fn, const char *line, bool enforce_newline) {
- _cleanup_fclose_ FILE *f = NULL;
- _cleanup_free_ char *p = NULL;
- int r;
-
- assert(fn);
- assert(line);
-
- r = fopen_temporary(fn, &f, &p);
- if (r < 0)
- return r;
-
- (void) fchmod_umask(fileno(f), 0644);
-
- r = write_string_stream(f, line, enforce_newline);
- if (r >= 0) {
- if (rename(p, fn) < 0)
- r = -errno;
- }
-
- if (r < 0)
- (void) unlink(p);
-
- return r;
-}
-
-int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) {
- _cleanup_fclose_ FILE *f = NULL;
- int q, r;
-
- assert(fn);
- assert(line);
-
- if (flags & WRITE_STRING_FILE_ATOMIC) {
- assert(flags & WRITE_STRING_FILE_CREATE);
-
- r = write_string_file_atomic(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
- if (r < 0)
- goto fail;
-
- return r;
- }
-
- if (flags & WRITE_STRING_FILE_CREATE) {
- f = fopen(fn, "we");
- if (!f) {
- r = -errno;
- goto fail;
- }
- } else {
- int fd;
-
- /* We manually build our own version of fopen(..., "we") that
- * works without O_CREAT */
- fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0) {
- r = -errno;
- goto fail;
- }
-
- f = fdopen(fd, "we");
- if (!f) {
- r = -errno;
- safe_close(fd);
- goto fail;
- }
- }
-
- r = write_string_stream(f, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
- if (r < 0)
- goto fail;
-
- return 0;
-
-fail:
- if (!(flags & WRITE_STRING_FILE_VERIFY_ON_FAILURE))
- return r;
-
- f = safe_fclose(f);
-
- /* OK, the operation failed, but let's see if the right
- * contents in place already. If so, eat up the error. */
-
- q = verify_file(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
- if (q <= 0)
- return r;
-
- return 0;
-}
-
-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 > 0 ? -errno : -EIO;
-
- t[0] = 0;
- }
-
- c = strdup(t);
- if (!c)
- return -ENOMEM;
- truncate_nl(c);
-
- *line = c;
- return 0;
-}
-
-int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
- _cleanup_fclose_ FILE *f = NULL;
- _cleanup_free_ char *buf = NULL;
- size_t l, k;
-
- assert(fn);
- assert(blob);
-
- l = strlen(blob);
-
- if (accept_extra_nl && endswith(blob, "\n"))
- accept_extra_nl = false;
-
- buf = malloc(l + accept_extra_nl + 1);
- if (!buf)
- return -ENOMEM;
-
- f = fopen(fn, "re");
- if (!f)
- return -errno;
-
- /* We try to read one byte more than we need, so that we know whether we hit eof */
- errno = 0;
- k = fread(buf, 1, l + accept_extra_nl + 1, f);
- if (ferror(f))
- return errno > 0 ? -errno : -EIO;
-
- if (k != l && k != l + accept_extra_nl)
- return 0;
- if (memcmp(buf, blob, l) != 0)
- return 0;
- if (k > l && buf[l] != '\n')
- return 0;
-
- return 1;
-}
-
-int read_full_stream(FILE *f, char **contents, size_t *size) {
- size_t n, l;
- _cleanup_free_ char *buf = NULL;
- struct stat st;
-
- assert(f);
- assert(contents);
-
- if (fstat(fileno(f), &st) < 0)
- return -errno;
-
- n = LINE_MAX;
-
- if (S_ISREG(st.st_mode)) {
-
- /* Safety check */
- if (st.st_size > READ_FULL_BYTES_MAX)
- return -E2BIG;
-
- /* Start with the right file size, but be prepared for
- * files from /proc which generally report a file size
- * of 0 */
- if (st.st_size > 0)
- n = st.st_size;
- }
-
- 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)
- l += k;
-
- if (ferror(f))
- return -errno;
-
- if (feof(f))
- break;
-
- /* We aren't expecting fread() to return a short read outside
- * of (error && eof), assert buffer is full and enlarge buffer.
- */
- assert(l == n);
-
- /* Safety check */
- if (n >= READ_FULL_BYTES_MAX)
- return -E2BIG;
-
- n = MIN(n * 2, READ_FULL_BYTES_MAX);
- }
-
- buf[l] = 0;
- *contents = buf;
- buf = NULL; /* do not free */
-
- if (size)
- *size = l;
-
- return 0;
-}
-
-int read_full_file(const char *fn, char **contents, size_t *size) {
- _cleanup_fclose_ FILE *f = NULL;
-
- assert(fn);
- assert(contents);
-
- f = fopen(fn, "re");
- if (!f)
- return -errno;
-
- return read_full_stream(f, contents, size);
-}
-
-static int parse_env_file_internal(
- FILE *f,
- const char *fname,
- const char *newline,
- int (*push) (const char *filename, unsigned line,
- const char *key, char *value, void *userdata, int *n_pushed),
- void *userdata,
- int *n_pushed) {
-
- _cleanup_free_ char *contents = NULL, *key = NULL;
- size_t key_alloc = 0, n_key = 0, value_alloc = 0, n_value = 0, last_value_whitespace = (size_t) -1, last_key_whitespace = (size_t) -1;
- char *p, *value = NULL;
- int r;
- unsigned line = 1;
-
- enum {
- PRE_KEY,
- KEY,
- PRE_VALUE,
- VALUE,
- VALUE_ESCAPE,
- SINGLE_QUOTE_VALUE,
- SINGLE_QUOTE_VALUE_ESCAPE,
- DOUBLE_QUOTE_VALUE,
- DOUBLE_QUOTE_VALUE_ESCAPE,
- COMMENT,
- COMMENT_ESCAPE
- } state = PRE_KEY;
-
- assert(newline);
-
- if (f)
- r = read_full_stream(f, &contents, NULL);
- else
- r = read_full_file(fname, &contents, NULL);
- if (r < 0)
- return r;
-
- for (p = contents; *p; p++) {
- char c = *p;
-
- switch (state) {
-
- case PRE_KEY:
- if (strchr(COMMENTS, c))
- state = COMMENT;
- else if (!strchr(WHITESPACE, c)) {
- state = KEY;
- last_key_whitespace = (size_t) -1;
-
- if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) {
- r = -ENOMEM;
- goto fail;
- }
-
- key[n_key++] = c;
- }
- break;
-
- case KEY:
- if (strchr(newline, c)) {
- state = PRE_KEY;
- line++;
- n_key = 0;
- } else if (c == '=') {
- state = PRE_VALUE;
- last_value_whitespace = (size_t) -1;
- } else {
- if (!strchr(WHITESPACE, c))
- last_key_whitespace = (size_t) -1;
- else if (last_key_whitespace == (size_t) -1)
- last_key_whitespace = n_key;
-
- if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) {
- r = -ENOMEM;
- goto fail;
- }
-
- key[n_key++] = c;
- }
-
- break;
-
- case PRE_VALUE:
- if (strchr(newline, c)) {
- state = PRE_KEY;
- line++;
- key[n_key] = 0;
-
- if (value)
- value[n_value] = 0;
-
- /* strip trailing whitespace from key */
- if (last_key_whitespace != (size_t) -1)
- key[last_key_whitespace] = 0;
-
- r = push(fname, line, key, value, userdata, n_pushed);
- if (r < 0)
- goto fail;
-
- n_key = 0;
- value = NULL;
- value_alloc = n_value = 0;
-
- } else if (c == '\'')
- state = SINGLE_QUOTE_VALUE;
- else if (c == '\"')
- state = DOUBLE_QUOTE_VALUE;
- else if (c == '\\')
- state = VALUE_ESCAPE;
- else if (!strchr(WHITESPACE, c)) {
- state = VALUE;
-
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
-
- value[n_value++] = c;
- }
-
- break;
-
- case VALUE:
- if (strchr(newline, c)) {
- state = PRE_KEY;
- line++;
-
- key[n_key] = 0;
-
- if (value)
- value[n_value] = 0;
-
- /* Chomp off trailing whitespace from value */
- if (last_value_whitespace != (size_t) -1)
- value[last_value_whitespace] = 0;
-
- /* strip trailing whitespace from key */
- if (last_key_whitespace != (size_t) -1)
- key[last_key_whitespace] = 0;
-
- r = push(fname, line, key, value, userdata, n_pushed);
- if (r < 0)
- goto fail;
-
- n_key = 0;
- value = NULL;
- value_alloc = n_value = 0;
-
- } else if (c == '\\') {
- state = VALUE_ESCAPE;
- last_value_whitespace = (size_t) -1;
- } else {
- if (!strchr(WHITESPACE, c))
- last_value_whitespace = (size_t) -1;
- else if (last_value_whitespace == (size_t) -1)
- last_value_whitespace = n_value;
-
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
-
- value[n_value++] = c;
- }
-
- break;
-
- case VALUE_ESCAPE:
- state = VALUE;
-
- if (!strchr(newline, c)) {
- /* Escaped newlines we eat up entirely */
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
-
- value[n_value++] = c;
- }
- break;
-
- case SINGLE_QUOTE_VALUE:
- if (c == '\'')
- state = PRE_VALUE;
- else if (c == '\\')
- state = SINGLE_QUOTE_VALUE_ESCAPE;
- else {
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
-
- value[n_value++] = c;
- }
-
- break;
-
- case SINGLE_QUOTE_VALUE_ESCAPE:
- state = SINGLE_QUOTE_VALUE;
-
- if (!strchr(newline, c)) {
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
-
- value[n_value++] = c;
- }
- break;
-
- case DOUBLE_QUOTE_VALUE:
- if (c == '\"')
- state = PRE_VALUE;
- else if (c == '\\')
- state = DOUBLE_QUOTE_VALUE_ESCAPE;
- else {
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
-
- value[n_value++] = c;
- }
-
- break;
-
- case DOUBLE_QUOTE_VALUE_ESCAPE:
- state = DOUBLE_QUOTE_VALUE;
-
- if (!strchr(newline, c)) {
- if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
- r = -ENOMEM;
- goto fail;
- }
-
- value[n_value++] = c;
- }
- break;
-
- case COMMENT:
- if (c == '\\')
- state = COMMENT_ESCAPE;
- else if (strchr(newline, c)) {
- state = PRE_KEY;
- line++;
- }
- break;
-
- case COMMENT_ESCAPE:
- state = COMMENT;
- break;
- }
- }
-
- if (state == PRE_VALUE ||
- state == VALUE ||
- state == VALUE_ESCAPE ||
- state == SINGLE_QUOTE_VALUE ||
- state == SINGLE_QUOTE_VALUE_ESCAPE ||
- state == DOUBLE_QUOTE_VALUE ||
- state == DOUBLE_QUOTE_VALUE_ESCAPE) {
-
- key[n_key] = 0;
-
- if (value)
- value[n_value] = 0;
-
- if (state == VALUE)
- if (last_value_whitespace != (size_t) -1)
- value[last_value_whitespace] = 0;
-
- /* strip trailing whitespace from key */
- if (last_key_whitespace != (size_t) -1)
- key[last_key_whitespace] = 0;
-
- r = push(fname, line, key, value, userdata, n_pushed);
- if (r < 0)
- goto fail;
- }
-
- return 0;
-
-fail:
- free(value);
- return r;
-}
-
-static int parse_env_file_push(
- const char *filename, unsigned line,
- const char *key, char *value,
- void *userdata,
- int *n_pushed) {
-
- const char *k;
- va_list aq, *ap = userdata;
-
- if (!utf8_is_valid(key)) {
- _cleanup_free_ char *p = NULL;
-
- p = utf8_escape_invalid(key);
- log_error("%s:%u: invalid UTF-8 in key '%s', ignoring.", strna(filename), line, p);
- return -EINVAL;
- }
-
- if (value && !utf8_is_valid(value)) {
- _cleanup_free_ char *p = NULL;
-
- p = utf8_escape_invalid(value);
- log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename), line, key, p);
- return -EINVAL;
- }
-
- va_copy(aq, *ap);
-
- while ((k = va_arg(aq, const char *))) {
- char **v;
-
- v = va_arg(aq, char **);
-
- if (streq(key, k)) {
- va_end(aq);
- free(*v);
- *v = value;
-
- if (n_pushed)
- (*n_pushed)++;
-
- return 1;
- }
- }
-
- va_end(aq);
- free(value);
-
- return 0;
-}
-
-int parse_env_file(
- const char *fname,
- const char *newline, ...) {
-
- va_list ap;
- int r, n_pushed = 0;
-
- if (!newline)
- newline = NEWLINE;
-
- va_start(ap, newline);
- r = parse_env_file_internal(NULL, fname, newline, parse_env_file_push, &ap, &n_pushed);
- va_end(ap);
-
- return r < 0 ? r : n_pushed;
-}
-
-static int load_env_file_push(
- const char *filename, unsigned line,
- const char *key, char *value,
- void *userdata,
- int *n_pushed) {
- char ***m = userdata;
- char *p;
- int r;
-
- if (!utf8_is_valid(key)) {
- _cleanup_free_ char *t = utf8_escape_invalid(key);
-
- log_error("%s:%u: invalid UTF-8 for key '%s', ignoring.", strna(filename), line, t);
- return -EINVAL;
- }
-
- if (value && !utf8_is_valid(value)) {
- _cleanup_free_ char *t = utf8_escape_invalid(value);
-
- log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename), line, key, t);
- return -EINVAL;
- }
-
- p = strjoin(key, "=", strempty(value), NULL);
- if (!p)
- return -ENOMEM;
-
- r = strv_consume(m, p);
- if (r < 0)
- return r;
-
- if (n_pushed)
- (*n_pushed)++;
-
- free(value);
- return 0;
-}
-
-int load_env_file(FILE *f, const char *fname, const char *newline, char ***rl) {
- char **m = NULL;
- int r;
-
- if (!newline)
- newline = NEWLINE;
-
- r = parse_env_file_internal(f, fname, newline, load_env_file_push, &m, NULL);
- if (r < 0) {
- strv_free(m);
- return r;
- }
-
- *rl = m;
- return 0;
-}
-
-static int load_env_file_push_pairs(
- const char *filename, unsigned line,
- const char *key, char *value,
- void *userdata,
- int *n_pushed) {
- char ***m = userdata;
- int r;
-
- if (!utf8_is_valid(key)) {
- _cleanup_free_ char *t = utf8_escape_invalid(key);
-
- log_error("%s:%u: invalid UTF-8 for key '%s', ignoring.", strna(filename), line, t);
- return -EINVAL;
- }
-
- if (value && !utf8_is_valid(value)) {
- _cleanup_free_ char *t = utf8_escape_invalid(value);
-
- log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename), line, key, t);
- return -EINVAL;
- }
-
- r = strv_extend(m, key);
- if (r < 0)
- return -ENOMEM;
-
- if (!value) {
- r = strv_extend(m, "");
- if (r < 0)
- return -ENOMEM;
- } else {
- r = strv_push(m, value);
- if (r < 0)
- return r;
- }
-
- if (n_pushed)
- (*n_pushed)++;
-
- return 0;
-}
-
-int load_env_file_pairs(FILE *f, const char *fname, const char *newline, char ***rl) {
- char **m = NULL;
- int r;
-
- if (!newline)
- newline = NEWLINE;
-
- r = parse_env_file_internal(f, fname, newline, load_env_file_push_pairs, &m, NULL);
- if (r < 0) {
- strv_free(m);
- return r;
- }
-
- *rl = m;
- return 0;
-}
-
-static void write_env_var(FILE *f, const char *v) {
- const char *p;
-
- p = strchr(v, '=');
- if (!p) {
- /* Fallback */
- fputs(v, f);
- fputc('\n', f);
- return;
- }
-
- p++;
- fwrite(v, 1, p-v, f);
-
- if (string_has_cc(p, NULL) || chars_intersect(p, WHITESPACE SHELL_NEED_QUOTES)) {
- fputc('\"', f);
-
- for (; *p; p++) {
- if (strchr(SHELL_NEED_ESCAPE, *p))
- fputc('\\', f);
-
- fputc(*p, f);
- }
-
- fputc('\"', f);
- } else
- fputs(p, f);
-
- fputc('\n', f);
-}
-
-int write_env_file(const char *fname, char **l) {
- _cleanup_fclose_ FILE *f = NULL;
- _cleanup_free_ char *p = NULL;
- char **i;
- int r;
-
- assert(fname);
-
- r = fopen_temporary(fname, &f, &p);
- if (r < 0)
- return r;
-
- fchmod_umask(fileno(f), 0644);
-
- STRV_FOREACH(i, l)
- write_env_var(f, *i);
-
- r = fflush_and_check(f);
- if (r >= 0) {
- if (rename(p, fname) >= 0)
- return 0;
-
- r = -errno;
- }
-
- unlink(p);
- return r;
-}
-
-int executable_is_script(const char *path, char **interpreter) {
- int r;
- _cleanup_free_ char *line = NULL;
- int len;
- char *ans;
-
- assert(path);
-
- r = read_one_line_file(path, &line);
- if (r < 0)
- return r;
-
- if (!startswith(line, "#!"))
- return 0;
-
- ans = strstrip(line + 2);
- len = strcspn(ans, " \t");
-
- if (len == 0)
- return 0;
-
- ans = strndup(ans, len);
- if (!ans)
- return -ENOMEM;
-
- *interpreter = ans;
- return 1;
-}
-
-/**
- * Retrieve one field from a file like /proc/self/status. pattern
- * should not include whitespace or the delimiter (':'). pattern matches only
- * the beginning of a line. Whitespace before ':' is skipped. Whitespace and
- * zeros after the ':' will be skipped. field must be freed afterwards.
- * terminator specifies the terminating characters of the field value (not
- * included in the value).
- */
-int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field) {
- _cleanup_free_ char *status = NULL;
- char *t, *f;
- size_t len;
- int r;
-
- assert(terminator);
- assert(filename);
- assert(pattern);
- assert(field);
-
- r = read_full_file(filename, &status, NULL);
- if (r < 0)
- return r;
-
- t = status;
-
- do {
- bool pattern_ok;
-
- do {
- t = strstr(t, pattern);
- if (!t)
- return -ENOENT;
-
- /* Check that pattern occurs in beginning of line. */
- pattern_ok = (t == status || t[-1] == '\n');
-
- t += strlen(pattern);
-
- } while (!pattern_ok);
-
- t += strspn(t, " \t");
- if (!*t)
- return -ENOENT;
-
- } while (*t != ':');
-
- t++;
-
- if (*t) {
- t += strspn(t, " \t");
-
- /* Also skip zeros, because when this is used for
- * capabilities, we don't want the zeros. This way the
- * same capability set always maps to the same string,
- * irrespective of the total capability set size. For
- * other numbers it shouldn't matter. */
- t += strspn(t, "0");
- /* Back off one char if there's nothing but whitespace
- and zeros */
- if (!*t || isspace(*t))
- t--;
- }
-
- len = strcspn(t, terminator);
-
- f = strndup(t, len);
- if (!f)
- return -ENOMEM;
-
- *field = f;
- return 0;
-}
-
-DIR *xopendirat(int fd, const char *name, int flags) {
- int nfd;
- DIR *d;
-
- assert(!(flags & O_CREAT));
-
- nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0);
- if (nfd < 0)
- return NULL;
-
- d = fdopendir(nfd);
- if (!d) {
- safe_close(nfd);
- return NULL;
- }
-
- return d;
-}
-
-static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) {
- char **i;
-
- assert(path);
- assert(mode);
- assert(_f);
-
- if (!path_strv_resolve_uniq(search, root))
- return -ENOMEM;
-
- STRV_FOREACH(i, search) {
- _cleanup_free_ char *p = NULL;
- FILE *f;
-
- if (root)
- p = strjoin(root, *i, "/", path, NULL);
- else
- p = strjoin(*i, "/", path, NULL);
- if (!p)
- return -ENOMEM;
-
- f = fopen(p, mode);
- if (f) {
- *_f = f;
- return 0;
- }
-
- if (errno != ENOENT)
- return -errno;
- }
-
- return -ENOENT;
-}
-
-int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) {
- _cleanup_strv_free_ char **copy = NULL;
-
- assert(path);
- assert(mode);
- assert(_f);
-
- if (path_is_absolute(path)) {
- FILE *f;
-
- f = fopen(path, mode);
- if (f) {
- *_f = f;
- return 0;
- }
-
- return -errno;
- }
-
- copy = strv_copy((char**) search);
- if (!copy)
- return -ENOMEM;
-
- return search_and_fopen_internal(path, mode, root, copy, _f);
-}
-
-int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) {
- _cleanup_strv_free_ char **s = NULL;
-
- if (path_is_absolute(path)) {
- FILE *f;
-
- f = fopen(path, mode);
- if (f) {
- *_f = f;
- return 0;
- }
-
- return -errno;
- }
-
- s = strv_split_nulstr(search);
- if (!s)
- return -ENOMEM;
-
- return search_and_fopen_internal(path, mode, root, s, _f);
-}
-
-int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
- FILE *f;
- char *t;
- int r, fd;
-
- assert(path);
- assert(_f);
- assert(_temp_path);
-
- r = tempfn_xxxxxx(path, NULL, &t);
- if (r < 0)
- return r;
-
- fd = mkostemp_safe(t);
- if (fd < 0) {
- free(t);
- return -errno;
- }
-
- f = fdopen(fd, "we");
- if (!f) {
- unlink_noerrno(t);
- free(t);
- safe_close(fd);
- return -errno;
- }
-
- *_f = f;
- *_temp_path = t;
-
- return 0;
-}
-
-int fflush_and_check(FILE *f) {
- assert(f);
-
- errno = 0;
- fflush(f);
-
- if (ferror(f))
- return errno > 0 ? -errno : -EIO;
-
- return 0;
-}
-
-/* This is much like mkostemp() but is subject to umask(). */
-int mkostemp_safe(char *pattern) {
- _cleanup_umask_ mode_t u = 0;
- int fd;
-
- assert(pattern);
-
- u = umask(077);
-
- fd = mkostemp(pattern, O_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- return fd;
-}
-
-int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
- const char *fn;
- char *t;
-
- assert(p);
- assert(ret);
-
- /*
- * Turns this:
- * /foo/bar/waldo
- *
- * Into this:
- * /foo/bar/.#<extra>waldoXXXXXX
- */
-
- fn = basename(p);
- if (!filename_is_valid(fn))
- return -EINVAL;
-
- if (extra == NULL)
- extra = "";
-
- t = new(char, strlen(p) + 2 + strlen(extra) + 6 + 1);
- if (!t)
- return -ENOMEM;
-
- strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn), "XXXXXX");
-
- *ret = path_kill_slashes(t);
- return 0;
-}
-
-int tempfn_random(const char *p, const char *extra, char **ret) {
- const char *fn;
- char *t, *x;
- uint64_t u;
- unsigned i;
-
- assert(p);
- assert(ret);
-
- /*
- * Turns this:
- * /foo/bar/waldo
- *
- * Into this:
- * /foo/bar/.#<extra>waldobaa2a261115984a9
- */
-
- fn = basename(p);
- if (!filename_is_valid(fn))
- return -EINVAL;
-
- if (!extra)
- extra = "";
-
- t = new(char, strlen(p) + 2 + strlen(extra) + 16 + 1);
- if (!t)
- return -ENOMEM;
-
- x = stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn);
-
- u = random_u64();
- for (i = 0; i < 16; i++) {
- *(x++) = hexchar(u & 0xF);
- u >>= 4;
- }
-
- *x = 0;
-
- *ret = path_kill_slashes(t);
- return 0;
-}
-
-int tempfn_random_child(const char *p, const char *extra, char **ret) {
- char *t, *x;
- uint64_t u;
- unsigned i;
- int r;
-
- assert(ret);
-
- /* Turns this:
- * /foo/bar/waldo
- * Into this:
- * /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0
- */
-
- if (!p) {
- r = tmp_dir(&p);
- if (r < 0)
- return r;
- }
-
- if (!extra)
- extra = "";
-
- t = new(char, strlen(p) + 3 + strlen(extra) + 16 + 1);
- if (!t)
- return -ENOMEM;
-
- x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra);
-
- u = random_u64();
- for (i = 0; i < 16; i++) {
- *(x++) = hexchar(u & 0xF);
- u >>= 4;
- }
-
- *x = 0;
-
- *ret = path_kill_slashes(t);
- return 0;
-}
-
-int write_timestamp_file_atomic(const char *fn, usec_t n) {
- char ln[DECIMAL_STR_MAX(n)+2];
-
- /* Creates a "timestamp" file, that contains nothing but a
- * usec_t timestamp, formatted in ASCII. */
-
- if (n <= 0 || n >= USEC_INFINITY)
- return -ERANGE;
-
- xsprintf(ln, USEC_FMT "\n", n);
-
- return write_string_file(fn, ln, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
-}
-
-int read_timestamp_file(const char *fn, usec_t *ret) {
- _cleanup_free_ char *ln = NULL;
- uint64_t t;
- int r;
-
- r = read_one_line_file(fn, &ln);
- if (r < 0)
- return r;
-
- r = safe_atou64(ln, &t);
- if (r < 0)
- return r;
-
- if (t <= 0 || t >= (uint64_t) USEC_INFINITY)
- return -ERANGE;
-
- *ret = (usec_t) t;
- return 0;
-}
-
-int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space) {
- int r;
-
- assert(s);
-
- /* Outputs the specified string with fputs(), but optionally prefixes it with a separator. The *space parameter
- * when specified shall initially point to a boolean variable initialized to false. It is set to true after the
- * first invocation. This call is supposed to be use in loops, where a separator shall be inserted between each
- * element, but not before the first one. */
-
- if (!f)
- f = stdout;
-
- if (space) {
- if (!separator)
- separator = " ";
-
- if (*space) {
- r = fputs(separator, f);
- if (r < 0)
- return r;
- }
-
- *space = true;
- }
-
- return fputs(s, f);
-}
-
-int open_tmpfile_unlinkable(const char *directory, int flags) {
- char *p;
- int fd, r;
-
- if (!directory) {
- r = tmp_dir(&directory);
- if (r < 0)
- return r;
- }
-
- /* Returns an unlinked temporary file that cannot be linked into the file system anymore */
-
- /* Try O_TMPFILE first, if it is supported */
- fd = open(directory, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
- if (fd >= 0)
- return fd;
-
- /* Fall back to unguessable name + unlinking */
- p = strjoina(directory, "/systemd-tmp-XXXXXX");
-
- fd = mkostemp_safe(p);
- if (fd < 0)
- return fd;
-
- (void) unlink(p);
-
- return fd;
-}
-
-int open_tmpfile_linkable(const char *target, int flags, char **ret_path) {
- _cleanup_free_ char *tmp = NULL;
- int r, fd;
-
- assert(target);
- assert(ret_path);
-
- /* Don't allow O_EXCL, as that has a special meaning for O_TMPFILE */
- assert((flags & O_EXCL) == 0);
-
- /* Creates a temporary file, that shall be renamed to "target" later. If possible, this uses O_TMPFILE – in
- * which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in
- * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
-
- {
- _cleanup_free_ char *dn = NULL;
-
- dn = dirname_malloc(target);
- if (!dn)
- return -ENOMEM;
-
- fd = open(dn, O_TMPFILE|flags, 0640);
- if (fd >= 0) {
- *ret_path = NULL;
- return fd;
- }
-
- log_debug_errno(errno, "Failed to use O_TMPFILE on %s: %m", dn);
- }
-
- r = tempfn_random(target, NULL, &tmp);
- if (r < 0)
- return r;
-
- fd = open(tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|flags, 0640);
- if (fd < 0)
- return -errno;
-
- *ret_path = tmp;
- tmp = NULL;
-
- return fd;
-}
-
-int link_tmpfile(int fd, const char *path, const char *target) {
-
- assert(fd >= 0);
- assert(target);
-
- /* Moves a temporary file created with open_tmpfile() above into its final place. if "path" is NULL an fd
- * created with O_TMPFILE is assumed, and linkat() is used. Otherwise it is assumed O_TMPFILE is not supported
- * on the directory, and renameat2() is used instead.
- *
- * Note that in both cases we will not replace existing files. This is because linkat() does not support this
- * operation currently (renameat2() does), and there is no nice way to emulate this. */
-
- if (path) {
- if (rename_noreplace(AT_FDCWD, path, AT_FDCWD, target) < 0)
- return -errno;
- } else {
- char proc_fd_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
-
- xsprintf(proc_fd_path, "/proc/self/fd/%i", fd);
-
- if (linkat(AT_FDCWD, proc_fd_path, AT_FDCWD, target, AT_SYMLINK_FOLLOW) < 0)
- return -errno;
- }
-
- return 0;
-}
-
-int read_nul_string(FILE *f, char **ret) {
- _cleanup_free_ char *x = NULL;
- size_t allocated = 0, n = 0;
-
- assert(f);
- assert(ret);
-
- /* Reads a NUL-terminated string from the specified file. */
-
- for (;;) {
- int c;
-
- if (!GREEDY_REALLOC(x, allocated, n+2))
- return -ENOMEM;
-
- c = fgetc(f);
- if (c == 0) /* Terminate at NUL byte */
- break;
- if (c == EOF) {
- if (ferror(f))
- return -errno;
- break; /* Terminate at EOF */
- }
-
- x[n++] = (char) c;
- }
-
- if (x)
- x[n] = 0;
- else {
- x = new0(char, 1);
- if (!x)
- return -ENOMEM;
- }
-
- *ret = x;
- x = NULL;
-
- return 0;
-}
diff --git a/src/basic/fileio.h b/src/basic/fileio.h
deleted file mode 100644
index b58c83e64a..0000000000
--- a/src/basic/fileio.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#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 <dirent.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <sys/types.h>
-
-#include "macro.h"
-#include "time-util.h"
-
-typedef enum {
- WRITE_STRING_FILE_CREATE = 1,
- WRITE_STRING_FILE_ATOMIC = 2,
- WRITE_STRING_FILE_AVOID_NEWLINE = 4,
- WRITE_STRING_FILE_VERIFY_ON_FAILURE = 8,
-} WriteStringFileFlags;
-
-int write_string_stream(FILE *f, const char *line, bool enforce_newline);
-int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags);
-
-int read_one_line_file(const char *fn, char **line);
-int read_full_file(const char *fn, char **contents, size_t *size);
-int read_full_stream(FILE *f, char **contents, size_t *size);
-
-int verify_file(const char *fn, const char *blob, bool accept_extra_nl);
-
-int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
-int load_env_file(FILE *f, const char *fname, const char *separator, char ***l);
-int load_env_file_pairs(FILE *f, const char *fname, const char *separator, char ***l);
-
-int write_env_file(const char *fname, char **l);
-
-int executable_is_script(const char *path, char **interpreter);
-
-int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field);
-
-DIR *xopendirat(int dirfd, const char *name, int flags);
-
-int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f);
-int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f);
-
-#define FOREACH_LINE(line, f, on_error) \
- for (;;) \
- if (!fgets(line, sizeof(line), f)) { \
- if (ferror(f)) { \
- on_error; \
- } \
- break; \
- } else
-
-int fflush_and_check(FILE *f);
-
-int fopen_temporary(const char *path, FILE **_f, char **_temp_path);
-int mkostemp_safe(char *pattern);
-
-int tempfn_xxxxxx(const char *p, const char *extra, char **ret);
-int tempfn_random(const char *p, const char *extra, char **ret);
-int tempfn_random_child(const char *p, const char *extra, char **ret);
-
-int write_timestamp_file_atomic(const char *fn, usec_t n);
-int read_timestamp_file(const char *fn, usec_t *ret);
-
-int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space);
-
-int open_tmpfile_unlinkable(const char *directory, int flags);
-int open_tmpfile_linkable(const char *target, int flags, char **ret_path);
-
-int link_tmpfile(int fd, const char *path, const char *target);
-
-int read_nul_string(FILE *f, char **ret);
diff --git a/src/basic/formats-util.h b/src/basic/formats-util.h
deleted file mode 100644
index 39a185f59b..0000000000
--- a/src/basic/formats-util.h
+++ /dev/null
@@ -1,79 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2015 Ronny Chevalier
-
- 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>
-
-#if SIZEOF_PID_T == 4
-# define PID_PRI PRIi32
-#elif SIZEOF_PID_T == 2
-# define PID_PRI PRIi16
-#else
-# error Unknown pid_t size
-#endif
-#define PID_FMT "%" PID_PRI
-
-#if SIZEOF_UID_T == 4
-# define UID_FMT "%" PRIu32
-#elif SIZEOF_UID_T == 2
-# define UID_FMT "%" PRIu16
-#else
-# error Unknown uid_t size
-#endif
-
-#if SIZEOF_GID_T == 4
-# define GID_FMT "%" PRIu32
-#elif SIZEOF_GID_T == 2
-# define GID_FMT "%" PRIu16
-#else
-# error Unknown gid_t size
-#endif
-
-#if SIZEOF_TIME_T == 8
-# define PRI_TIME PRIi64
-#elif SIZEOF_TIME_T == 4
-# define PRI_TIME "li"
-#else
-# error Unknown time_t size
-#endif
-
-#if SIZEOF_RLIM_T == 8
-# define RLIM_FMT "%" PRIu64
-#elif SIZEOF_RLIM_T == 4
-# define RLIM_FMT "%" PRIu32
-#else
-# error Unknown rlim_t size
-#endif
-
-#if SIZEOF_DEV_T == 8
-# define DEV_FMT "%" PRIu64
-#elif SIZEOF_DEV_T == 4
-# define DEV_FMT "%" PRIu32
-#else
-# error Unknown dev_t size
-#endif
-
-#if SIZEOF_INO_T == 8
-# define INO_FMT "%" PRIu64
-#elif SIZEOF_INO_T == 4
-# define INO_FMT "%" PRIu32
-#else
-# error Unknown ino_t size
-#endif
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
deleted file mode 100644
index 48952a1c26..0000000000
--- a/src/basic/fs-util.c
+++ /dev/null
@@ -1,782 +0,0 @@
-/***
- 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 <dirent.h>
-#include <errno.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "alloc-util.h"
-#include "dirent-util.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "fs-util.h"
-#include "log.h"
-#include "macro.h"
-#include "missing.h"
-#include "mkdir.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "stat-util.h"
-#include "stdio-util.h"
-#include "string-util.h"
-#include "strv.h"
-#include "time-util.h"
-#include "user-util.h"
-#include "util.h"
-
-int unlink_noerrno(const char *path) {
- PROTECT_ERRNO;
- int r;
-
- r = unlink(path);
- if (r < 0)
- return -errno;
-
- return 0;
-}
-
-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;
-
- t = strndup(path, l);
- if (!t)
- 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;
-}
-
-
-int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
- struct stat buf;
- int ret;
-
- ret = renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE);
- if (ret >= 0)
- return 0;
-
- /* renameat2() exists since Linux 3.15, btrfs added support for it later.
- * If it is not implemented, fallback to another method. */
- if (!IN_SET(errno, EINVAL, ENOSYS))
- return -errno;
-
- /* The link()/unlink() fallback does not work on directories. But
- * renameat() without RENAME_NOREPLACE gives the same semantics on
- * directories, except when newpath is an *empty* directory. This is
- * good enough. */
- ret = fstatat(olddirfd, oldpath, &buf, AT_SYMLINK_NOFOLLOW);
- if (ret >= 0 && S_ISDIR(buf.st_mode)) {
- ret = renameat(olddirfd, oldpath, newdirfd, newpath);
- return ret >= 0 ? 0 : -errno;
- }
-
- /* If it is not a directory, use the link()/unlink() fallback. */
- ret = linkat(olddirfd, oldpath, newdirfd, newpath, 0);
- if (ret < 0)
- return -errno;
-
- ret = unlinkat(olddirfd, oldpath, 0);
- if (ret < 0) {
- /* backup errno before the following unlinkat() alters it */
- ret = errno;
- (void) unlinkat(newdirfd, newpath, 0);
- errno = ret;
- return -errno;
- }
-
- return 0;
-}
-
-int readlinkat_malloc(int fd, const char *p, char **ret) {
- size_t l = 100;
- int r;
-
- assert(p);
- assert(ret);
-
- for (;;) {
- char *c;
- ssize_t n;
-
- c = new(char, l);
- if (!c)
- return -ENOMEM;
-
- n = readlinkat(fd, p, c, l-1);
- if (n < 0) {
- r = -errno;
- free(c);
- return r;
- }
-
- if ((size_t) n < l-1) {
- c[n] = 0;
- *ret = c;
- return 0;
- }
-
- free(c);
- l *= 2;
- }
-}
-
-int readlink_malloc(const char *p, char **ret) {
- return readlinkat_malloc(AT_FDCWD, p, ret);
-}
-
-int readlink_value(const char *p, char **ret) {
- _cleanup_free_ char *link = NULL;
- char *value;
- int r;
-
- r = readlink_malloc(p, &link);
- if (r < 0)
- return r;
-
- value = basename(link);
- if (!value)
- return -ENOENT;
-
- value = strdup(value);
- if (!value)
- return -ENOMEM;
-
- *ret = value;
-
- return 0;
-}
-
-int readlink_and_make_absolute(const char *p, char **r) {
- _cleanup_free_ char *target = NULL;
- char *k;
- int j;
-
- assert(p);
- assert(r);
-
- j = readlink_malloc(p, &target);
- if (j < 0)
- return j;
-
- k = file_in_same_dir(p, 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 readlink_and_make_absolute_root(const char *root, const char *path, char **ret) {
- _cleanup_free_ char *target = NULL, *t = NULL;
- const char *full;
- int r;
-
- full = prefix_roota(root, path);
- r = readlink_malloc(full, &target);
- if (r < 0)
- return r;
-
- t = file_in_same_dir(path, target);
- if (!t)
- return -ENOMEM;
-
- *ret = t;
- t = NULL;
-
- return 0;
-}
-
-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_INVALID)
- if (chmod(path, mode) < 0)
- return -errno;
-
- if (uid != UID_INVALID || gid != GID_INVALID)
- if (chown(path, uid, gid) < 0)
- return -errno;
-
- 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 fd_warn_permissions(const char *path, int fd) {
- struct stat st;
-
- if (fstat(fd, &st) < 0)
- return -errno;
-
- if (st.st_mode & 0111)
- log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path);
-
- if (st.st_mode & 0002)
- log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
-
- if (getpid() == 1 && (st.st_mode & 0044) != 0044)
- log_warning("Configuration file %s is marked world-inaccessible. This has no effect as configuration data is accessible via APIs without restrictions. Proceeding anyway.", path);
-
- return 0;
-}
-
-int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) {
- _cleanup_close_ int fd;
- int r;
-
- assert(path);
-
- if (parents)
- mkdir_parents(path, 0755);
-
- fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY,
- (mode == 0 || mode == MODE_INVALID) ? 0644 : mode);
- if (fd < 0)
- return -errno;
-
- if (mode != MODE_INVALID) {
- r = fchmod(fd, mode);
- if (r < 0)
- return -errno;
- }
-
- if (uid != UID_INVALID || gid != GID_INVALID) {
- r = fchown(fd, uid, gid);
- if (r < 0)
- return -errno;
- }
-
- if (stamp != USEC_INFINITY) {
- struct timespec ts[2];
-
- timespec_store(&ts[0], stamp);
- ts[1] = ts[0];
- r = futimens(fd, ts);
- } else
- r = futimens(fd, NULL);
- if (r < 0)
- return -errno;
-
- return 0;
-}
-
-int touch(const char *path) {
- return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID);
-}
-
-int symlink_idempotent(const char *from, const char *to) {
- _cleanup_free_ char *p = NULL;
- int r;
-
- assert(from);
- assert(to);
-
- if (symlink(from, to) < 0) {
- if (errno != EEXIST)
- return -errno;
-
- r = readlink_malloc(to, &p);
- if (r < 0)
- return r;
-
- if (!streq(p, from))
- return -EINVAL;
- }
-
- return 0;
-}
-
-int symlink_atomic(const char *from, const char *to) {
- _cleanup_free_ char *t = NULL;
- int r;
-
- assert(from);
- assert(to);
-
- r = tempfn_random(to, NULL, &t);
- if (r < 0)
- return r;
-
- if (symlink(from, t) < 0)
- return -errno;
-
- if (rename(t, to) < 0) {
- unlink_noerrno(t);
- return -errno;
- }
-
- return 0;
-}
-
-int mknod_atomic(const char *path, mode_t mode, dev_t dev) {
- _cleanup_free_ char *t = NULL;
- int r;
-
- assert(path);
-
- r = tempfn_random(path, NULL, &t);
- if (r < 0)
- return r;
-
- if (mknod(t, mode, dev) < 0)
- return -errno;
-
- if (rename(t, path) < 0) {
- unlink_noerrno(t);
- return -errno;
- }
-
- return 0;
-}
-
-int mkfifo_atomic(const char *path, mode_t mode) {
- _cleanup_free_ char *t = NULL;
- int r;
-
- assert(path);
-
- r = tempfn_random(path, NULL, &t);
- if (r < 0)
- return r;
-
- if (mkfifo(t, mode) < 0)
- return -errno;
-
- if (rename(t, path) < 0) {
- unlink_noerrno(t);
- return -errno;
- }
-
- return 0;
-}
-
-int get_files_in_directory(const char *path, char ***list) {
- _cleanup_closedir_ DIR *d = NULL;
- size_t bufsize = 0, n = 0;
- _cleanup_strv_free_ 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;
-
- errno = 0;
- de = readdir(d);
- if (!de && errno > 0)
- return -errno;
- if (!de)
- break;
-
- dirent_ensure_type(d, de);
-
- if (!dirent_is_file(de))
- continue;
-
- if (list) {
- /* one extra slot is needed for the terminating NULL */
- if (!GREEDY_REALLOC(l, bufsize, n + 2))
- return -ENOMEM;
-
- l[n] = strdup(de->d_name);
- if (!l[n])
- return -ENOMEM;
-
- l[++n] = NULL;
- } else
- n++;
- }
-
- if (list) {
- *list = l;
- l = NULL; /* avoid freeing */
- }
-
- return n;
-}
-
-static int getenv_tmp_dir(const char **ret_path) {
- const char *n;
- int r, ret = 0;
-
- assert(ret_path);
-
- /* We use the same order of environment variables python uses in tempfile.gettempdir():
- * https://docs.python.org/3/library/tempfile.html#tempfile.gettempdir */
- FOREACH_STRING(n, "TMPDIR", "TEMP", "TMP") {
- const char *e;
-
- e = secure_getenv(n);
- if (!e)
- continue;
- if (!path_is_absolute(e)) {
- r = -ENOTDIR;
- goto next;
- }
- if (!path_is_safe(e)) {
- r = -EPERM;
- goto next;
- }
-
- r = is_dir(e, true);
- if (r < 0)
- goto next;
- if (r == 0) {
- r = -ENOTDIR;
- goto next;
- }
-
- *ret_path = e;
- return 1;
-
- next:
- /* Remember first error, to make this more debuggable */
- if (ret >= 0)
- ret = r;
- }
-
- if (ret < 0)
- return ret;
-
- *ret_path = NULL;
- return ret;
-}
-
-static int tmp_dir_internal(const char *def, const char **ret) {
- const char *e;
- int r, k;
-
- assert(def);
- assert(ret);
-
- r = getenv_tmp_dir(&e);
- if (r > 0) {
- *ret = e;
- return 0;
- }
-
- k = is_dir(def, true);
- if (k == 0)
- k = -ENOTDIR;
- if (k < 0)
- return r < 0 ? r : k;
-
- *ret = def;
- return 0;
-}
-
-int var_tmp_dir(const char **ret) {
-
- /* Returns the location for "larger" temporary files, that is backed by physical storage if available, and thus
- * even might survive a boot: /var/tmp. If $TMPDIR (or related environment variables) are set, its value is
- * returned preferably however. Note that both this function and tmp_dir() below are affected by $TMPDIR,
- * making it a variable that overrides all temporary file storage locations. */
-
- return tmp_dir_internal("/var/tmp", ret);
-}
-
-int tmp_dir(const char **ret) {
-
- /* Similar to var_tmp_dir() above, but returns the location for "smaller" temporary files, which is usually
- * backed by an in-memory file system: /tmp. */
-
- return tmp_dir_internal("/tmp", ret);
-}
-
-int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
- char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
- int r;
-
- /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
- xsprintf(path, "/proc/self/fd/%i", what);
-
- r = inotify_add_watch(fd, path, mask);
- if (r < 0)
- return -errno;
-
- return r;
-}
-
-int chase_symlinks(const char *path, const char *_root, char **ret) {
- _cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL;
- _cleanup_close_ int fd = -1;
- unsigned max_follow = 32; /* how many symlinks to follow before giving up and returning ELOOP */
- char *todo;
- int r;
-
- assert(path);
-
- /* This is a lot like canonicalize_file_name(), but takes an additional "root" parameter, that allows following
- * symlinks relative to a root directory, instead of the root of the host.
- *
- * Note that "root" matters only if we encounter an absolute symlink, it's unused otherwise. Most importantly
- * this means the path parameter passed in is not prefixed by it.
- *
- * Algorithmically this operates on two path buffers: "done" are the components of the path we already
- * processed and resolved symlinks, "." and ".." of. "todo" are the components of the path we still need to
- * process. On each iteration, we move one component from "todo" to "done", processing it's special meaning
- * each time. The "todo" path always starts with at least one slash, the "done" path always ends in no
- * slash. We always keep an O_PATH fd to the component we are currently processing, thus keeping lookup races
- * at a minimum. */
-
- r = path_make_absolute_cwd(path, &buffer);
- if (r < 0)
- return r;
-
- if (_root) {
- r = path_make_absolute_cwd(_root, &root);
- if (r < 0)
- return r;
- }
-
- fd = open("/", O_CLOEXEC|O_NOFOLLOW|O_PATH);
- if (fd < 0)
- return -errno;
-
- todo = buffer;
- for (;;) {
- _cleanup_free_ char *first = NULL;
- _cleanup_close_ int child = -1;
- struct stat st;
- size_t n, m;
-
- /* Determine length of first component in the path */
- n = strspn(todo, "/"); /* The slashes */
- m = n + strcspn(todo + n, "/"); /* The entire length of the component */
-
- /* Extract the first component. */
- first = strndup(todo, m);
- if (!first)
- return -ENOMEM;
-
- todo += m;
-
- /* Just a single slash? Then we reached the end. */
- if (isempty(first) || path_equal(first, "/"))
- break;
-
- /* Just a dot? Then let's eat this up. */
- if (path_equal(first, "/."))
- continue;
-
- /* Two dots? Then chop off the last bit of what we already found out. */
- if (path_equal(first, "/..")) {
- _cleanup_free_ char *parent = NULL;
- int fd_parent = -1;
-
- if (isempty(done) || path_equal(done, "/"))
- return -EINVAL;
-
- parent = dirname_malloc(done);
- if (!parent)
- return -ENOMEM;
-
- /* Don't allow this to leave the root dir */
- if (root &&
- path_startswith(done, root) &&
- !path_startswith(parent, root))
- return -EINVAL;
-
- free_and_replace(done, parent);
-
- fd_parent = openat(fd, "..", O_CLOEXEC|O_NOFOLLOW|O_PATH);
- if (fd_parent < 0)
- return -errno;
-
- safe_close(fd);
- fd = fd_parent;
-
- continue;
- }
-
- /* Otherwise let's see what this is. */
- child = openat(fd, first + n, O_CLOEXEC|O_NOFOLLOW|O_PATH);
- if (child < 0)
- return -errno;
-
- if (fstat(child, &st) < 0)
- return -errno;
-
- if (S_ISLNK(st.st_mode)) {
- _cleanup_free_ char *destination = NULL;
-
- /* This is a symlink, in this case read the destination. But let's make sure we don't follow
- * symlinks without bounds. */
- if (--max_follow <= 0)
- return -ELOOP;
-
- r = readlinkat_malloc(fd, first + n, &destination);
- if (r < 0)
- return r;
- if (isempty(destination))
- return -EINVAL;
-
- if (path_is_absolute(destination)) {
-
- /* An absolute destination. Start the loop from the beginning, but use the root
- * directory as base. */
-
- safe_close(fd);
- fd = open(root ?: "/", O_CLOEXEC|O_NOFOLLOW|O_PATH);
- if (fd < 0)
- return -errno;
-
- free_and_replace(buffer, destination);
-
- todo = buffer;
- free(done);
-
- /* Note that we do not revalidate the root, we take it as is. */
- if (isempty(root))
- done = NULL;
- else {
- done = strdup(root);
- if (!done)
- return -ENOMEM;
- }
-
- } else {
- char *joined;
-
- /* A relative destination. If so, this is what we'll prefix what's left to do with what
- * we just read, and start the loop again, but remain in the current directory. */
-
- joined = strjoin("/", destination, todo, NULL);
- if (!joined)
- return -ENOMEM;
-
- free(buffer);
- todo = buffer = joined;
- }
-
- continue;
- }
-
- /* If this is not a symlink, then let's just add the name we read to what we already verified. */
- if (!done) {
- done = first;
- first = NULL;
- } else {
- if (!strextend(&done, first, NULL))
- return -ENOMEM;
- }
-
- /* And iterate again, but go one directory further down. */
- safe_close(fd);
- fd = child;
- child = -1;
- }
-
- if (!done) {
- /* Special case, turn the empty string into "/", to indicate the root directory. */
- done = strdup("/");
- if (!done)
- return -ENOMEM;
- }
-
- *ret = done;
- done = NULL;
-
- return 0;
-}
diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h
deleted file mode 100644
index 31df47cf1e..0000000000
--- a/src/basic/fs-util.h
+++ /dev/null
@@ -1,81 +0,0 @@
-#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 <fcntl.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <sys/inotify.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "time-util.h"
-
-int unlink_noerrno(const char *path);
-
-int rmdir_parents(const char *path, const char *stop);
-
-int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
-
-int readlinkat_malloc(int fd, const char *p, char **ret);
-int readlink_malloc(const char *p, char **r);
-int readlink_value(const char *p, char **ret);
-int readlink_and_make_absolute(const char *p, char **r);
-int readlink_and_canonicalize(const char *p, char **r);
-int readlink_and_make_absolute_root(const char *root, const char *path, char **ret);
-
-int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
-
-int fchmod_umask(int fd, mode_t mode);
-
-int fd_warn_permissions(const char *path, int fd);
-
-#define laccess(path, mode) faccessat(AT_FDCWD, (path), (mode), AT_SYMLINK_NOFOLLOW)
-
-int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode);
-int touch(const char *path);
-
-int symlink_idempotent(const char *from, const char *to);
-
-int symlink_atomic(const char *from, const char *to);
-int mknod_atomic(const char *path, mode_t mode, dev_t dev);
-int mkfifo_atomic(const char *path, mode_t mode);
-
-int get_files_in_directory(const char *path, char ***list);
-
-int tmp_dir(const char **ret);
-int var_tmp_dir(const char **ret);
-
-#define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1)
-
-#define FOREACH_INOTIFY_EVENT(e, buffer, sz) \
- for ((e) = &buffer.ev; \
- (uint8_t*) (e) < (uint8_t*) (buffer.raw) + (sz); \
- (e) = (struct inotify_event*) ((uint8_t*) (e) + sizeof(struct inotify_event) + (e)->len))
-
-union inotify_event_buffer {
- struct inotify_event ev;
- uint8_t raw[INOTIFY_EVENT_MAX];
-};
-
-int inotify_add_watch_fd(int fd, int what, uint32_t mask);
-
-int chase_symlinks(const char *path, const char *_root, char **ret);
diff --git a/src/basic/glob-util.c b/src/basic/glob-util.c
deleted file mode 100644
index 007198c269..0000000000
--- a/src/basic/glob-util.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/***
- 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 <glob.h>
-
-#include "glob-util.h"
-#include "macro.h"
-#include "strv.h"
-
-int glob_exists(const char *path) {
- _cleanup_globfree_ glob_t g = {};
- int k;
-
- assert(path);
-
- errno = 0;
- k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
-
- if (k == GLOB_NOMATCH)
- return 0;
- if (k == GLOB_NOSPACE)
- return -ENOMEM;
- if (k != 0)
- return errno > 0 ? -errno : -EIO;
-
- return !strv_isempty(g.gl_pathv);
-}
-
-int glob_extend(char ***strv, const char *path) {
- _cleanup_globfree_ glob_t g = {};
- int k;
- char **p;
-
- errno = 0;
- k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
-
- if (k == GLOB_NOMATCH)
- return -ENOENT;
- if (k == GLOB_NOSPACE)
- return -ENOMEM;
- if (k != 0)
- return errno > 0 ? -errno : -EIO;
- if (strv_isempty(g.gl_pathv))
- return -ENOENT;
-
- STRV_FOREACH(p, g.gl_pathv) {
- k = strv_extend(strv, *p);
- if (k < 0)
- return k;
- }
-
- return 0;
-}
diff --git a/src/basic/glob-util.h b/src/basic/glob-util.h
deleted file mode 100644
index 5d8fb47a26..0000000000
--- a/src/basic/glob-util.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#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 <string.h>
-
-#include "macro.h"
-#include "string-util.h"
-
-int glob_exists(const char *path);
-int glob_extend(char ***strv, const char *path);
-
-#define _cleanup_globfree_ _cleanup_(globfree)
-
-_pure_ static inline bool string_is_glob(const char *p) {
- /* Check if a string contains any glob patterns. */
- return !!strpbrk(p, GLOB_CHARS);
-}
diff --git a/src/basic/gunicode.c b/src/basic/gunicode.c
deleted file mode 100644
index e6ac0545a4..0000000000
--- a/src/basic/gunicode.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/* gunicode.c - Unicode manipulation functions
- *
- * Copyright (C) 1999, 2000 Tom Tromey
- * Copyright 2000, 2005 Red Hat, Inc.
- */
-
-#include <stdlib.h>
-
-#include "gunicode.h"
-
-#define unichar uint32_t
-
-/**
- * g_utf8_prev_char:
- * @p: a pointer to a position within a UTF-8 encoded string
- *
- * Finds the previous UTF-8 character in the string before @p.
- *
- * @p does not have to be at the beginning of a UTF-8 character. No check
- * is made to see if the character found is actually valid other than
- * it starts with an appropriate byte. If @p might be the first
- * character of the string, you must use g_utf8_find_prev_char() instead.
- *
- * Return value: a pointer to the found character.
- **/
-char *
-utf8_prev_char (const char *p)
-{
- for (;;)
- {
- p--;
- if ((*p & 0xc0) != 0x80)
- return (char *)p;
- }
-}
-
-struct Interval
-{
- unichar start, end;
-};
-
-static int
-interval_compare (const void *key, const void *elt)
-{
- unichar c = (unichar) (long) (key);
- struct Interval *interval = (struct Interval *)elt;
-
- if (c < interval->start)
- return -1;
- if (c > interval->end)
- return +1;
-
- return 0;
-}
-
-/*
- * NOTE:
- *
- * The tables for g_unichar_iswide() and g_unichar_iswide_cjk() are
- * generated from the Unicode Character Database's file
- * extracted/DerivedEastAsianWidth.txt using the gen-iswide-table.py
- * in this way:
- *
- * ./gen-iswide-table.py < path/to/ucd/extracted/DerivedEastAsianWidth.txt | fmt
- *
- * Last update for Unicode 6.0.
- */
-
-/**
- * g_unichar_iswide:
- * @c: a Unicode character
- *
- * Determines if a character is typically rendered in a double-width
- * cell.
- *
- * Return value: %TRUE if the character is wide
- **/
-bool
-unichar_iswide (unichar c)
-{
- /* See NOTE earlier for how to update this table. */
- static const struct Interval wide[] = {
- {0x1100, 0x115F}, {0x2329, 0x232A}, {0x2E80, 0x2E99}, {0x2E9B, 0x2EF3},
- {0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB}, {0x3000, 0x303E}, {0x3041, 0x3096},
- {0x3099, 0x30FF}, {0x3105, 0x312D}, {0x3131, 0x318E}, {0x3190, 0x31BA},
- {0x31C0, 0x31E3}, {0x31F0, 0x321E}, {0x3220, 0x3247}, {0x3250, 0x32FE},
- {0x3300, 0x4DBF}, {0x4E00, 0xA48C}, {0xA490, 0xA4C6}, {0xA960, 0xA97C},
- {0xAC00, 0xD7A3}, {0xF900, 0xFAFF}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52},
- {0xFE54, 0xFE66}, {0xFE68, 0xFE6B}, {0xFF01, 0xFF60}, {0xFFE0, 0xFFE6},
- {0x1B000, 0x1B001}, {0x1F200, 0x1F202}, {0x1F210, 0x1F23A},
- {0x1F240, 0x1F248}, {0x1F250, 0x1F251},
- {0x1F300, 0x1F567}, /* Miscellaneous Symbols and Pictographs */
- {0x20000, 0x2FFFD}, {0x30000, 0x3FFFD},
- };
-
- if (bsearch ((void *)(uintptr_t)c, wide, (sizeof (wide) / sizeof ((wide)[0])), sizeof wide[0],
- interval_compare))
- return true;
-
- return false;
-}
-
-const char utf8_skip_data[256] = {
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
- 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1
-};
diff --git a/src/basic/gunicode.h b/src/basic/gunicode.h
deleted file mode 100644
index 5975bc8fc9..0000000000
--- a/src/basic/gunicode.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#pragma once
-
-/* gunicode.h - Unicode manipulation functions
- *
- * Copyright (C) 1999, 2000 Tom Tromey
- * Copyright 2000, 2005 Red Hat, Inc.
- */
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-char *utf8_prev_char (const char *p);
-
-extern const char utf8_skip_data[256];
-
-/**
- * g_utf8_next_char:
- * @p: Pointer to the start of a valid UTF-8 character
- *
- * Skips to the next character in a UTF-8 string. The string must be
- * valid; this macro is as fast as possible, and has no error-checking.
- * You would use this macro to iterate over a string character by
- * character. The macro returns the start of the next UTF-8 character.
- * Before using this macro, use g_utf8_validate() to validate strings
- * that may contain invalid UTF-8.
- */
-#define utf8_next_char(p) (char *)((p) + utf8_skip_data[*(const unsigned char *)(p)])
-
-bool unichar_iswide (uint32_t c);
diff --git a/src/basic/hash-funcs.c b/src/basic/hash-funcs.c
deleted file mode 100644
index c3a4a011b5..0000000000
--- a/src/basic/hash-funcs.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2014 Michal Schmidt
-
- 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 "hash-funcs.h"
-
-void string_hash_func(const void *p, struct siphash *state) {
- siphash24_compress(p, strlen(p) + 1, state);
-}
-
-int string_compare_func(const void *a, const void *b) {
- return strcmp(a, b);
-}
-
-const struct hash_ops string_hash_ops = {
- .hash = string_hash_func,
- .compare = string_compare_func
-};
-
-void trivial_hash_func(const void *p, struct siphash *state) {
- siphash24_compress(&p, sizeof(p), state);
-}
-
-int trivial_compare_func(const void *a, const void *b) {
- return a < b ? -1 : (a > b ? 1 : 0);
-}
-
-const struct hash_ops trivial_hash_ops = {
- .hash = trivial_hash_func,
- .compare = trivial_compare_func
-};
-
-void uint64_hash_func(const void *p, struct siphash *state) {
- siphash24_compress(p, sizeof(uint64_t), state);
-}
-
-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);
-}
-
-const struct hash_ops uint64_hash_ops = {
- .hash = uint64_hash_func,
- .compare = uint64_compare_func
-};
-
-#if SIZEOF_DEV_T != 8
-void devt_hash_func(const void *p, struct siphash *state) {
- siphash24_compress(p, sizeof(dev_t), state);
-}
-
-int devt_compare_func(const void *_a, const void *_b) {
- dev_t a, b;
- a = *(const dev_t*) _a;
- b = *(const dev_t*) _b;
- return a < b ? -1 : (a > b ? 1 : 0);
-}
-
-const struct hash_ops devt_hash_ops = {
- .hash = devt_hash_func,
- .compare = devt_compare_func
-};
-#endif
diff --git a/src/basic/hash-funcs.h b/src/basic/hash-funcs.h
deleted file mode 100644
index 299189d143..0000000000
--- a/src/basic/hash-funcs.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2014 Michal Schmidt
-
- 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"
-#include "siphash24.h"
-
-typedef void (*hash_func_t)(const void *p, struct siphash *state);
-typedef int (*compare_func_t)(const void *a, const void *b);
-
-struct hash_ops {
- hash_func_t hash;
- compare_func_t compare;
-};
-
-void string_hash_func(const void *p, struct siphash *state);
-int string_compare_func(const void *a, const void *b) _pure_;
-extern const struct hash_ops string_hash_ops;
-
-/* This will compare the passed pointers directly, and will not
- * dereference them. This is hence not useful for strings or
- * suchlike. */
-void trivial_hash_func(const void *p, struct siphash *state);
-int trivial_compare_func(const void *a, const void *b) _const_;
-extern const struct hash_ops trivial_hash_ops;
-
-/* 32bit values we can always just embed in the pointer itself, but
- * in order to support 32bit archs we need store 64bit values
- * indirectly, since they don't fit in a pointer. */
-void uint64_hash_func(const void *p, struct siphash *state);
-int uint64_compare_func(const void *a, const void *b) _pure_;
-extern const struct hash_ops uint64_hash_ops;
-
-/* On some archs dev_t is 32bit, and on others 64bit. And sometimes
- * it's 64bit on 32bit archs, and sometimes 32bit on 64bit archs. Yuck! */
-#if SIZEOF_DEV_T != 8
-void devt_hash_func(const void *p, struct siphash *state) _pure_;
-int devt_compare_func(const void *a, const void *b) _pure_;
-extern const struct hash_ops devt_hash_ops = {
- .hash = devt_hash_func,
- .compare = devt_compare_func
-};
-#else
-#define devt_hash_func uint64_hash_func
-#define devt_compare_func uint64_compare_func
-#define devt_hash_ops uint64_hash_ops
-#endif
diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c
deleted file mode 100644
index 50fefb0b54..0000000000
--- a/src/basic/hashmap.c
+++ /dev/null
@@ -1,1828 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2014 Michal Schmidt
-
- 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 <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "alloc-util.h"
-#include "hashmap.h"
-#include "macro.h"
-#include "mempool.h"
-#include "process-util.h"
-#include "random-util.h"
-#include "set.h"
-#include "siphash24.h"
-#include "strv.h"
-#include "util.h"
-
-#ifdef ENABLE_DEBUG_HASHMAP
-#include <pthread.h>
-#include "list.h"
-#endif
-
-/*
- * Implementation of hashmaps.
- * Addressing: open
- * - uses less RAM compared to closed addressing (chaining), because
- * our entries are small (especially in Sets, which tend to contain
- * the majority of entries in systemd).
- * Collision resolution: Robin Hood
- * - tends to equalize displacement of entries from their optimal buckets.
- * Probe sequence: linear
- * - though theoretically worse than random probing/uniform hashing/double
- * hashing, it is good for cache locality.
- *
- * References:
- * Celis, P. 1986. Robin Hood Hashing.
- * Ph.D. Dissertation. University of Waterloo, Waterloo, Ont., Canada, Canada.
- * https://cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf
- * - The results are derived for random probing. Suggests deletion with
- * tombstones and two mean-centered search methods. None of that works
- * well for linear probing.
- *
- * Janson, S. 2005. Individual displacements for linear probing hashing with different insertion policies.
- * ACM Trans. Algorithms 1, 2 (October 2005), 177-213.
- * DOI=10.1145/1103963.1103964 http://doi.acm.org/10.1145/1103963.1103964
- * http://www.math.uu.se/~svante/papers/sj157.pdf
- * - Applies to Robin Hood with linear probing. Contains remarks on
- * the unsuitability of mean-centered search with linear probing.
- *
- * Viola, A. 2005. Exact distribution of individual displacements in linear probing hashing.
- * ACM Trans. Algorithms 1, 2 (October 2005), 214-242.
- * DOI=10.1145/1103963.1103965 http://doi.acm.org/10.1145/1103963.1103965
- * - Similar to Janson. Note that Viola writes about C_{m,n} (number of probes
- * in a successful search), and Janson writes about displacement. C = d + 1.
- *
- * Goossaert, E. 2013. Robin Hood hashing: backward shift deletion.
- * http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/
- * - Explanation of backward shift deletion with pictures.
- *
- * Khuong, P. 2013. The Other Robin Hood Hashing.
- * http://www.pvk.ca/Blog/2013/11/26/the-other-robin-hood-hashing/
- * - Short summary of random vs. linear probing, and tombstones vs. backward shift.
- */
-
-/*
- * XXX Ideas for improvement:
- * For unordered hashmaps, randomize iteration order, similarly to Perl:
- * http://blog.booking.com/hardening-perls-hash-function.html
- */
-
-/* INV_KEEP_FREE = 1 / (1 - max_load_factor)
- * e.g. 1 / (1 - 0.8) = 5 ... keep one fifth of the buckets free. */
-#define INV_KEEP_FREE 5U
-
-/* Fields common to entries of all hashmap/set types */
-struct hashmap_base_entry {
- const void *key;
-};
-
-/* Entry types for specific hashmap/set types
- * hashmap_base_entry must be at the beginning of each entry struct. */
-
-struct plain_hashmap_entry {
- struct hashmap_base_entry b;
- void *value;
-};
-
-struct ordered_hashmap_entry {
- struct plain_hashmap_entry p;
- unsigned iterate_next, iterate_previous;
-};
-
-struct set_entry {
- struct hashmap_base_entry b;
-};
-
-/* In several functions it is advantageous to have the hash table extended
- * virtually by a couple of additional buckets. We reserve special index values
- * for these "swap" buckets. */
-#define _IDX_SWAP_BEGIN (UINT_MAX - 3)
-#define IDX_PUT (_IDX_SWAP_BEGIN + 0)
-#define IDX_TMP (_IDX_SWAP_BEGIN + 1)
-#define _IDX_SWAP_END (_IDX_SWAP_BEGIN + 2)
-
-#define IDX_FIRST (UINT_MAX - 1) /* special index for freshly initialized iterators */
-#define IDX_NIL UINT_MAX /* special index value meaning "none" or "end" */
-
-assert_cc(IDX_FIRST == _IDX_SWAP_END);
-assert_cc(IDX_FIRST == _IDX_ITERATOR_FIRST);
-
-/* Storage space for the "swap" buckets.
- * All entry types can fit into a ordered_hashmap_entry. */
-struct swap_entries {
- struct ordered_hashmap_entry e[_IDX_SWAP_END - _IDX_SWAP_BEGIN];
-};
-
-/* Distance from Initial Bucket */
-typedef uint8_t dib_raw_t;
-#define DIB_RAW_OVERFLOW ((dib_raw_t)0xfdU) /* indicates DIB value is greater than representable */
-#define DIB_RAW_REHASH ((dib_raw_t)0xfeU) /* entry yet to be rehashed during in-place resize */
-#define DIB_RAW_FREE ((dib_raw_t)0xffU) /* a free bucket */
-#define DIB_RAW_INIT ((char)DIB_RAW_FREE) /* a byte to memset a DIB store with when initializing */
-
-#define DIB_FREE UINT_MAX
-
-#ifdef ENABLE_DEBUG_HASHMAP
-struct hashmap_debug_info {
- LIST_FIELDS(struct hashmap_debug_info, debug_list);
- unsigned max_entries; /* high watermark of n_entries */
-
- /* who allocated this hashmap */
- int line;
- const char *file;
- const char *func;
-
- /* fields to detect modification while iterating */
- unsigned put_count; /* counts puts into the hashmap */
- unsigned rem_count; /* counts removals from hashmap */
- unsigned last_rem_idx; /* remembers last removal index */
-};
-
-/* Tracks all existing hashmaps. Get at it from gdb. See sd_dump_hashmaps.py */
-static LIST_HEAD(struct hashmap_debug_info, hashmap_debug_list);
-static pthread_mutex_t hashmap_debug_list_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-#define HASHMAP_DEBUG_FIELDS struct hashmap_debug_info debug;
-
-#else /* !ENABLE_DEBUG_HASHMAP */
-#define HASHMAP_DEBUG_FIELDS
-#endif /* ENABLE_DEBUG_HASHMAP */
-
-enum HashmapType {
- HASHMAP_TYPE_PLAIN,
- HASHMAP_TYPE_ORDERED,
- HASHMAP_TYPE_SET,
- _HASHMAP_TYPE_MAX
-};
-
-struct _packed_ indirect_storage {
- void *storage; /* where buckets and DIBs are stored */
- uint8_t hash_key[HASH_KEY_SIZE]; /* hash key; changes during resize */
-
- unsigned n_entries; /* number of stored entries */
- unsigned n_buckets; /* number of buckets */
-
- unsigned idx_lowest_entry; /* Index below which all buckets are free.
- Makes "while(hashmap_steal_first())" loops
- O(n) instead of O(n^2) for unordered hashmaps. */
- uint8_t _pad[3]; /* padding for the whole HashmapBase */
- /* The bitfields in HashmapBase complete the alignment of the whole thing. */
-};
-
-struct direct_storage {
- /* This gives us 39 bytes on 64bit, or 35 bytes on 32bit.
- * That's room for 4 set_entries + 4 DIB bytes + 3 unused bytes on 64bit,
- * or 7 set_entries + 7 DIB bytes + 0 unused bytes on 32bit. */
- uint8_t storage[sizeof(struct indirect_storage)];
-};
-
-#define DIRECT_BUCKETS(entry_t) \
- (sizeof(struct direct_storage) / (sizeof(entry_t) + sizeof(dib_raw_t)))
-
-/* We should be able to store at least one entry directly. */
-assert_cc(DIRECT_BUCKETS(struct ordered_hashmap_entry) >= 1);
-
-/* We have 3 bits for n_direct_entries. */
-assert_cc(DIRECT_BUCKETS(struct set_entry) < (1 << 3));
-
-/* Hashmaps with directly stored entries all use this shared hash key.
- * It's no big deal if the key is guessed, because there can be only
- * a handful of directly stored entries in a hashmap. When a hashmap
- * outgrows direct storage, it gets its own key for indirect storage. */
-static uint8_t shared_hash_key[HASH_KEY_SIZE];
-static bool shared_hash_key_initialized;
-
-/* Fields that all hashmap/set types must have */
-struct HashmapBase {
- const struct hash_ops *hash_ops; /* hash and compare ops to use */
-
- union _packed_ {
- struct indirect_storage indirect; /* if has_indirect */
- struct direct_storage direct; /* if !has_indirect */
- };
-
- enum HashmapType type:2; /* HASHMAP_TYPE_* */
- bool has_indirect:1; /* whether indirect storage is used */
- unsigned n_direct_entries:3; /* Number of entries in direct storage.
- * Only valid if !has_indirect. */
- bool from_pool:1; /* whether was allocated from mempool */
- HASHMAP_DEBUG_FIELDS /* optional hashmap_debug_info */
-};
-
-/* Specific hash types
- * HashmapBase must be at the beginning of each hashmap struct. */
-
-struct Hashmap {
- struct HashmapBase b;
-};
-
-struct OrderedHashmap {
- struct HashmapBase b;
- unsigned iterate_list_head, iterate_list_tail;
-};
-
-struct Set {
- struct HashmapBase b;
-};
-
-DEFINE_MEMPOOL(hashmap_pool, Hashmap, 8);
-DEFINE_MEMPOOL(ordered_hashmap_pool, OrderedHashmap, 8);
-/* No need for a separate Set pool */
-assert_cc(sizeof(Hashmap) == sizeof(Set));
-
-struct hashmap_type_info {
- size_t head_size;
- size_t entry_size;
- struct mempool *mempool;
- unsigned n_direct_buckets;
-};
-
-static const struct hashmap_type_info hashmap_type_info[_HASHMAP_TYPE_MAX] = {
- [HASHMAP_TYPE_PLAIN] = {
- .head_size = sizeof(Hashmap),
- .entry_size = sizeof(struct plain_hashmap_entry),
- .mempool = &hashmap_pool,
- .n_direct_buckets = DIRECT_BUCKETS(struct plain_hashmap_entry),
- },
- [HASHMAP_TYPE_ORDERED] = {
- .head_size = sizeof(OrderedHashmap),
- .entry_size = sizeof(struct ordered_hashmap_entry),
- .mempool = &ordered_hashmap_pool,
- .n_direct_buckets = DIRECT_BUCKETS(struct ordered_hashmap_entry),
- },
- [HASHMAP_TYPE_SET] = {
- .head_size = sizeof(Set),
- .entry_size = sizeof(struct set_entry),
- .mempool = &hashmap_pool,
- .n_direct_buckets = DIRECT_BUCKETS(struct set_entry),
- },
-};
-
-static unsigned n_buckets(HashmapBase *h) {
- return h->has_indirect ? h->indirect.n_buckets
- : hashmap_type_info[h->type].n_direct_buckets;
-}
-
-static unsigned n_entries(HashmapBase *h) {
- return h->has_indirect ? h->indirect.n_entries
- : h->n_direct_entries;
-}
-
-static void n_entries_inc(HashmapBase *h) {
- if (h->has_indirect)
- h->indirect.n_entries++;
- else
- h->n_direct_entries++;
-}
-
-static void n_entries_dec(HashmapBase *h) {
- if (h->has_indirect)
- h->indirect.n_entries--;
- else
- h->n_direct_entries--;
-}
-
-static void *storage_ptr(HashmapBase *h) {
- return h->has_indirect ? h->indirect.storage
- : h->direct.storage;
-}
-
-static uint8_t *hash_key(HashmapBase *h) {
- return h->has_indirect ? h->indirect.hash_key
- : shared_hash_key;
-}
-
-static unsigned base_bucket_hash(HashmapBase *h, const void *p) {
- struct siphash state;
- uint64_t hash;
-
- siphash24_init(&state, hash_key(h));
-
- h->hash_ops->hash(p, &state);
-
- hash = siphash24_finalize(&state);
-
- return (unsigned) (hash % n_buckets(h));
-}
-#define bucket_hash(h, p) base_bucket_hash(HASHMAP_BASE(h), p)
-
-static void get_hash_key(uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok) {
- static uint8_t current[HASH_KEY_SIZE];
- static bool current_initialized = false;
-
- /* Returns a hash function key to use. In order to keep things
- * fast we will not generate a new key each time we allocate a
- * new hash table. Instead, we'll just reuse the most recently
- * generated one, except if we never generated one or when we
- * are rehashing an entire hash table because we reached a
- * fill level */
-
- if (!current_initialized || !reuse_is_ok) {
- random_bytes(current, sizeof(current));
- current_initialized = true;
- }
-
- memcpy(hash_key, current, sizeof(current));
-}
-
-static struct hashmap_base_entry *bucket_at(HashmapBase *h, unsigned idx) {
- return (struct hashmap_base_entry*)
- ((uint8_t*) storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size);
-}
-
-static struct plain_hashmap_entry *plain_bucket_at(Hashmap *h, unsigned idx) {
- return (struct plain_hashmap_entry*) bucket_at(HASHMAP_BASE(h), idx);
-}
-
-static struct ordered_hashmap_entry *ordered_bucket_at(OrderedHashmap *h, unsigned idx) {
- return (struct ordered_hashmap_entry*) bucket_at(HASHMAP_BASE(h), idx);
-}
-
-static struct set_entry *set_bucket_at(Set *h, unsigned idx) {
- return (struct set_entry*) bucket_at(HASHMAP_BASE(h), idx);
-}
-
-static struct ordered_hashmap_entry *bucket_at_swap(struct swap_entries *swap, unsigned idx) {
- return &swap->e[idx - _IDX_SWAP_BEGIN];
-}
-
-/* Returns a pointer to the bucket at index idx.
- * Understands real indexes and swap indexes, hence "_virtual". */
-static struct hashmap_base_entry *bucket_at_virtual(HashmapBase *h, struct swap_entries *swap,
- unsigned idx) {
- if (idx < _IDX_SWAP_BEGIN)
- return bucket_at(h, idx);
-
- if (idx < _IDX_SWAP_END)
- return &bucket_at_swap(swap, idx)->p.b;
-
- assert_not_reached("Invalid index");
-}
-
-static dib_raw_t *dib_raw_ptr(HashmapBase *h) {
- return (dib_raw_t*)
- ((uint8_t*) storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h));
-}
-
-static unsigned bucket_distance(HashmapBase *h, unsigned idx, unsigned from) {
- return idx >= from ? idx - from
- : n_buckets(h) + idx - from;
-}
-
-static unsigned bucket_calculate_dib(HashmapBase *h, unsigned idx, dib_raw_t raw_dib) {
- unsigned initial_bucket;
-
- if (raw_dib == DIB_RAW_FREE)
- return DIB_FREE;
-
- if (_likely_(raw_dib < DIB_RAW_OVERFLOW))
- return raw_dib;
-
- /*
- * Having an overflow DIB value is very unlikely. The hash function
- * would have to be bad. For example, in a table of size 2^24 filled
- * to load factor 0.9 the maximum observed DIB is only about 60.
- * In theory (assuming I used Maxima correctly), for an infinite size
- * hash table with load factor 0.8 the probability of a given entry
- * having DIB > 40 is 1.9e-8.
- * This returns the correct DIB value by recomputing the hash value in
- * the unlikely case. XXX Hitting this case could be a hint to rehash.
- */
- initial_bucket = bucket_hash(h, bucket_at(h, idx)->key);
- return bucket_distance(h, idx, initial_bucket);
-}
-
-static void bucket_set_dib(HashmapBase *h, unsigned idx, unsigned dib) {
- dib_raw_ptr(h)[idx] = dib != DIB_FREE ? MIN(dib, DIB_RAW_OVERFLOW) : DIB_RAW_FREE;
-}
-
-static unsigned skip_free_buckets(HashmapBase *h, unsigned idx) {
- dib_raw_t *dibs;
-
- dibs = dib_raw_ptr(h);
-
- for ( ; idx < n_buckets(h); idx++)
- if (dibs[idx] != DIB_RAW_FREE)
- return idx;
-
- return IDX_NIL;
-}
-
-static void bucket_mark_free(HashmapBase *h, unsigned idx) {
- memzero(bucket_at(h, idx), hashmap_type_info[h->type].entry_size);
- bucket_set_dib(h, idx, DIB_FREE);
-}
-
-static void bucket_move_entry(HashmapBase *h, struct swap_entries *swap,
- unsigned from, unsigned to) {
- struct hashmap_base_entry *e_from, *e_to;
-
- assert(from != to);
-
- e_from = bucket_at_virtual(h, swap, from);
- e_to = bucket_at_virtual(h, swap, to);
-
- memcpy(e_to, e_from, hashmap_type_info[h->type].entry_size);
-
- if (h->type == HASHMAP_TYPE_ORDERED) {
- OrderedHashmap *lh = (OrderedHashmap*) h;
- struct ordered_hashmap_entry *le, *le_to;
-
- le_to = (struct ordered_hashmap_entry*) e_to;
-
- if (le_to->iterate_next != IDX_NIL) {
- le = (struct ordered_hashmap_entry*)
- bucket_at_virtual(h, swap, le_to->iterate_next);
- le->iterate_previous = to;
- }
-
- if (le_to->iterate_previous != IDX_NIL) {
- le = (struct ordered_hashmap_entry*)
- bucket_at_virtual(h, swap, le_to->iterate_previous);
- le->iterate_next = to;
- }
-
- if (lh->iterate_list_head == from)
- lh->iterate_list_head = to;
- if (lh->iterate_list_tail == from)
- lh->iterate_list_tail = to;
- }
-}
-
-static unsigned next_idx(HashmapBase *h, unsigned idx) {
- return (idx + 1U) % n_buckets(h);
-}
-
-static unsigned prev_idx(HashmapBase *h, unsigned idx) {
- return (n_buckets(h) + idx - 1U) % n_buckets(h);
-}
-
-static void *entry_value(HashmapBase *h, struct hashmap_base_entry *e) {
- switch (h->type) {
-
- case HASHMAP_TYPE_PLAIN:
- case HASHMAP_TYPE_ORDERED:
- return ((struct plain_hashmap_entry*)e)->value;
-
- case HASHMAP_TYPE_SET:
- return (void*) e->key;
-
- default:
- assert_not_reached("Unknown hashmap type");
- }
-}
-
-static void base_remove_entry(HashmapBase *h, unsigned idx) {
- unsigned left, right, prev, dib;
- dib_raw_t raw_dib, *dibs;
-
- dibs = dib_raw_ptr(h);
- assert(dibs[idx] != DIB_RAW_FREE);
-
-#ifdef ENABLE_DEBUG_HASHMAP
- h->debug.rem_count++;
- h->debug.last_rem_idx = idx;
-#endif
-
- left = idx;
- /* Find the stop bucket ("right"). It is either free or has DIB == 0. */
- for (right = next_idx(h, left); ; right = next_idx(h, right)) {
- raw_dib = dibs[right];
- if (raw_dib == 0 || raw_dib == DIB_RAW_FREE)
- break;
-
- /* The buckets are not supposed to be all occupied and with DIB > 0.
- * That would mean we could make everyone better off by shifting them
- * backward. This scenario is impossible. */
- assert(left != right);
- }
-
- if (h->type == HASHMAP_TYPE_ORDERED) {
- OrderedHashmap *lh = (OrderedHashmap*) h;
- struct ordered_hashmap_entry *le = ordered_bucket_at(lh, idx);
-
- if (le->iterate_next != IDX_NIL)
- ordered_bucket_at(lh, le->iterate_next)->iterate_previous = le->iterate_previous;
- else
- lh->iterate_list_tail = le->iterate_previous;
-
- if (le->iterate_previous != IDX_NIL)
- ordered_bucket_at(lh, le->iterate_previous)->iterate_next = le->iterate_next;
- else
- lh->iterate_list_head = le->iterate_next;
- }
-
- /* Now shift all buckets in the interval (left, right) one step backwards */
- for (prev = left, left = next_idx(h, left); left != right;
- prev = left, left = next_idx(h, left)) {
- dib = bucket_calculate_dib(h, left, dibs[left]);
- assert(dib != 0);
- bucket_move_entry(h, NULL, left, prev);
- bucket_set_dib(h, prev, dib - 1);
- }
-
- bucket_mark_free(h, prev);
- n_entries_dec(h);
-}
-#define remove_entry(h, idx) base_remove_entry(HASHMAP_BASE(h), idx)
-
-static unsigned hashmap_iterate_in_insertion_order(OrderedHashmap *h, Iterator *i) {
- struct ordered_hashmap_entry *e;
- unsigned idx;
-
- assert(h);
- assert(i);
-
- if (i->idx == IDX_NIL)
- goto at_end;
-
- if (i->idx == IDX_FIRST && h->iterate_list_head == IDX_NIL)
- goto at_end;
-
- if (i->idx == IDX_FIRST) {
- idx = h->iterate_list_head;
- e = ordered_bucket_at(h, idx);
- } else {
- idx = i->idx;
- e = ordered_bucket_at(h, idx);
- /*
- * We allow removing the current entry while iterating, but removal may cause
- * a backward shift. The next entry may thus move one bucket to the left.
- * To detect when it happens, we remember the key pointer of the entry we were
- * going to iterate next. If it does not match, there was a backward shift.
- */
- if (e->p.b.key != i->next_key) {
- idx = prev_idx(HASHMAP_BASE(h), idx);
- e = ordered_bucket_at(h, idx);
- }
- assert(e->p.b.key == i->next_key);
- }
-
-#ifdef ENABLE_DEBUG_HASHMAP
- i->prev_idx = idx;
-#endif
-
- if (e->iterate_next != IDX_NIL) {
- struct ordered_hashmap_entry *n;
- i->idx = e->iterate_next;
- n = ordered_bucket_at(h, i->idx);
- i->next_key = n->p.b.key;
- } else
- i->idx = IDX_NIL;
-
- return idx;
-
-at_end:
- i->idx = IDX_NIL;
- return IDX_NIL;
-}
-
-static unsigned hashmap_iterate_in_internal_order(HashmapBase *h, Iterator *i) {
- unsigned idx;
-
- assert(h);
- assert(i);
-
- if (i->idx == IDX_NIL)
- goto at_end;
-
- if (i->idx == IDX_FIRST) {
- /* fast forward to the first occupied bucket */
- if (h->has_indirect) {
- i->idx = skip_free_buckets(h, h->indirect.idx_lowest_entry);
- h->indirect.idx_lowest_entry = i->idx;
- } else
- i->idx = skip_free_buckets(h, 0);
-
- if (i->idx == IDX_NIL)
- goto at_end;
- } else {
- struct hashmap_base_entry *e;
-
- assert(i->idx > 0);
-
- e = bucket_at(h, i->idx);
- /*
- * We allow removing the current entry while iterating, but removal may cause
- * a backward shift. The next entry may thus move one bucket to the left.
- * To detect when it happens, we remember the key pointer of the entry we were
- * going to iterate next. If it does not match, there was a backward shift.
- */
- if (e->key != i->next_key)
- e = bucket_at(h, --i->idx);
-
- assert(e->key == i->next_key);
- }
-
- idx = i->idx;
-#ifdef ENABLE_DEBUG_HASHMAP
- i->prev_idx = idx;
-#endif
-
- i->idx = skip_free_buckets(h, i->idx + 1);
- if (i->idx != IDX_NIL)
- i->next_key = bucket_at(h, i->idx)->key;
- else
- i->idx = IDX_NIL;
-
- return idx;
-
-at_end:
- i->idx = IDX_NIL;
- return IDX_NIL;
-}
-
-static unsigned hashmap_iterate_entry(HashmapBase *h, Iterator *i) {
- if (!h) {
- i->idx = IDX_NIL;
- return IDX_NIL;
- }
-
-#ifdef ENABLE_DEBUG_HASHMAP
- if (i->idx == IDX_FIRST) {
- i->put_count = h->debug.put_count;
- i->rem_count = h->debug.rem_count;
- } else {
- /* While iterating, must not add any new entries */
- assert(i->put_count == h->debug.put_count);
- /* ... or remove entries other than the current one */
- assert(i->rem_count == h->debug.rem_count ||
- (i->rem_count == h->debug.rem_count - 1 &&
- i->prev_idx == h->debug.last_rem_idx));
- /* Reset our removals counter */
- i->rem_count = h->debug.rem_count;
- }
-#endif
-
- return h->type == HASHMAP_TYPE_ORDERED ? hashmap_iterate_in_insertion_order((OrderedHashmap*) h, i)
- : hashmap_iterate_in_internal_order(h, i);
-}
-
-bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key) {
- struct hashmap_base_entry *e;
- void *data;
- unsigned idx;
-
- idx = hashmap_iterate_entry(h, i);
- if (idx == IDX_NIL) {
- if (value)
- *value = NULL;
- if (key)
- *key = NULL;
-
- return false;
- }
-
- e = bucket_at(h, idx);
- data = entry_value(h, e);
- if (value)
- *value = data;
- if (key)
- *key = e->key;
-
- return true;
-}
-
-bool set_iterate(Set *s, Iterator *i, void **value) {
- return internal_hashmap_iterate(HASHMAP_BASE(s), i, value, NULL);
-}
-
-#define HASHMAP_FOREACH_IDX(idx, h, i) \
- for ((i) = ITERATOR_FIRST, (idx) = hashmap_iterate_entry((h), &(i)); \
- (idx != IDX_NIL); \
- (idx) = hashmap_iterate_entry((h), &(i)))
-
-static void reset_direct_storage(HashmapBase *h) {
- const struct hashmap_type_info *hi = &hashmap_type_info[h->type];
- void *p;
-
- assert(!h->has_indirect);
-
- p = mempset(h->direct.storage, 0, hi->entry_size * hi->n_direct_buckets);
- memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets);
-}
-
-static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) {
- HashmapBase *h;
- const struct hashmap_type_info *hi = &hashmap_type_info[type];
- bool use_pool;
-
- use_pool = is_main_thread();
-
- h = use_pool ? mempool_alloc0_tile(hi->mempool) : malloc0(hi->head_size);
-
- if (!h)
- return NULL;
-
- h->type = type;
- h->from_pool = use_pool;
- h->hash_ops = hash_ops ? hash_ops : &trivial_hash_ops;
-
- if (type == HASHMAP_TYPE_ORDERED) {
- OrderedHashmap *lh = (OrderedHashmap*)h;
- lh->iterate_list_head = lh->iterate_list_tail = IDX_NIL;
- }
-
- reset_direct_storage(h);
-
- if (!shared_hash_key_initialized) {
- random_bytes(shared_hash_key, sizeof(shared_hash_key));
- shared_hash_key_initialized= true;
- }
-
-#ifdef ENABLE_DEBUG_HASHMAP
- h->debug.func = func;
- h->debug.file = file;
- h->debug.line = line;
- assert_se(pthread_mutex_lock(&hashmap_debug_list_mutex) == 0);
- LIST_PREPEND(debug_list, hashmap_debug_list, &h->debug);
- assert_se(pthread_mutex_unlock(&hashmap_debug_list_mutex) == 0);
-#endif
-
- return h;
-}
-
-Hashmap *internal_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return (Hashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS);
-}
-
-OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return (OrderedHashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS);
-}
-
-Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return (Set*) hashmap_base_new(hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
-}
-
-static int hashmap_base_ensure_allocated(HashmapBase **h, const struct hash_ops *hash_ops,
- enum HashmapType type HASHMAP_DEBUG_PARAMS) {
- HashmapBase *q;
-
- assert(h);
-
- if (*h)
- return 0;
-
- q = hashmap_base_new(hash_ops, type HASHMAP_DEBUG_PASS_ARGS);
- if (!q)
- return -ENOMEM;
-
- *h = q;
- return 0;
-}
-
-int internal_hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS);
-}
-
-int internal_ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS);
-}
-
-int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return hashmap_base_ensure_allocated((HashmapBase**)s, hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
-}
-
-static void hashmap_free_no_clear(HashmapBase *h) {
- assert(!h->has_indirect);
- assert(!h->n_direct_entries);
-
-#ifdef ENABLE_DEBUG_HASHMAP
- assert_se(pthread_mutex_lock(&hashmap_debug_list_mutex) == 0);
- LIST_REMOVE(debug_list, hashmap_debug_list, &h->debug);
- assert_se(pthread_mutex_unlock(&hashmap_debug_list_mutex) == 0);
-#endif
-
- if (h->from_pool)
- mempool_free_tile(hashmap_type_info[h->type].mempool, h);
- else
- free(h);
-}
-
-HashmapBase *internal_hashmap_free(HashmapBase *h) {
-
- /* Free the hashmap, but nothing in it */
-
- if (h) {
- internal_hashmap_clear(h);
- hashmap_free_no_clear(h);
- }
-
- return NULL;
-}
-
-HashmapBase *internal_hashmap_free_free(HashmapBase *h) {
-
- /* Free the hashmap and all data objects in it, but not the
- * keys */
-
- if (h) {
- internal_hashmap_clear_free(h);
- hashmap_free_no_clear(h);
- }
-
- return NULL;
-}
-
-Hashmap *hashmap_free_free_free(Hashmap *h) {
-
- /* Free the hashmap and all data and key objects in it */
-
- if (h) {
- hashmap_clear_free_free(h);
- hashmap_free_no_clear(HASHMAP_BASE(h));
- }
-
- return NULL;
-}
-
-void internal_hashmap_clear(HashmapBase *h) {
- if (!h)
- return;
-
- if (h->has_indirect) {
- free(h->indirect.storage);
- h->has_indirect = false;
- }
-
- h->n_direct_entries = 0;
- reset_direct_storage(h);
-
- if (h->type == HASHMAP_TYPE_ORDERED) {
- OrderedHashmap *lh = (OrderedHashmap*) h;
- lh->iterate_list_head = lh->iterate_list_tail = IDX_NIL;
- }
-}
-
-void internal_hashmap_clear_free(HashmapBase *h) {
- unsigned idx;
-
- if (!h)
- return;
-
- for (idx = skip_free_buckets(h, 0); idx != IDX_NIL;
- idx = skip_free_buckets(h, idx + 1))
- free(entry_value(h, bucket_at(h, idx)));
-
- internal_hashmap_clear(h);
-}
-
-void hashmap_clear_free_free(Hashmap *h) {
- unsigned idx;
-
- if (!h)
- return;
-
- for (idx = skip_free_buckets(HASHMAP_BASE(h), 0); idx != IDX_NIL;
- idx = skip_free_buckets(HASHMAP_BASE(h), idx + 1)) {
- struct plain_hashmap_entry *e = plain_bucket_at(h, idx);
- free((void*)e->b.key);
- free(e->value);
- }
-
- internal_hashmap_clear(HASHMAP_BASE(h));
-}
-
-static int resize_buckets(HashmapBase *h, unsigned entries_add);
-
-/*
- * Finds an empty bucket to put an entry into, starting the scan at 'idx'.
- * Performs Robin Hood swaps as it goes. The entry to put must be placed
- * by the caller into swap slot IDX_PUT.
- * If used for in-place resizing, may leave a displaced entry in swap slot
- * IDX_PUT. Caller must rehash it next.
- * Returns: true if it left a displaced entry to rehash next in IDX_PUT,
- * false otherwise.
- */
-static bool hashmap_put_robin_hood(HashmapBase *h, unsigned idx,
- struct swap_entries *swap) {
- dib_raw_t raw_dib, *dibs;
- unsigned dib, distance;
-
-#ifdef ENABLE_DEBUG_HASHMAP
- h->debug.put_count++;
-#endif
-
- dibs = dib_raw_ptr(h);
-
- for (distance = 0; ; distance++) {
- raw_dib = dibs[idx];
- if (raw_dib == DIB_RAW_FREE || raw_dib == DIB_RAW_REHASH) {
- if (raw_dib == DIB_RAW_REHASH)
- bucket_move_entry(h, swap, idx, IDX_TMP);
-
- if (h->has_indirect && h->indirect.idx_lowest_entry > idx)
- h->indirect.idx_lowest_entry = idx;
-
- bucket_set_dib(h, idx, distance);
- bucket_move_entry(h, swap, IDX_PUT, idx);
- if (raw_dib == DIB_RAW_REHASH) {
- bucket_move_entry(h, swap, IDX_TMP, IDX_PUT);
- return true;
- }
-
- return false;
- }
-
- dib = bucket_calculate_dib(h, idx, raw_dib);
-
- if (dib < distance) {
- /* Found a wealthier entry. Go Robin Hood! */
- bucket_set_dib(h, idx, distance);
-
- /* swap the entries */
- bucket_move_entry(h, swap, idx, IDX_TMP);
- bucket_move_entry(h, swap, IDX_PUT, idx);
- bucket_move_entry(h, swap, IDX_TMP, IDX_PUT);
-
- distance = dib;
- }
-
- idx = next_idx(h, idx);
- }
-}
-
-/*
- * Puts an entry into a hashmap, boldly - no check whether key already exists.
- * The caller must place the entry (only its key and value, not link indexes)
- * in swap slot IDX_PUT.
- * Caller must ensure: the key does not exist yet in the hashmap.
- * that resize is not needed if !may_resize.
- * Returns: 1 if entry was put successfully.
- * -ENOMEM if may_resize==true and resize failed with -ENOMEM.
- * Cannot return -ENOMEM if !may_resize.
- */
-static int hashmap_base_put_boldly(HashmapBase *h, unsigned idx,
- struct swap_entries *swap, bool may_resize) {
- struct ordered_hashmap_entry *new_entry;
- int r;
-
- assert(idx < n_buckets(h));
-
- new_entry = bucket_at_swap(swap, IDX_PUT);
-
- if (may_resize) {
- r = resize_buckets(h, 1);
- if (r < 0)
- return r;
- if (r > 0)
- idx = bucket_hash(h, new_entry->p.b.key);
- }
- assert(n_entries(h) < n_buckets(h));
-
- if (h->type == HASHMAP_TYPE_ORDERED) {
- OrderedHashmap *lh = (OrderedHashmap*) h;
-
- new_entry->iterate_next = IDX_NIL;
- new_entry->iterate_previous = lh->iterate_list_tail;
-
- if (lh->iterate_list_tail != IDX_NIL) {
- struct ordered_hashmap_entry *old_tail;
-
- old_tail = ordered_bucket_at(lh, lh->iterate_list_tail);
- assert(old_tail->iterate_next == IDX_NIL);
- old_tail->iterate_next = IDX_PUT;
- }
-
- lh->iterate_list_tail = IDX_PUT;
- if (lh->iterate_list_head == IDX_NIL)
- lh->iterate_list_head = IDX_PUT;
- }
-
- assert_se(hashmap_put_robin_hood(h, idx, swap) == false);
-
- n_entries_inc(h);
-#ifdef ENABLE_DEBUG_HASHMAP
- h->debug.max_entries = MAX(h->debug.max_entries, n_entries(h));
-#endif
-
- return 1;
-}
-#define hashmap_put_boldly(h, idx, swap, may_resize) \
- hashmap_base_put_boldly(HASHMAP_BASE(h), idx, swap, may_resize)
-
-/*
- * Returns 0 if resize is not needed.
- * 1 if successfully resized.
- * -ENOMEM on allocation failure.
- */
-static int resize_buckets(HashmapBase *h, unsigned entries_add) {
- struct swap_entries swap;
- void *new_storage;
- dib_raw_t *old_dibs, *new_dibs;
- const struct hashmap_type_info *hi;
- unsigned idx, optimal_idx;
- unsigned old_n_buckets, new_n_buckets, n_rehashed, new_n_entries;
- uint8_t new_shift;
- bool rehash_next;
-
- assert(h);
-
- hi = &hashmap_type_info[h->type];
- new_n_entries = n_entries(h) + entries_add;
-
- /* overflow? */
- if (_unlikely_(new_n_entries < entries_add))
- return -ENOMEM;
-
- /* For direct storage we allow 100% load, because it's tiny. */
- if (!h->has_indirect && new_n_entries <= hi->n_direct_buckets)
- return 0;
-
- /*
- * Load factor = n/m = 1 - (1/INV_KEEP_FREE).
- * From it follows: m = n + n/(INV_KEEP_FREE - 1)
- */
- new_n_buckets = new_n_entries + new_n_entries / (INV_KEEP_FREE - 1);
- /* overflow? */
- if (_unlikely_(new_n_buckets < new_n_entries))
- return -ENOMEM;
-
- if (_unlikely_(new_n_buckets > UINT_MAX / (hi->entry_size + sizeof(dib_raw_t))))
- return -ENOMEM;
-
- old_n_buckets = n_buckets(h);
-
- if (_likely_(new_n_buckets <= old_n_buckets))
- return 0;
-
- new_shift = log2u_round_up(MAX(
- new_n_buckets * (hi->entry_size + sizeof(dib_raw_t)),
- 2 * sizeof(struct direct_storage)));
-
- /* Realloc storage (buckets and DIB array). */
- new_storage = realloc(h->has_indirect ? h->indirect.storage : NULL,
- 1U << new_shift);
- if (!new_storage)
- return -ENOMEM;
-
- /* Must upgrade direct to indirect storage. */
- if (!h->has_indirect) {
- memcpy(new_storage, h->direct.storage,
- old_n_buckets * (hi->entry_size + sizeof(dib_raw_t)));
- h->indirect.n_entries = h->n_direct_entries;
- h->indirect.idx_lowest_entry = 0;
- h->n_direct_entries = 0;
- }
-
- /* Get a new hash key. If we've just upgraded to indirect storage,
- * allow reusing a previously generated key. It's still a different key
- * from the shared one that we used for direct storage. */
- get_hash_key(h->indirect.hash_key, !h->has_indirect);
-
- h->has_indirect = true;
- h->indirect.storage = new_storage;
- h->indirect.n_buckets = (1U << new_shift) /
- (hi->entry_size + sizeof(dib_raw_t));
-
- old_dibs = (dib_raw_t*)((uint8_t*) new_storage + hi->entry_size * old_n_buckets);
- new_dibs = dib_raw_ptr(h);
-
- /*
- * Move the DIB array to the new place, replacing valid DIB values with
- * DIB_RAW_REHASH to indicate all of the used buckets need rehashing.
- * Note: Overlap is not possible, because we have at least doubled the
- * number of buckets and dib_raw_t is smaller than any entry type.
- */
- for (idx = 0; idx < old_n_buckets; idx++) {
- assert(old_dibs[idx] != DIB_RAW_REHASH);
- new_dibs[idx] = old_dibs[idx] == DIB_RAW_FREE ? DIB_RAW_FREE
- : DIB_RAW_REHASH;
- }
-
- /* Zero the area of newly added entries (including the old DIB area) */
- memzero(bucket_at(h, old_n_buckets),
- (n_buckets(h) - old_n_buckets) * hi->entry_size);
-
- /* The upper half of the new DIB array needs initialization */
- memset(&new_dibs[old_n_buckets], DIB_RAW_INIT,
- (n_buckets(h) - old_n_buckets) * sizeof(dib_raw_t));
-
- /* Rehash entries that need it */
- n_rehashed = 0;
- for (idx = 0; idx < old_n_buckets; idx++) {
- if (new_dibs[idx] != DIB_RAW_REHASH)
- continue;
-
- optimal_idx = bucket_hash(h, bucket_at(h, idx)->key);
-
- /*
- * Not much to do if by luck the entry hashes to its current
- * location. Just set its DIB.
- */
- if (optimal_idx == idx) {
- new_dibs[idx] = 0;
- n_rehashed++;
- continue;
- }
-
- new_dibs[idx] = DIB_RAW_FREE;
- bucket_move_entry(h, &swap, idx, IDX_PUT);
- /* bucket_move_entry does not clear the source */
- memzero(bucket_at(h, idx), hi->entry_size);
-
- do {
- /*
- * Find the new bucket for the current entry. This may make
- * another entry homeless and load it into IDX_PUT.
- */
- rehash_next = hashmap_put_robin_hood(h, optimal_idx, &swap);
- n_rehashed++;
-
- /* Did the current entry displace another one? */
- if (rehash_next)
- optimal_idx = bucket_hash(h, bucket_at_swap(&swap, IDX_PUT)->p.b.key);
- } while (rehash_next);
- }
-
- assert(n_rehashed == n_entries(h));
-
- return 1;
-}
-
-/*
- * Finds an entry with a matching key
- * Returns: index of the found entry, or IDX_NIL if not found.
- */
-static unsigned base_bucket_scan(HashmapBase *h, unsigned idx, const void *key) {
- struct hashmap_base_entry *e;
- unsigned dib, distance;
- dib_raw_t *dibs = dib_raw_ptr(h);
-
- assert(idx < n_buckets(h));
-
- for (distance = 0; ; distance++) {
- if (dibs[idx] == DIB_RAW_FREE)
- return IDX_NIL;
-
- dib = bucket_calculate_dib(h, idx, dibs[idx]);
-
- if (dib < distance)
- return IDX_NIL;
- if (dib == distance) {
- e = bucket_at(h, idx);
- if (h->hash_ops->compare(e->key, key) == 0)
- return idx;
- }
-
- idx = next_idx(h, idx);
- }
-}
-#define bucket_scan(h, idx, key) base_bucket_scan(HASHMAP_BASE(h), idx, key)
-
-int hashmap_put(Hashmap *h, const void *key, void *value) {
- struct swap_entries swap;
- struct plain_hashmap_entry *e;
- unsigned hash, idx;
-
- assert(h);
-
- hash = bucket_hash(h, key);
- idx = bucket_scan(h, hash, key);
- if (idx != IDX_NIL) {
- e = plain_bucket_at(h, idx);
- if (e->value == value)
- return 0;
- return -EEXIST;
- }
-
- e = &bucket_at_swap(&swap, IDX_PUT)->p;
- e->b.key = key;
- e->value = value;
- return hashmap_put_boldly(h, hash, &swap, true);
-}
-
-int set_put(Set *s, const void *key) {
- struct swap_entries swap;
- struct hashmap_base_entry *e;
- unsigned hash, idx;
-
- assert(s);
-
- hash = bucket_hash(s, key);
- idx = bucket_scan(s, hash, key);
- if (idx != IDX_NIL)
- return 0;
-
- e = &bucket_at_swap(&swap, IDX_PUT)->p.b;
- e->key = key;
- return hashmap_put_boldly(s, hash, &swap, true);
-}
-
-int hashmap_replace(Hashmap *h, const void *key, void *value) {
- struct swap_entries swap;
- struct plain_hashmap_entry *e;
- unsigned hash, idx;
-
- assert(h);
-
- hash = bucket_hash(h, key);
- idx = bucket_scan(h, hash, key);
- if (idx != IDX_NIL) {
- e = plain_bucket_at(h, idx);
-#ifdef ENABLE_DEBUG_HASHMAP
- /* Although the key is equal, the key pointer may have changed,
- * and this would break our assumption for iterating. So count
- * this operation as incompatible with iteration. */
- if (e->b.key != key) {
- h->b.debug.put_count++;
- h->b.debug.rem_count++;
- h->b.debug.last_rem_idx = idx;
- }
-#endif
- e->b.key = key;
- e->value = value;
- return 0;
- }
-
- e = &bucket_at_swap(&swap, IDX_PUT)->p;
- e->b.key = key;
- e->value = value;
- return hashmap_put_boldly(h, hash, &swap, true);
-}
-
-int hashmap_update(Hashmap *h, const void *key, void *value) {
- struct plain_hashmap_entry *e;
- unsigned hash, idx;
-
- assert(h);
-
- hash = bucket_hash(h, key);
- idx = bucket_scan(h, hash, key);
- if (idx == IDX_NIL)
- return -ENOENT;
-
- e = plain_bucket_at(h, idx);
- e->value = value;
- return 0;
-}
-
-void *internal_hashmap_get(HashmapBase *h, const void *key) {
- struct hashmap_base_entry *e;
- unsigned hash, idx;
-
- if (!h)
- return NULL;
-
- hash = bucket_hash(h, key);
- idx = bucket_scan(h, hash, key);
- if (idx == IDX_NIL)
- return NULL;
-
- e = bucket_at(h, idx);
- return entry_value(h, e);
-}
-
-void *hashmap_get2(Hashmap *h, const void *key, void **key2) {
- struct plain_hashmap_entry *e;
- unsigned hash, idx;
-
- if (!h)
- return NULL;
-
- hash = bucket_hash(h, key);
- idx = bucket_scan(h, hash, key);
- if (idx == IDX_NIL)
- return NULL;
-
- e = plain_bucket_at(h, idx);
- if (key2)
- *key2 = (void*) e->b.key;
-
- return e->value;
-}
-
-bool internal_hashmap_contains(HashmapBase *h, const void *key) {
- unsigned hash;
-
- if (!h)
- return false;
-
- hash = bucket_hash(h, key);
- return bucket_scan(h, hash, key) != IDX_NIL;
-}
-
-void *internal_hashmap_remove(HashmapBase *h, const void *key) {
- struct hashmap_base_entry *e;
- unsigned hash, idx;
- void *data;
-
- if (!h)
- return NULL;
-
- hash = bucket_hash(h, key);
- idx = bucket_scan(h, hash, key);
- if (idx == IDX_NIL)
- return NULL;
-
- e = bucket_at(h, idx);
- data = entry_value(h, e);
- remove_entry(h, idx);
-
- return data;
-}
-
-void *hashmap_remove2(Hashmap *h, const void *key, void **rkey) {
- struct plain_hashmap_entry *e;
- unsigned hash, idx;
- void *data;
-
- if (!h) {
- if (rkey)
- *rkey = NULL;
- return NULL;
- }
-
- hash = bucket_hash(h, key);
- idx = bucket_scan(h, hash, key);
- if (idx == IDX_NIL) {
- if (rkey)
- *rkey = NULL;
- return NULL;
- }
-
- e = plain_bucket_at(h, idx);
- data = e->value;
- if (rkey)
- *rkey = (void*) e->b.key;
-
- remove_entry(h, idx);
-
- return data;
-}
-
-int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value) {
- struct swap_entries swap;
- struct plain_hashmap_entry *e;
- unsigned old_hash, new_hash, idx;
-
- if (!h)
- return -ENOENT;
-
- old_hash = bucket_hash(h, old_key);
- idx = bucket_scan(h, old_hash, old_key);
- if (idx == IDX_NIL)
- return -ENOENT;
-
- new_hash = bucket_hash(h, new_key);
- if (bucket_scan(h, new_hash, new_key) != IDX_NIL)
- return -EEXIST;
-
- remove_entry(h, idx);
-
- e = &bucket_at_swap(&swap, IDX_PUT)->p;
- e->b.key = new_key;
- e->value = value;
- assert_se(hashmap_put_boldly(h, new_hash, &swap, false) == 1);
-
- return 0;
-}
-
-int set_remove_and_put(Set *s, const void *old_key, const void *new_key) {
- struct swap_entries swap;
- struct hashmap_base_entry *e;
- unsigned old_hash, new_hash, idx;
-
- if (!s)
- return -ENOENT;
-
- old_hash = bucket_hash(s, old_key);
- idx = bucket_scan(s, old_hash, old_key);
- if (idx == IDX_NIL)
- return -ENOENT;
-
- new_hash = bucket_hash(s, new_key);
- if (bucket_scan(s, new_hash, new_key) != IDX_NIL)
- return -EEXIST;
-
- remove_entry(s, idx);
-
- e = &bucket_at_swap(&swap, IDX_PUT)->p.b;
- e->key = new_key;
- assert_se(hashmap_put_boldly(s, new_hash, &swap, false) == 1);
-
- return 0;
-}
-
-int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value) {
- struct swap_entries swap;
- struct plain_hashmap_entry *e;
- unsigned old_hash, new_hash, idx_old, idx_new;
-
- if (!h)
- return -ENOENT;
-
- old_hash = bucket_hash(h, old_key);
- idx_old = bucket_scan(h, old_hash, old_key);
- if (idx_old == IDX_NIL)
- return -ENOENT;
-
- old_key = bucket_at(HASHMAP_BASE(h), idx_old)->key;
-
- new_hash = bucket_hash(h, new_key);
- idx_new = bucket_scan(h, new_hash, new_key);
- if (idx_new != IDX_NIL)
- if (idx_old != idx_new) {
- remove_entry(h, idx_new);
- /* Compensate for a possible backward shift. */
- if (old_key != bucket_at(HASHMAP_BASE(h), idx_old)->key)
- idx_old = prev_idx(HASHMAP_BASE(h), idx_old);
- assert(old_key == bucket_at(HASHMAP_BASE(h), idx_old)->key);
- }
-
- remove_entry(h, idx_old);
-
- e = &bucket_at_swap(&swap, IDX_PUT)->p;
- e->b.key = new_key;
- e->value = value;
- assert_se(hashmap_put_boldly(h, new_hash, &swap, false) == 1);
-
- return 0;
-}
-
-void *hashmap_remove_value(Hashmap *h, const void *key, void *value) {
- struct plain_hashmap_entry *e;
- unsigned hash, idx;
-
- if (!h)
- return NULL;
-
- hash = bucket_hash(h, key);
- idx = bucket_scan(h, hash, key);
- if (idx == IDX_NIL)
- return NULL;
-
- e = plain_bucket_at(h, idx);
- if (e->value != value)
- return NULL;
-
- remove_entry(h, idx);
-
- return value;
-}
-
-static unsigned find_first_entry(HashmapBase *h) {
- Iterator i = ITERATOR_FIRST;
-
- if (!h || !n_entries(h))
- return IDX_NIL;
-
- return hashmap_iterate_entry(h, &i);
-}
-
-void *internal_hashmap_first(HashmapBase *h) {
- unsigned idx;
-
- idx = find_first_entry(h);
- if (idx == IDX_NIL)
- return NULL;
-
- return entry_value(h, bucket_at(h, idx));
-}
-
-void *internal_hashmap_first_key(HashmapBase *h) {
- struct hashmap_base_entry *e;
- unsigned idx;
-
- idx = find_first_entry(h);
- if (idx == IDX_NIL)
- return NULL;
-
- e = bucket_at(h, idx);
- return (void*) e->key;
-}
-
-void *internal_hashmap_steal_first(HashmapBase *h) {
- struct hashmap_base_entry *e;
- void *data;
- unsigned idx;
-
- idx = find_first_entry(h);
- if (idx == IDX_NIL)
- return NULL;
-
- e = bucket_at(h, idx);
- data = entry_value(h, e);
- remove_entry(h, idx);
-
- return data;
-}
-
-void *internal_hashmap_steal_first_key(HashmapBase *h) {
- struct hashmap_base_entry *e;
- void *key;
- unsigned idx;
-
- idx = find_first_entry(h);
- if (idx == IDX_NIL)
- return NULL;
-
- e = bucket_at(h, idx);
- key = (void*) e->key;
- remove_entry(h, idx);
-
- return key;
-}
-
-unsigned internal_hashmap_size(HashmapBase *h) {
-
- if (!h)
- return 0;
-
- return n_entries(h);
-}
-
-unsigned internal_hashmap_buckets(HashmapBase *h) {
-
- if (!h)
- return 0;
-
- return n_buckets(h);
-}
-
-int internal_hashmap_merge(Hashmap *h, Hashmap *other) {
- Iterator i;
- unsigned idx;
-
- assert(h);
-
- HASHMAP_FOREACH_IDX(idx, HASHMAP_BASE(other), i) {
- struct plain_hashmap_entry *pe = plain_bucket_at(other, idx);
- int r;
-
- r = hashmap_put(h, pe->b.key, pe->value);
- if (r < 0 && r != -EEXIST)
- return r;
- }
-
- return 0;
-}
-
-int set_merge(Set *s, Set *other) {
- Iterator i;
- unsigned idx;
-
- assert(s);
-
- HASHMAP_FOREACH_IDX(idx, HASHMAP_BASE(other), i) {
- struct set_entry *se = set_bucket_at(other, idx);
- int r;
-
- r = set_put(s, se->b.key);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-int internal_hashmap_reserve(HashmapBase *h, unsigned entries_add) {
- int r;
-
- assert(h);
-
- r = resize_buckets(h, entries_add);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-/*
- * The same as hashmap_merge(), but every new item from other is moved to h.
- * Keys already in h are skipped and stay in other.
- * Returns: 0 on success.
- * -ENOMEM on alloc failure, in which case no move has been done.
- */
-int internal_hashmap_move(HashmapBase *h, HashmapBase *other) {
- struct swap_entries swap;
- struct hashmap_base_entry *e, *n;
- Iterator i;
- unsigned idx;
- int r;
-
- assert(h);
-
- if (!other)
- return 0;
-
- assert(other->type == h->type);
-
- /*
- * This reserves buckets for the worst case, where none of other's
- * entries are yet present in h. This is preferable to risking
- * an allocation failure in the middle of the moving and having to
- * rollback or return a partial result.
- */
- r = resize_buckets(h, n_entries(other));
- if (r < 0)
- return r;
-
- HASHMAP_FOREACH_IDX(idx, other, i) {
- unsigned h_hash;
-
- e = bucket_at(other, idx);
- h_hash = bucket_hash(h, e->key);
- if (bucket_scan(h, h_hash, e->key) != IDX_NIL)
- continue;
-
- n = &bucket_at_swap(&swap, IDX_PUT)->p.b;
- n->key = e->key;
- if (h->type != HASHMAP_TYPE_SET)
- ((struct plain_hashmap_entry*) n)->value =
- ((struct plain_hashmap_entry*) e)->value;
- assert_se(hashmap_put_boldly(h, h_hash, &swap, false) == 1);
-
- remove_entry(other, idx);
- }
-
- return 0;
-}
-
-int internal_hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key) {
- struct swap_entries swap;
- unsigned h_hash, other_hash, idx;
- struct hashmap_base_entry *e, *n;
- int r;
-
- assert(h);
-
- h_hash = bucket_hash(h, key);
- if (bucket_scan(h, h_hash, key) != IDX_NIL)
- return -EEXIST;
-
- if (!other)
- return -ENOENT;
-
- assert(other->type == h->type);
-
- other_hash = bucket_hash(other, key);
- idx = bucket_scan(other, other_hash, key);
- if (idx == IDX_NIL)
- return -ENOENT;
-
- e = bucket_at(other, idx);
-
- n = &bucket_at_swap(&swap, IDX_PUT)->p.b;
- n->key = e->key;
- if (h->type != HASHMAP_TYPE_SET)
- ((struct plain_hashmap_entry*) n)->value =
- ((struct plain_hashmap_entry*) e)->value;
- r = hashmap_put_boldly(h, h_hash, &swap, true);
- if (r < 0)
- return r;
-
- remove_entry(other, idx);
- return 0;
-}
-
-HashmapBase *internal_hashmap_copy(HashmapBase *h) {
- HashmapBase *copy;
- int r;
-
- assert(h);
-
- copy = hashmap_base_new(h->hash_ops, h->type HASHMAP_DEBUG_SRC_ARGS);
- if (!copy)
- return NULL;
-
- switch (h->type) {
- case HASHMAP_TYPE_PLAIN:
- case HASHMAP_TYPE_ORDERED:
- r = hashmap_merge((Hashmap*)copy, (Hashmap*)h);
- break;
- case HASHMAP_TYPE_SET:
- r = set_merge((Set*)copy, (Set*)h);
- break;
- default:
- assert_not_reached("Unknown hashmap type");
- }
-
- if (r < 0) {
- internal_hashmap_free(copy);
- return NULL;
- }
-
- return copy;
-}
-
-char **internal_hashmap_get_strv(HashmapBase *h) {
- char **sv;
- Iterator i;
- unsigned idx, n;
-
- sv = new(char*, n_entries(h)+1);
- if (!sv)
- return NULL;
-
- n = 0;
- HASHMAP_FOREACH_IDX(idx, h, i)
- sv[n++] = entry_value(h, bucket_at(h, idx));
- sv[n] = NULL;
-
- return sv;
-}
-
-void *ordered_hashmap_next(OrderedHashmap *h, const void *key) {
- struct ordered_hashmap_entry *e;
- unsigned hash, idx;
-
- if (!h)
- return NULL;
-
- hash = bucket_hash(h, key);
- idx = bucket_scan(h, hash, key);
- if (idx == IDX_NIL)
- return NULL;
-
- e = ordered_bucket_at(h, idx);
- if (e->iterate_next == IDX_NIL)
- return NULL;
- return ordered_bucket_at(h, e->iterate_next)->p.value;
-}
-
-int set_consume(Set *s, void *value) {
- int r;
-
- assert(s);
- assert(value);
-
- r = set_put(s, value);
- if (r <= 0)
- free(value);
-
- return r;
-}
-
-int set_put_strdup(Set *s, const char *p) {
- char *c;
-
- assert(s);
- assert(p);
-
- if (set_contains(s, (char*) p))
- return 0;
-
- c = strdup(p);
- if (!c)
- return -ENOMEM;
-
- return set_consume(s, c);
-}
-
-int set_put_strdupv(Set *s, char **l) {
- int n = 0, r;
- char **i;
-
- assert(s);
-
- STRV_FOREACH(i, l) {
- r = set_put_strdup(s, *i);
- if (r < 0)
- return r;
-
- n += r;
- }
-
- return n;
-}
-
-int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags) {
- const char *p = v;
- int r;
-
- assert(s);
- assert(v);
-
- for (;;) {
- char *word;
-
- r = extract_first_word(&p, &word, separators, flags);
- if (r <= 0)
- return r;
-
- r = set_consume(s, word);
- if (r < 0)
- return r;
- }
-}
diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h
deleted file mode 100644
index 6d1ae48b21..0000000000
--- a/src/basic/hashmap.h
+++ /dev/null
@@ -1,372 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2014 Michal Schmidt
-
- 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 <limits.h>
-#include <stdbool.h>
-#include <stddef.h>
-
-#include "hash-funcs.h"
-#include "macro.h"
-#include "util.h"
-
-/*
- * A 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.
- *
- * If ENABLE_DEBUG_HASHMAP is defined (by configuring with --enable-debug=hashmap),
- * the implemention will:
- * - store extra data for debugging and statistics (see tools/gdb-sd_dump_hashmaps.py)
- * - perform extra checks for invalid use of iterators
- */
-
-#define HASH_KEY_SIZE 16
-
-/* The base type for all hashmap and set types. Many functions in the
- * implementation take (HashmapBase*) parameters and are run-time polymorphic,
- * though the API is not meant to be polymorphic (do not call functions
- * internal_*() directly). */
-typedef struct HashmapBase HashmapBase;
-
-/* Specific hashmap/set types */
-typedef struct Hashmap Hashmap; /* Maps keys to values */
-typedef struct OrderedHashmap OrderedHashmap; /* Like Hashmap, but also remembers entry insertion order */
-typedef struct Set Set; /* Stores just keys */
-
-/* Ideally the Iterator would be an opaque struct, but it is instantiated
- * by hashmap users, so the definition has to be here. Do not use its fields
- * directly. */
-typedef struct {
- unsigned idx; /* index of an entry to be iterated next */
- const void *next_key; /* expected value of that entry's key pointer */
-#ifdef ENABLE_DEBUG_HASHMAP
- unsigned put_count; /* hashmap's put_count recorded at start of iteration */
- unsigned rem_count; /* hashmap's rem_count in previous iteration */
- unsigned prev_idx; /* idx in previous iteration */
-#endif
-} Iterator;
-
-#define _IDX_ITERATOR_FIRST (UINT_MAX - 1)
-#define ITERATOR_FIRST ((Iterator) { .idx = _IDX_ITERATOR_FIRST, .next_key = NULL })
-
-/* Macros for type checking */
-#define PTR_COMPATIBLE_WITH_HASHMAP_BASE(h) \
- (__builtin_types_compatible_p(typeof(h), HashmapBase*) || \
- __builtin_types_compatible_p(typeof(h), Hashmap*) || \
- __builtin_types_compatible_p(typeof(h), OrderedHashmap*) || \
- __builtin_types_compatible_p(typeof(h), Set*))
-
-#define PTR_COMPATIBLE_WITH_PLAIN_HASHMAP(h) \
- (__builtin_types_compatible_p(typeof(h), Hashmap*) || \
- __builtin_types_compatible_p(typeof(h), OrderedHashmap*)) \
-
-#define HASHMAP_BASE(h) \
- __builtin_choose_expr(PTR_COMPATIBLE_WITH_HASHMAP_BASE(h), \
- (HashmapBase*)(h), \
- (void)0)
-
-#define PLAIN_HASHMAP(h) \
- __builtin_choose_expr(PTR_COMPATIBLE_WITH_PLAIN_HASHMAP(h), \
- (Hashmap*)(h), \
- (void)0)
-
-#ifdef ENABLE_DEBUG_HASHMAP
-# define HASHMAP_DEBUG_PARAMS , const char *func, const char *file, int line
-# define HASHMAP_DEBUG_SRC_ARGS , __func__, __FILE__, __LINE__
-# define HASHMAP_DEBUG_PASS_ARGS , func, file, line
-#else
-# define HASHMAP_DEBUG_PARAMS
-# define HASHMAP_DEBUG_SRC_ARGS
-# define HASHMAP_DEBUG_PASS_ARGS
-#endif
-
-Hashmap *internal_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
-OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
-#define hashmap_new(ops) internal_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
-#define ordered_hashmap_new(ops) internal_ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
-
-HashmapBase *internal_hashmap_free(HashmapBase *h);
-static inline Hashmap *hashmap_free(Hashmap *h) {
- return (void*)internal_hashmap_free(HASHMAP_BASE(h));
-}
-static inline OrderedHashmap *ordered_hashmap_free(OrderedHashmap *h) {
- return (void*)internal_hashmap_free(HASHMAP_BASE(h));
-}
-
-HashmapBase *internal_hashmap_free_free(HashmapBase *h);
-static inline Hashmap *hashmap_free_free(Hashmap *h) {
- return (void*)internal_hashmap_free_free(HASHMAP_BASE(h));
-}
-static inline OrderedHashmap *ordered_hashmap_free_free(OrderedHashmap *h) {
- return (void*)internal_hashmap_free_free(HASHMAP_BASE(h));
-}
-
-Hashmap *hashmap_free_free_free(Hashmap *h);
-static inline OrderedHashmap *ordered_hashmap_free_free_free(OrderedHashmap *h) {
- return (void*)hashmap_free_free_free(PLAIN_HASHMAP(h));
-}
-
-HashmapBase *internal_hashmap_copy(HashmapBase *h);
-static inline Hashmap *hashmap_copy(Hashmap *h) {
- return (Hashmap*) internal_hashmap_copy(HASHMAP_BASE(h));
-}
-static inline OrderedHashmap *ordered_hashmap_copy(OrderedHashmap *h) {
- return (OrderedHashmap*) internal_hashmap_copy(HASHMAP_BASE(h));
-}
-
-int internal_hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
-int internal_ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
-#define hashmap_ensure_allocated(h, ops) internal_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
-#define ordered_hashmap_ensure_allocated(h, ops) internal_ordered_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
-
-int hashmap_put(Hashmap *h, const void *key, void *value);
-static inline int ordered_hashmap_put(OrderedHashmap *h, const void *key, void *value) {
- return hashmap_put(PLAIN_HASHMAP(h), key, value);
-}
-
-int hashmap_update(Hashmap *h, const void *key, void *value);
-static inline int ordered_hashmap_update(OrderedHashmap *h, const void *key, void *value) {
- return hashmap_update(PLAIN_HASHMAP(h), key, value);
-}
-
-int hashmap_replace(Hashmap *h, const void *key, void *value);
-static inline int ordered_hashmap_replace(OrderedHashmap *h, const void *key, void *value) {
- return hashmap_replace(PLAIN_HASHMAP(h), key, value);
-}
-
-void *internal_hashmap_get(HashmapBase *h, const void *key);
-static inline void *hashmap_get(Hashmap *h, const void *key) {
- return internal_hashmap_get(HASHMAP_BASE(h), key);
-}
-static inline void *ordered_hashmap_get(OrderedHashmap *h, const void *key) {
- return internal_hashmap_get(HASHMAP_BASE(h), key);
-}
-
-void *hashmap_get2(Hashmap *h, const void *key, void **rkey);
-static inline void *ordered_hashmap_get2(OrderedHashmap *h, const void *key, void **rkey) {
- return hashmap_get2(PLAIN_HASHMAP(h), key, rkey);
-}
-
-bool internal_hashmap_contains(HashmapBase *h, const void *key);
-static inline bool hashmap_contains(Hashmap *h, const void *key) {
- return internal_hashmap_contains(HASHMAP_BASE(h), key);
-}
-static inline bool ordered_hashmap_contains(OrderedHashmap *h, const void *key) {
- return internal_hashmap_contains(HASHMAP_BASE(h), key);
-}
-
-void *internal_hashmap_remove(HashmapBase *h, const void *key);
-static inline void *hashmap_remove(Hashmap *h, const void *key) {
- return internal_hashmap_remove(HASHMAP_BASE(h), key);
-}
-static inline void *ordered_hashmap_remove(OrderedHashmap *h, const void *key) {
- return internal_hashmap_remove(HASHMAP_BASE(h), key);
-}
-
-void *hashmap_remove2(Hashmap *h, const void *key, void **rkey);
-static inline void *ordered_hashmap_remove2(OrderedHashmap *h, const void *key, void **rkey) {
- return hashmap_remove2(PLAIN_HASHMAP(h), key, rkey);
-}
-
-void *hashmap_remove_value(Hashmap *h, const void *key, void *value);
-static inline void *ordered_hashmap_remove_value(OrderedHashmap *h, const void *key, void *value) {
- return hashmap_remove_value(PLAIN_HASHMAP(h), key, value);
-}
-
-int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value);
-static inline int ordered_hashmap_remove_and_put(OrderedHashmap *h, const void *old_key, const void *new_key, void *value) {
- return hashmap_remove_and_put(PLAIN_HASHMAP(h), old_key, new_key, value);
-}
-
-int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value);
-static inline int ordered_hashmap_remove_and_replace(OrderedHashmap *h, const void *old_key, const void *new_key, void *value) {
- return hashmap_remove_and_replace(PLAIN_HASHMAP(h), old_key, new_key, value);
-}
-
-/* Since merging data from a OrderedHashmap into a Hashmap or vice-versa
- * should just work, allow this by having looser type-checking here. */
-int internal_hashmap_merge(Hashmap *h, Hashmap *other);
-#define hashmap_merge(h, other) internal_hashmap_merge(PLAIN_HASHMAP(h), PLAIN_HASHMAP(other))
-#define ordered_hashmap_merge(h, other) hashmap_merge(h, other)
-
-int internal_hashmap_reserve(HashmapBase *h, unsigned entries_add);
-static inline int hashmap_reserve(Hashmap *h, unsigned entries_add) {
- return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add);
-}
-static inline int ordered_hashmap_reserve(OrderedHashmap *h, unsigned entries_add) {
- return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add);
-}
-
-int internal_hashmap_move(HashmapBase *h, HashmapBase *other);
-/* Unlike hashmap_merge, hashmap_move does not allow mixing the types. */
-static inline int hashmap_move(Hashmap *h, Hashmap *other) {
- return internal_hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other));
-}
-static inline int ordered_hashmap_move(OrderedHashmap *h, OrderedHashmap *other) {
- return internal_hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other));
-}
-
-int internal_hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key);
-static inline int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key) {
- return internal_hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key);
-}
-static inline int ordered_hashmap_move_one(OrderedHashmap *h, OrderedHashmap *other, const void *key) {
- return internal_hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key);
-}
-
-unsigned internal_hashmap_size(HashmapBase *h) _pure_;
-static inline unsigned hashmap_size(Hashmap *h) {
- return internal_hashmap_size(HASHMAP_BASE(h));
-}
-static inline unsigned ordered_hashmap_size(OrderedHashmap *h) {
- return internal_hashmap_size(HASHMAP_BASE(h));
-}
-
-static inline bool hashmap_isempty(Hashmap *h) {
- return hashmap_size(h) == 0;
-}
-static inline bool ordered_hashmap_isempty(OrderedHashmap *h) {
- return ordered_hashmap_size(h) == 0;
-}
-
-unsigned internal_hashmap_buckets(HashmapBase *h) _pure_;
-static inline unsigned hashmap_buckets(Hashmap *h) {
- return internal_hashmap_buckets(HASHMAP_BASE(h));
-}
-static inline unsigned ordered_hashmap_buckets(OrderedHashmap *h) {
- return internal_hashmap_buckets(HASHMAP_BASE(h));
-}
-
-bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key);
-static inline bool hashmap_iterate(Hashmap *h, Iterator *i, void **value, const void **key) {
- return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key);
-}
-static inline bool ordered_hashmap_iterate(OrderedHashmap *h, Iterator *i, void **value, const void **key) {
- return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key);
-}
-
-void internal_hashmap_clear(HashmapBase *h);
-static inline void hashmap_clear(Hashmap *h) {
- internal_hashmap_clear(HASHMAP_BASE(h));
-}
-static inline void ordered_hashmap_clear(OrderedHashmap *h) {
- internal_hashmap_clear(HASHMAP_BASE(h));
-}
-
-void internal_hashmap_clear_free(HashmapBase *h);
-static inline void hashmap_clear_free(Hashmap *h) {
- internal_hashmap_clear_free(HASHMAP_BASE(h));
-}
-static inline void ordered_hashmap_clear_free(OrderedHashmap *h) {
- internal_hashmap_clear_free(HASHMAP_BASE(h));
-}
-
-void hashmap_clear_free_free(Hashmap *h);
-static inline void ordered_hashmap_clear_free_free(OrderedHashmap *h) {
- hashmap_clear_free_free(PLAIN_HASHMAP(h));
-}
-
-/*
- * Note about all *_first*() functions
- *
- * For plain Hashmaps and Sets the order of entries is undefined.
- * The functions find whatever entry is first in the implementation
- * internal order.
- *
- * Only for OrderedHashmaps the order is well defined and finding
- * the first entry is O(1).
- */
-
-void *internal_hashmap_steal_first(HashmapBase *h);
-static inline void *hashmap_steal_first(Hashmap *h) {
- return internal_hashmap_steal_first(HASHMAP_BASE(h));
-}
-static inline void *ordered_hashmap_steal_first(OrderedHashmap *h) {
- return internal_hashmap_steal_first(HASHMAP_BASE(h));
-}
-
-void *internal_hashmap_steal_first_key(HashmapBase *h);
-static inline void *hashmap_steal_first_key(Hashmap *h) {
- return internal_hashmap_steal_first_key(HASHMAP_BASE(h));
-}
-static inline void *ordered_hashmap_steal_first_key(OrderedHashmap *h) {
- return internal_hashmap_steal_first_key(HASHMAP_BASE(h));
-}
-
-void *internal_hashmap_first_key(HashmapBase *h) _pure_;
-static inline void *hashmap_first_key(Hashmap *h) {
- return internal_hashmap_first_key(HASHMAP_BASE(h));
-}
-static inline void *ordered_hashmap_first_key(OrderedHashmap *h) {
- return internal_hashmap_first_key(HASHMAP_BASE(h));
-}
-
-void *internal_hashmap_first(HashmapBase *h) _pure_;
-static inline void *hashmap_first(Hashmap *h) {
- return internal_hashmap_first(HASHMAP_BASE(h));
-}
-static inline void *ordered_hashmap_first(OrderedHashmap *h) {
- return internal_hashmap_first(HASHMAP_BASE(h));
-}
-
-/* no hashmap_next */
-void *ordered_hashmap_next(OrderedHashmap *h, const void *key);
-
-char **internal_hashmap_get_strv(HashmapBase *h);
-static inline char **hashmap_get_strv(Hashmap *h) {
- return internal_hashmap_get_strv(HASHMAP_BASE(h));
-}
-static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) {
- return internal_hashmap_get_strv(HASHMAP_BASE(h));
-}
-
-/*
- * Hashmaps are iterated in unpredictable order.
- * OrderedHashmaps are an exception to this. They are iterated in the order
- * the entries were inserted.
- * It is safe to remove the current entry.
- */
-#define HASHMAP_FOREACH(e, h, i) \
- for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), NULL); )
-
-#define ORDERED_HASHMAP_FOREACH(e, h, i) \
- for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), NULL); )
-
-#define HASHMAP_FOREACH_KEY(e, k, h, i) \
- for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); )
-
-#define ORDERED_HASHMAP_FOREACH_KEY(e, k, h, i) \
- for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); )
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free_free);
-
-#define _cleanup_hashmap_free_ _cleanup_(hashmap_freep)
-#define _cleanup_hashmap_free_free_ _cleanup_(hashmap_free_freep)
-#define _cleanup_hashmap_free_free_free_ _cleanup_(hashmap_free_free_freep)
-#define _cleanup_ordered_hashmap_free_ _cleanup_(ordered_hashmap_freep)
-#define _cleanup_ordered_hashmap_free_free_ _cleanup_(ordered_hashmap_free_freep)
-#define _cleanup_ordered_hashmap_free_free_free_ _cleanup_(ordered_hashmap_free_free_freep)
diff --git a/src/basic/hexdecoct.c b/src/basic/hexdecoct.c
deleted file mode 100644
index c5bda6c4d6..0000000000
--- a/src/basic/hexdecoct.c
+++ /dev/null
@@ -1,754 +0,0 @@
-/***
- 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 <ctype.h>
-#include <errno.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#include "alloc-util.h"
-#include "hexdecoct.h"
-#include "macro.h"
-#include "util.h"
-
-char octchar(int x) {
- return '0' + (x & 7);
-}
-
-int unoctchar(char c) {
-
- if (c >= '0' && c <= '7')
- return c - '0';
-
- return -EINVAL;
-}
-
-char decchar(int x) {
- return '0' + (x % 10);
-}
-
-int undecchar(char c) {
-
- if (c >= '0' && c <= '9')
- return c - '0';
-
- return -EINVAL;
-}
-
-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 -EINVAL;
-}
-
-char *hexmem(const void *p, size_t l) {
- char *r, *z;
- const uint8_t *x;
-
- z = r = malloc(l * 2 + 1);
- if (!r)
- return NULL;
-
- for (x = p; x < (const uint8_t*) p + l; x++) {
- *(z++) = hexchar(*x >> 4);
- *(z++) = hexchar(*x & 15);
- }
-
- *z = 0;
- return r;
-}
-
-int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
- _cleanup_free_ uint8_t *r = NULL;
- uint8_t *z;
- const char *x;
-
- assert(mem);
- assert(len);
- assert(p);
-
- z = r = malloc((l + 1) / 2 + 1);
- if (!r)
- return -ENOMEM;
-
- for (x = p; x < p + l; x += 2) {
- int a, b;
-
- a = unhexchar(x[0]);
- if (a < 0)
- return a;
- else if (x+1 < p + l) {
- b = unhexchar(x[1]);
- if (b < 0)
- return b;
- } else
- b = 0;
-
- *(z++) = (uint8_t) a << 4 | (uint8_t) b;
- }
-
- *z = 0;
-
- *mem = r;
- r = NULL;
- *len = (l + 1) / 2;
-
- return 0;
-}
-
-/* https://tools.ietf.org/html/rfc4648#section-6
- * Notice that base32hex differs from base32 in the alphabet it uses.
- * The distinction is that the base32hex representation preserves the
- * order of the underlying data when compared as bytestrings, this is
- * useful when representing NSEC3 hashes, as one can then verify the
- * order of hashes directly from their representation. */
-char base32hexchar(int x) {
- static const char table[32] = "0123456789"
- "ABCDEFGHIJKLMNOPQRSTUV";
-
- return table[x & 31];
-}
-
-int unbase32hexchar(char c) {
- unsigned offset;
-
- if (c >= '0' && c <= '9')
- return c - '0';
-
- offset = '9' - '0' + 1;
-
- if (c >= 'A' && c <= 'V')
- return c - 'A' + offset;
-
- return -EINVAL;
-}
-
-char *base32hexmem(const void *p, size_t l, bool padding) {
- char *r, *z;
- const uint8_t *x;
- size_t len;
-
- if (padding)
- /* five input bytes makes eight output bytes, padding is added so we must round up */
- len = 8 * (l + 4) / 5;
- else {
- /* same, but round down as there is no padding */
- len = 8 * l / 5;
-
- switch (l % 5) {
- case 4:
- len += 7;
- break;
- case 3:
- len += 5;
- break;
- case 2:
- len += 4;
- break;
- case 1:
- len += 2;
- break;
- }
- }
-
- z = r = malloc(len + 1);
- if (!r)
- return NULL;
-
- for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
- /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
- x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
- *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
- *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
- *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
- *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
- *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
- *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
- *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5); /* 000QQWWW */
- *(z++) = base32hexchar((x[4] & 31)); /* 000WWWWW */
- }
-
- switch (l % 5) {
- case 4:
- *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
- *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
- *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
- *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
- *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */
- *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */
- *(z++) = base32hexchar((x[3] & 3) << 3); /* 000QQ000 */
- if (padding)
- *(z++) = '=';
-
- break;
-
- case 3:
- *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
- *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
- *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
- *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */
- *(z++) = base32hexchar((x[2] & 15) << 1); /* 000ZZZZ0 */
- if (padding) {
- *(z++) = '=';
- *(z++) = '=';
- *(z++) = '=';
- }
-
- break;
-
- case 2:
- *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
- *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
- *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
- *(z++) = base32hexchar((x[1] & 1) << 4); /* 000Y0000 */
- if (padding) {
- *(z++) = '=';
- *(z++) = '=';
- *(z++) = '=';
- *(z++) = '=';
- }
-
- break;
-
- case 1:
- *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
- *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */
- if (padding) {
- *(z++) = '=';
- *(z++) = '=';
- *(z++) = '=';
- *(z++) = '=';
- *(z++) = '=';
- *(z++) = '=';
- }
-
- break;
- }
-
- *z = 0;
- return r;
-}
-
-int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) {
- _cleanup_free_ uint8_t *r = NULL;
- int a, b, c, d, e, f, g, h;
- uint8_t *z;
- const char *x;
- size_t len;
- unsigned pad = 0;
-
- assert(p);
-
- /* padding ensures any base32hex input has input divisible by 8 */
- if (padding && l % 8 != 0)
- return -EINVAL;
-
- if (padding) {
- /* strip the padding */
- while (l > 0 && p[l - 1] == '=' && pad < 7) {
- pad++;
- l--;
- }
- }
-
- /* a group of eight input bytes needs five output bytes, in case of
- padding we need to add some extra bytes */
- len = (l / 8) * 5;
-
- switch (l % 8) {
- case 7:
- len += 4;
- break;
- case 5:
- len += 3;
- break;
- case 4:
- len += 2;
- break;
- case 2:
- len += 1;
- break;
- case 0:
- break;
- default:
- return -EINVAL;
- }
-
- z = r = malloc(len + 1);
- if (!r)
- return -ENOMEM;
-
- for (x = p; x < p + (l / 8) * 8; x += 8) {
- /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
- e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
- a = unbase32hexchar(x[0]);
- if (a < 0)
- return -EINVAL;
-
- b = unbase32hexchar(x[1]);
- if (b < 0)
- return -EINVAL;
-
- c = unbase32hexchar(x[2]);
- if (c < 0)
- return -EINVAL;
-
- d = unbase32hexchar(x[3]);
- if (d < 0)
- return -EINVAL;
-
- e = unbase32hexchar(x[4]);
- if (e < 0)
- return -EINVAL;
-
- f = unbase32hexchar(x[5]);
- if (f < 0)
- return -EINVAL;
-
- g = unbase32hexchar(x[6]);
- if (g < 0)
- return -EINVAL;
-
- h = unbase32hexchar(x[7]);
- if (h < 0)
- return -EINVAL;
-
- *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
- *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
- *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
- *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
- *(z++) = (uint8_t) g << 5 | (uint8_t) h; /* VVVRRRRR */
- }
-
- switch (l % 8) {
- case 7:
- a = unbase32hexchar(x[0]);
- if (a < 0)
- return -EINVAL;
-
- b = unbase32hexchar(x[1]);
- if (b < 0)
- return -EINVAL;
-
- c = unbase32hexchar(x[2]);
- if (c < 0)
- return -EINVAL;
-
- d = unbase32hexchar(x[3]);
- if (d < 0)
- return -EINVAL;
-
- e = unbase32hexchar(x[4]);
- if (e < 0)
- return -EINVAL;
-
- f = unbase32hexchar(x[5]);
- if (f < 0)
- return -EINVAL;
-
- g = unbase32hexchar(x[6]);
- if (g < 0)
- return -EINVAL;
-
- /* g == 000VV000 */
- if (g & 7)
- return -EINVAL;
-
- *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
- *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
- *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
- *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */
-
- break;
- case 5:
- a = unbase32hexchar(x[0]);
- if (a < 0)
- return -EINVAL;
-
- b = unbase32hexchar(x[1]);
- if (b < 0)
- return -EINVAL;
-
- c = unbase32hexchar(x[2]);
- if (c < 0)
- return -EINVAL;
-
- d = unbase32hexchar(x[3]);
- if (d < 0)
- return -EINVAL;
-
- e = unbase32hexchar(x[4]);
- if (e < 0)
- return -EINVAL;
-
- /* e == 000SSSS0 */
- if (e & 1)
- return -EINVAL;
-
- *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
- *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
- *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */
-
- break;
- case 4:
- a = unbase32hexchar(x[0]);
- if (a < 0)
- return -EINVAL;
-
- b = unbase32hexchar(x[1]);
- if (b < 0)
- return -EINVAL;
-
- c = unbase32hexchar(x[2]);
- if (c < 0)
- return -EINVAL;
-
- d = unbase32hexchar(x[3]);
- if (d < 0)
- return -EINVAL;
-
- /* d == 000W0000 */
- if (d & 15)
- return -EINVAL;
-
- *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
- *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */
-
- break;
- case 2:
- a = unbase32hexchar(x[0]);
- if (a < 0)
- return -EINVAL;
-
- b = unbase32hexchar(x[1]);
- if (b < 0)
- return -EINVAL;
-
- /* b == 000YYY00 */
- if (b & 3)
- return -EINVAL;
-
- *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */
-
- break;
- case 0:
- break;
- default:
- return -EINVAL;
- }
-
- *z = 0;
-
- *mem = r;
- r = NULL;
- *_len = len;
-
- return 0;
-}
-
-/* https://tools.ietf.org/html/rfc4648#section-4 */
-char base64char(int x) {
- static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789+/";
- return table[x & 63];
-}
-
-int unbase64char(char c) {
- unsigned offset;
-
- if (c >= 'A' && c <= 'Z')
- return c - 'A';
-
- offset = 'Z' - 'A' + 1;
-
- if (c >= 'a' && c <= 'z')
- return c - 'a' + offset;
-
- offset += 'z' - 'a' + 1;
-
- if (c >= '0' && c <= '9')
- return c - '0' + offset;
-
- offset += '9' - '0' + 1;
-
- if (c == '+')
- return offset;
-
- offset++;
-
- if (c == '/')
- return offset;
-
- return -EINVAL;
-}
-
-ssize_t base64mem(const void *p, size_t l, char **out) {
- char *r, *z;
- const uint8_t *x;
-
- /* three input bytes makes four output bytes, padding is added so we must round up */
- z = r = malloc(4 * (l + 2) / 3 + 1);
- if (!r)
- return -ENOMEM;
-
- for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
- /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
- *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
- *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
- *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */
- *(z++) = base64char(x[2] & 63); /* 00ZZZZZZ */
- }
-
- switch (l % 3) {
- case 2:
- *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
- *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
- *(z++) = base64char((x[1] & 15) << 2); /* 00YYYY00 */
- *(z++) = '=';
-
- break;
- case 1:
- *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
- *(z++) = base64char((x[0] & 3) << 4); /* 00XX0000 */
- *(z++) = '=';
- *(z++) = '=';
-
- break;
- }
-
- *z = 0;
- *out = r;
- return z - r;
-}
-
-static int base64_append_width(char **prefix, int plen,
- const char *sep, int indent,
- const void *p, size_t l,
- int width) {
-
- _cleanup_free_ char *x = NULL;
- char *t, *s;
- ssize_t slen, len, avail;
- int line, lines;
-
- len = base64mem(p, l, &x);
- if (len <= 0)
- return len;
-
- lines = (len + width - 1) / width;
-
- slen = sep ? strlen(sep) : 0;
- t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines);
- if (!t)
- return -ENOMEM;
-
- memcpy_safe(t + plen, sep, slen);
-
- for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) {
- int act = MIN(width, avail);
-
- if (line > 0 || sep) {
- memset(s, ' ', indent);
- s += indent;
- }
-
- memcpy(s, x + width * line, act);
- s += act;
- *(s++) = line < lines - 1 ? '\n' : '\0';
- avail -= act;
- }
- assert(avail == 0);
-
- *prefix = t;
- return 0;
-}
-
-int base64_append(char **prefix, int plen,
- const void *p, size_t l,
- int indent, int width) {
- if (plen > width / 2 || plen + indent > width)
- /* leave indent on the left, keep last column free */
- return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1);
- else
- /* leave plen on the left, keep last column free */
- return base64_append_width(prefix, plen, NULL, plen, p, l, width - plen - 1);
-};
-
-
-int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) {
- _cleanup_free_ uint8_t *r = NULL;
- int a, b, c, d;
- uint8_t *z;
- const char *x;
- size_t len;
-
- assert(p);
-
- /* padding ensures any base63 input has input divisible by 4 */
- if (l % 4 != 0)
- return -EINVAL;
-
- /* strip the padding */
- if (l > 0 && p[l - 1] == '=')
- l--;
- if (l > 0 && p[l - 1] == '=')
- l--;
-
- /* a group of four input bytes needs three output bytes, in case of
- padding we need to add two or three extra bytes */
- len = (l / 4) * 3 + (l % 4 ? (l % 4) - 1 : 0);
-
- z = r = malloc(len + 1);
- if (!r)
- return -ENOMEM;
-
- for (x = p; x < p + (l / 4) * 4; x += 4) {
- /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
- a = unbase64char(x[0]);
- if (a < 0)
- return -EINVAL;
-
- b = unbase64char(x[1]);
- if (b < 0)
- return -EINVAL;
-
- c = unbase64char(x[2]);
- if (c < 0)
- return -EINVAL;
-
- d = unbase64char(x[3]);
- if (d < 0)
- return -EINVAL;
-
- *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
- *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
- *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */
- }
-
- switch (l % 4) {
- case 3:
- a = unbase64char(x[0]);
- if (a < 0)
- return -EINVAL;
-
- b = unbase64char(x[1]);
- if (b < 0)
- return -EINVAL;
-
- c = unbase64char(x[2]);
- if (c < 0)
- return -EINVAL;
-
- /* c == 00ZZZZ00 */
- if (c & 3)
- return -EINVAL;
-
- *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
- *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
-
- break;
- case 2:
- a = unbase64char(x[0]);
- if (a < 0)
- return -EINVAL;
-
- b = unbase64char(x[1]);
- if (b < 0)
- return -EINVAL;
-
- /* b == 00YY0000 */
- if (b & 15)
- return -EINVAL;
-
- *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
-
- break;
- case 0:
-
- break;
- default:
- return -EINVAL;
- }
-
- *z = 0;
-
- *mem = r;
- r = NULL;
- *_len = len;
-
- return 0;
-}
-
-void hexdump(FILE *f, const void *p, size_t s) {
- const uint8_t *b = p;
- unsigned n = 0;
-
- assert(s == 0 || b);
-
- while (s > 0) {
- size_t i;
-
- fprintf(f, "%04x ", n);
-
- for (i = 0; i < 16; i++) {
-
- if (i >= s)
- fputs(" ", f);
- else
- fprintf(f, "%02x ", b[i]);
-
- if (i == 7)
- fputc(' ', f);
- }
-
- fputc(' ', f);
-
- for (i = 0; i < 16; i++) {
-
- if (i >= s)
- fputc(' ', f);
- else
- fputc(isprint(b[i]) ? (char) b[i] : '.', f);
- }
-
- fputc('\n', f);
-
- if (s < 16)
- break;
-
- n += 16;
- b += 16;
- s -= 16;
- }
-}
diff --git a/src/basic/hexdecoct.h b/src/basic/hexdecoct.h
deleted file mode 100644
index 1ba2f69ebd..0000000000
--- a/src/basic/hexdecoct.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#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 <stddef.h>
-#include <stdio.h>
-#include <sys/types.h>
-
-#include "macro.h"
-
-char octchar(int x) _const_;
-int unoctchar(char c) _const_;
-
-char decchar(int x) _const_;
-int undecchar(char c) _const_;
-
-char hexchar(int x) _const_;
-int unhexchar(char c) _const_;
-
-char *hexmem(const void *p, size_t l);
-int unhexmem(const char *p, size_t l, void **mem, size_t *len);
-
-char base32hexchar(int x) _const_;
-int unbase32hexchar(char c) _const_;
-
-char base64char(int x) _const_;
-int unbase64char(char c) _const_;
-
-char *base32hexmem(const void *p, size_t l, bool padding);
-int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *len);
-
-ssize_t base64mem(const void *p, size_t l, char **out);
-int base64_append(char **prefix, int plen,
- const void *p, size_t l,
- int margin, int width);
-int unbase64mem(const char *p, size_t l, void **mem, size_t *len);
-
-void hexdump(FILE *f, const void *p, size_t s);
diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c
deleted file mode 100644
index e44a357287..0000000000
--- a/src/basic/hostname-util.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2015 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 <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/utsname.h>
-#include <unistd.h>
-
-#include "fd-util.h"
-#include "fileio.h"
-#include "hostname-util.h"
-#include "macro.h"
-#include "string-util.h"
-
-bool hostname_is_set(void) {
- struct utsname u;
-
- assert_se(uname(&u) >= 0);
-
- if (isempty(u.nodename))
- return false;
-
- /* This is the built-in kernel default host name */
- if (streq(u.nodename, "(none)"))
- return false;
-
- return true;
-}
-
-char* gethostname_malloc(void) {
- struct utsname u;
-
- /* This call tries to return something useful, either the actual hostname
- * or it makes something up. The only reason it might fail is OOM.
- * It might even return "localhost" if that's set. */
-
- assert_se(uname(&u) >= 0);
-
- if (isempty(u.nodename) || streq(u.nodename, "(none)"))
- return strdup(u.sysname);
-
- return strdup(u.nodename);
-}
-
-int gethostname_strict(char **ret) {
- struct utsname u;
- char *k;
-
- /* This call will rather fail than make up a name. It will not return "localhost" either. */
-
- assert_se(uname(&u) >= 0);
-
- if (isempty(u.nodename))
- return -ENXIO;
-
- if (streq(u.nodename, "(none)"))
- return -ENXIO;
-
- if (is_localhost(u.nodename))
- return -ENXIO;
-
- k = strdup(u.nodename);
- if (!k)
- return -ENOMEM;
-
- *ret = k;
- return 0;
-}
-
-static bool hostname_valid_char(char c) {
- return
- (c >= 'a' && c <= 'z') ||
- (c >= 'A' && c <= 'Z') ||
- (c >= '0' && c <= '9') ||
- c == '-' ||
- c == '_' ||
- c == '.';
-}
-
-/**
- * Check if s looks like a valid host name or FQDN. This does not do
- * full DNS validation, but only checks if the name is composed of
- * allowed characters and the length is not above the maximum allowed
- * by Linux (c.f. dns_name_is_valid()). Trailing dot is allowed if
- * allow_trailing_dot is true and at least two components are present
- * in the name. Note that due to the restricted charset and length
- * this call is substantially more conservative than
- * dns_name_is_valid().
- */
-bool hostname_is_valid(const char *s, bool allow_trailing_dot) {
- unsigned n_dots = 0;
- const char *p;
- bool dot;
-
- if (isempty(s))
- return false;
-
- /* Doesn't accept empty hostnames, hostnames with
- * leading dots, and hostnames with multiple dots in a
- * sequence. Also ensures that the length stays below
- * HOST_NAME_MAX. */
-
- for (p = s, dot = true; *p; p++) {
- if (*p == '.') {
- if (dot)
- return false;
-
- dot = true;
- n_dots++;
- } else {
- if (!hostname_valid_char(*p))
- return false;
-
- dot = false;
- }
- }
-
- if (dot && (n_dots < 2 || !allow_trailing_dot))
- return false;
-
- if (p-s > HOST_NAME_MAX) /* Note that HOST_NAME_MAX is 64 on
- * Linux, but DNS allows domain names
- * up to 255 characters */
- return false;
-
- return true;
-}
-
-char* hostname_cleanup(char *s) {
- char *p, *d;
- bool dot;
-
- assert(s);
-
- strshorten(s, HOST_NAME_MAX);
-
- for (p = s, d = s, dot = true; *p; p++) {
- if (*p == '.') {
- if (dot)
- continue;
-
- *(d++) = '.';
- dot = true;
- } else if (hostname_valid_char(*p)) {
- *(d++) = *p;
- dot = false;
- }
- }
-
- if (dot && d > s)
- d[-1] = 0;
- else
- *d = 0;
-
- return s;
-}
-
-bool is_localhost(const char *hostname) {
- assert(hostname);
-
- /* This tries to identify local host and domain names
- * described in RFC6761 plus the redhatism of localdomain */
-
- return strcaseeq(hostname, "localhost") ||
- strcaseeq(hostname, "localhost.") ||
- strcaseeq(hostname, "localhost.localdomain") ||
- strcaseeq(hostname, "localhost.localdomain.") ||
- endswith_no_case(hostname, ".localhost") ||
- endswith_no_case(hostname, ".localhost.") ||
- endswith_no_case(hostname, ".localhost.localdomain") ||
- endswith_no_case(hostname, ".localhost.localdomain.");
-}
-
-bool is_gateway_hostname(const char *hostname) {
- assert(hostname);
-
- /* This tries to identify the valid syntaxes for the our
- * synthetic "gateway" host. */
-
- return
- strcaseeq(hostname, "gateway") ||
- strcaseeq(hostname, "gateway.");
-}
-
-int sethostname_idempotent(const char *s) {
- char buf[HOST_NAME_MAX + 1] = {};
-
- assert(s);
-
- if (gethostname(buf, sizeof(buf)) < 0)
- return -errno;
-
- if (streq(buf, s))
- return 0;
-
- if (sethostname(s, strlen(s)) < 0)
- return -errno;
-
- return 1;
-}
-
-int read_hostname_config(const char *path, char **hostname) {
- _cleanup_fclose_ FILE *f = NULL;
- char l[LINE_MAX];
- char *name = NULL;
-
- assert(path);
- assert(hostname);
-
- f = fopen(path, "re");
- if (!f)
- return -errno;
-
- /* may have comments, ignore them */
- FOREACH_LINE(l, f, return -errno) {
- truncate_nl(l);
- if (l[0] != '\0' && l[0] != '#') {
- /* found line with value */
- name = hostname_cleanup(l);
- name = strdup(name);
- if (!name)
- return -ENOMEM;
- break;
- }
- }
-
- if (!name)
- /* no non-empty line found */
- return -ENOENT;
-
- *hostname = name;
- return 0;
-}
diff --git a/src/basic/hostname-util.h b/src/basic/hostname-util.h
deleted file mode 100644
index 7af4e6c7ec..0000000000
--- a/src/basic/hostname-util.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010-2015 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 "macro.h"
-
-bool hostname_is_set(void);
-
-char* gethostname_malloc(void);
-int gethostname_strict(char **ret);
-
-bool hostname_is_valid(const char *s, bool allow_trailing_dot) _pure_;
-char* hostname_cleanup(char *s);
-
-#define machine_name_is_valid(s) hostname_is_valid(s, false)
-
-bool is_localhost(const char *hostname);
-bool is_gateway_hostname(const char *hostname);
-
-int sethostname_idempotent(const char *s);
-
-int read_hostname_config(const char *path, char **hostname);
diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c
deleted file mode 100644
index aa7ccd1afd..0000000000
--- a/src/basic/in-addr-util.c
+++ /dev/null
@@ -1,449 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 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 <arpa/inet.h>
-#include <endian.h>
-#include <errno.h>
-#include <net/if.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#include "alloc-util.h"
-#include "in-addr-util.h"
-#include "macro.h"
-#include "parse-util.h"
-#include "util.h"
-
-bool in4_addr_is_null(const struct in_addr *a) {
- return a->s_addr == 0;
-}
-
-bool in6_addr_is_null(const struct in6_addr *a) {
- return
- a->s6_addr32[0] == 0 &&
- a->s6_addr32[1] == 0 &&
- a->s6_addr32[2] == 0 &&
- a->s6_addr32[3] == 0;
-}
-
-int in_addr_is_null(int family, const union in_addr_union *u) {
- assert(u);
-
- if (family == AF_INET)
- return in4_addr_is_null(&u->in);
-
- if (family == AF_INET6)
- return in6_addr_is_null(&u->in6);
-
- return -EAFNOSUPPORT;
-}
-
-int in_addr_is_link_local(int family, const union in_addr_union *u) {
- assert(u);
-
- if (family == AF_INET)
- return (be32toh(u->in.s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
-
- if (family == AF_INET6)
- return IN6_IS_ADDR_LINKLOCAL(&u->in6);
-
- return -EAFNOSUPPORT;
-}
-
-int in_addr_is_localhost(int family, const union in_addr_union *u) {
- assert(u);
-
- if (family == AF_INET)
- /* All of 127.x.x.x is localhost. */
- return (be32toh(u->in.s_addr) & UINT32_C(0xFF000000)) == UINT32_C(127) << 24;
-
- if (family == AF_INET6)
- return IN6_IS_ADDR_LOOPBACK(&u->in6);
-
- return -EAFNOSUPPORT;
-}
-
-int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b) {
- assert(a);
- assert(b);
-
- if (family == AF_INET)
- return a->in.s_addr == b->in.s_addr;
-
- if (family == AF_INET6)
- return
- a->in6.s6_addr32[0] == b->in6.s6_addr32[0] &&
- a->in6.s6_addr32[1] == b->in6.s6_addr32[1] &&
- a->in6.s6_addr32[2] == b->in6.s6_addr32[2] &&
- a->in6.s6_addr32[3] == b->in6.s6_addr32[3];
-
- return -EAFNOSUPPORT;
-}
-
-int in_addr_prefix_intersect(
- int family,
- const union in_addr_union *a,
- unsigned aprefixlen,
- const union in_addr_union *b,
- unsigned bprefixlen) {
-
- unsigned m;
-
- assert(a);
- assert(b);
-
- /* Checks whether there are any addresses that are in both
- * networks */
-
- m = MIN(aprefixlen, bprefixlen);
-
- if (family == AF_INET) {
- uint32_t x, nm;
-
- x = be32toh(a->in.s_addr ^ b->in.s_addr);
- nm = (m == 0) ? 0 : 0xFFFFFFFFUL << (32 - m);
-
- return (x & nm) == 0;
- }
-
- if (family == AF_INET6) {
- unsigned i;
-
- if (m > 128)
- m = 128;
-
- for (i = 0; i < 16; i++) {
- uint8_t x, nm;
-
- x = a->in6.s6_addr[i] ^ b->in6.s6_addr[i];
-
- if (m < 8)
- nm = 0xFF << (8 - m);
- else
- nm = 0xFF;
-
- if ((x & nm) != 0)
- return 0;
-
- if (m > 8)
- m -= 8;
- else
- m = 0;
- }
-
- return 1;
- }
-
- return -EAFNOSUPPORT;
-}
-
-int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen) {
- assert(u);
-
- /* Increases the network part of an address by one. Returns
- * positive it that succeeds, or 0 if this overflows. */
-
- if (prefixlen <= 0)
- return 0;
-
- if (family == AF_INET) {
- uint32_t c, n;
-
- if (prefixlen > 32)
- prefixlen = 32;
-
- c = be32toh(u->in.s_addr);
- n = c + (1UL << (32 - prefixlen));
- if (n < c)
- return 0;
- n &= 0xFFFFFFFFUL << (32 - prefixlen);
-
- u->in.s_addr = htobe32(n);
- return 1;
- }
-
- if (family == AF_INET6) {
- struct in6_addr add = {}, result;
- uint8_t overflow = 0;
- unsigned i;
-
- if (prefixlen > 128)
- prefixlen = 128;
-
- /* First calculate what we have to add */
- add.s6_addr[(prefixlen-1) / 8] = 1 << (7 - (prefixlen-1) % 8);
-
- for (i = 16; i > 0; i--) {
- unsigned j = i - 1;
-
- result.s6_addr[j] = u->in6.s6_addr[j] + add.s6_addr[j] + overflow;
- overflow = (result.s6_addr[j] < u->in6.s6_addr[j]);
- }
-
- if (overflow)
- return 0;
-
- u->in6 = result;
- return 1;
- }
-
- return -EAFNOSUPPORT;
-}
-
-int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
- char *x;
- size_t l;
-
- assert(u);
- assert(ret);
-
- if (family == AF_INET)
- l = INET_ADDRSTRLEN;
- else if (family == AF_INET6)
- l = INET6_ADDRSTRLEN;
- else
- return -EAFNOSUPPORT;
-
- x = new(char, l);
- if (!x)
- return -ENOMEM;
-
- errno = 0;
- if (!inet_ntop(family, u, x, l)) {
- free(x);
- return errno > 0 ? -errno : -EINVAL;
- }
-
- *ret = x;
- return 0;
-}
-
-int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) {
- size_t l;
- char *x;
- int r;
-
- assert(u);
- assert(ret);
-
- /* Much like in_addr_to_string(), but optionally appends the zone interface index to the address, to properly
- * handle IPv6 link-local addresses. */
-
- if (family != AF_INET6)
- goto fallback;
- if (ifindex <= 0)
- goto fallback;
-
- r = in_addr_is_link_local(family, u);
- if (r < 0)
- return r;
- if (r == 0)
- goto fallback;
-
- l = INET6_ADDRSTRLEN + 1 + DECIMAL_STR_MAX(ifindex) + 1;
- x = new(char, l);
- if (!x)
- return -ENOMEM;
-
- errno = 0;
- if (!inet_ntop(family, u, x, l)) {
- free(x);
- return errno > 0 ? -errno : -EINVAL;
- }
-
- sprintf(strchr(x, 0), "%%%i", ifindex);
- *ret = x;
-
- return 0;
-
-fallback:
- return in_addr_to_string(family, u, ret);
-}
-
-int in_addr_from_string(int family, const char *s, union in_addr_union *ret) {
-
- assert(s);
- assert(ret);
-
- if (!IN_SET(family, AF_INET, AF_INET6))
- return -EAFNOSUPPORT;
-
- errno = 0;
- if (inet_pton(family, s, ret) <= 0)
- return errno > 0 ? -errno : -EINVAL;
-
- return 0;
-}
-
-int in_addr_from_string_auto(const char *s, int *family, union in_addr_union *ret) {
- int r;
-
- assert(s);
- assert(family);
- assert(ret);
-
- r = in_addr_from_string(AF_INET, s, ret);
- if (r >= 0) {
- *family = AF_INET;
- return 0;
- }
-
- r = in_addr_from_string(AF_INET6, s, ret);
- if (r >= 0) {
- *family = AF_INET6;
- return 0;
- }
-
- return -EINVAL;
-}
-
-int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex) {
- const char *suffix;
- int r, ifi = 0;
-
- assert(s);
- assert(family);
- assert(ret);
-
- /* Similar to in_addr_from_string_auto() but also parses an optionally appended IPv6 zone suffix ("scope id")
- * if one is found. */
-
- suffix = strchr(s, '%');
- if (suffix) {
-
- if (ifindex) {
- /* If we shall return the interface index, try to parse it */
- r = parse_ifindex(suffix + 1, &ifi);
- if (r < 0) {
- unsigned u;
-
- u = if_nametoindex(suffix + 1);
- if (u <= 0)
- return -errno;
-
- ifi = (int) u;
- }
- }
-
- s = strndupa(s, suffix - s);
- }
-
- r = in_addr_from_string_auto(s, family, ret);
- if (r < 0)
- return r;
-
- if (ifindex)
- *ifindex = ifi;
-
- return r;
-}
-
-unsigned char in_addr_netmask_to_prefixlen(const struct in_addr *addr) {
- assert(addr);
-
- return 32 - u32ctz(be32toh(addr->s_addr));
-}
-
-struct in_addr* in_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char prefixlen) {
- assert(addr);
- assert(prefixlen <= 32);
-
- /* Shifting beyond 32 is not defined, handle this specially. */
- if (prefixlen == 0)
- addr->s_addr = 0;
- else
- addr->s_addr = htobe32((0xffffffff << (32 - prefixlen)) & 0xffffffff);
-
- return addr;
-}
-
-int in_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen) {
- uint8_t msb_octet = *(uint8_t*) addr;
-
- /* addr may not be aligned, so make sure we only access it byte-wise */
-
- assert(addr);
- assert(prefixlen);
-
- if (msb_octet < 128)
- /* class A, leading bits: 0 */
- *prefixlen = 8;
- else if (msb_octet < 192)
- /* class B, leading bits 10 */
- *prefixlen = 16;
- else if (msb_octet < 224)
- /* class C, leading bits 110 */
- *prefixlen = 24;
- else
- /* class D or E, no default prefixlen */
- return -ERANGE;
-
- return 0;
-}
-
-int in_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mask) {
- unsigned char prefixlen;
- int r;
-
- assert(addr);
- assert(mask);
-
- r = in_addr_default_prefixlen(addr, &prefixlen);
- if (r < 0)
- return r;
-
- in_addr_prefixlen_to_netmask(mask, prefixlen);
- return 0;
-}
-
-int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen) {
- assert(addr);
-
- if (family == AF_INET) {
- struct in_addr mask;
-
- if (!in_addr_prefixlen_to_netmask(&mask, prefixlen))
- return -EINVAL;
-
- addr->in.s_addr &= mask.s_addr;
- return 0;
- }
-
- if (family == AF_INET6) {
- unsigned i;
-
- for (i = 0; i < 16; i++) {
- uint8_t mask;
-
- if (prefixlen >= 8) {
- mask = 0xFF;
- prefixlen -= 8;
- } else {
- mask = 0xFF << (8 - prefixlen);
- prefixlen = 0;
- }
-
- addr->in6.s6_addr[i] &= mask;
- }
-
- return 0;
- }
-
- return -EAFNOSUPPORT;
-}
diff --git a/src/basic/in-addr-util.h b/src/basic/in-addr-util.h
deleted file mode 100644
index d60064aef8..0000000000
--- a/src/basic/in-addr-util.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 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 <netinet/in.h>
-#include <stddef.h>
-#include <sys/socket.h>
-
-#include "macro.h"
-#include "util.h"
-
-union in_addr_union {
- struct in_addr in;
- struct in6_addr in6;
-};
-
-struct in_addr_data {
- int family;
- union in_addr_union address;
-};
-
-bool in4_addr_is_null(const struct in_addr *a);
-bool in6_addr_is_null(const struct in6_addr *a);
-
-int in_addr_is_null(int family, const union in_addr_union *u);
-int in_addr_is_link_local(int family, const union in_addr_union *u);
-int in_addr_is_localhost(int family, const union in_addr_union *u);
-int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b);
-int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen);
-int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen);
-int in_addr_to_string(int family, const union in_addr_union *u, char **ret);
-int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret);
-int in_addr_from_string(int family, const char *s, union in_addr_union *ret);
-int in_addr_from_string_auto(const char *s, int *family, union in_addr_union *ret);
-int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex);
-unsigned char in_addr_netmask_to_prefixlen(const struct in_addr *addr);
-struct in_addr* in_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char prefixlen);
-int in_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen);
-int in_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mask);
-int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen);
-
-static inline size_t FAMILY_ADDRESS_SIZE(int family) {
- assert(family == AF_INET || family == AF_INET6);
- return family == AF_INET6 ? 16 : 4;
-}
-
-#define IN_ADDR_NULL ((union in_addr_union) {})
diff --git a/src/basic/io-util.c b/src/basic/io-util.c
deleted file mode 100644
index cc6dfa8c1b..0000000000
--- a/src/basic/io-util.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/***
- 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 <limits.h>
-#include <poll.h>
-#include <stdio.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "io-util.h"
-#include "time-util.h"
-
-int flush_fd(int fd) {
- struct pollfd pollfd = {
- .fd = fd,
- .events = POLLIN,
- };
-
- /* Read from the specified file descriptor, until POLLIN is not set anymore, throwing away everything
- * read. Note that some file descriptors (notable IP sockets) will trigger POLLIN even when no data can be read
- * (due to IP packet checksum mismatches), hence this function is only safe to be non-blocking if the fd used
- * was set to non-blocking too. */
-
- for (;;) {
- char buf[LINE_MAX];
- ssize_t l;
- int r;
-
- r = poll(&pollfd, 1, 0);
- if (r < 0) {
- if (errno == EINTR)
- continue;
-
- return -errno;
-
- } else if (r == 0)
- return 0;
-
- l = read(fd, buf, sizeof(buf));
- if (l < 0) {
-
- if (errno == EINTR)
- continue;
-
- if (errno == EAGAIN)
- return 0;
-
- return -errno;
- } else if (l == 0)
- return 0;
- }
-}
-
-ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
- uint8_t *p = buf;
- ssize_t n = 0;
-
- assert(fd >= 0);
- assert(buf);
-
- /* If called with nbytes == 0, let's call read() at least
- * once, to validate the operation */
-
- if (nbytes > (size_t) SSIZE_MAX)
- return -EINVAL;
-
- do {
- ssize_t k;
-
- k = read(fd, p, nbytes);
- if (k < 0) {
- if (errno == EINTR)
- continue;
-
- if (errno == EAGAIN && do_poll) {
-
- /* We knowingly ignore any return value here,
- * and expect that any error/EOF is reported
- * via read() */
-
- (void) fd_wait_for_event(fd, POLLIN, USEC_INFINITY);
- continue;
- }
-
- return n > 0 ? n : -errno;
- }
-
- if (k == 0)
- return n;
-
- assert((size_t) k <= nbytes);
-
- p += k;
- nbytes -= k;
- n += k;
- } while (nbytes > 0);
-
- return n;
-}
-
-int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll) {
- ssize_t n;
-
- n = loop_read(fd, buf, nbytes, do_poll);
- if (n < 0)
- return (int) n;
- if ((size_t) n != nbytes)
- return -EIO;
-
- return 0;
-}
-
-int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
- const uint8_t *p = buf;
-
- assert(fd >= 0);
- assert(buf);
-
- if (nbytes > (size_t) SSIZE_MAX)
- return -EINVAL;
-
- do {
- ssize_t k;
-
- k = write(fd, p, nbytes);
- if (k < 0) {
- if (errno == EINTR)
- continue;
-
- if (errno == EAGAIN && do_poll) {
- /* We knowingly ignore any return value here,
- * and expect that any error/EOF is reported
- * via write() */
-
- (void) fd_wait_for_event(fd, POLLOUT, USEC_INFINITY);
- continue;
- }
-
- return -errno;
- }
-
- if (_unlikely_(nbytes > 0 && k == 0)) /* Can't really happen */
- return -EIO;
-
- assert((size_t) k <= nbytes);
-
- p += k;
- nbytes -= k;
- } while (nbytes > 0);
-
- return 0;
-}
-
-int pipe_eof(int fd) {
- struct pollfd pollfd = {
- .fd = fd,
- .events = POLLIN|POLLHUP,
- };
-
- int r;
-
- 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 = {
- .fd = fd,
- .events = event,
- };
-
- struct timespec ts;
- int r;
-
- r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL);
- if (r < 0)
- return -errno;
-
- if (r == 0)
- return 0;
-
- return pollfd.revents;
-}
-
-static size_t nul_length(const uint8_t *p, size_t sz) {
- size_t n = 0;
-
- while (sz > 0) {
- if (*p != 0)
- break;
-
- n++;
- p++;
- sz--;
- }
-
- return n;
-}
-
-ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length) {
- const uint8_t *q, *w, *e;
- ssize_t l;
-
- q = w = p;
- e = q + sz;
- while (q < e) {
- size_t n;
-
- n = nul_length(q, e - q);
-
- /* If there are more than the specified run length of
- * NUL bytes, or if this is the beginning or the end
- * of the buffer, then seek instead of write */
- if ((n > run_length) ||
- (n > 0 && q == p) ||
- (n > 0 && q + n >= e)) {
- if (q > w) {
- l = write(fd, w, q - w);
- if (l < 0)
- return -errno;
- if (l != q -w)
- return -EIO;
- }
-
- if (lseek(fd, n, SEEK_CUR) == (off_t) -1)
- return -errno;
-
- q += n;
- w = q;
- } else if (n > 0)
- q += n;
- else
- q++;
- }
-
- if (q > w) {
- l = write(fd, w, q - w);
- if (l < 0)
- return -errno;
- if (l != q - w)
- return -EIO;
- }
-
- return q - (const uint8_t*) p;
-}
diff --git a/src/basic/io-util.h b/src/basic/io-util.h
deleted file mode 100644
index 4684ed3bfc..0000000000
--- a/src/basic/io-util.h
+++ /dev/null
@@ -1,95 +0,0 @@
-#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 <stddef.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-
-#include "macro.h"
-#include "time-util.h"
-
-int flush_fd(int fd);
-
-ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll);
-int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll);
-int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll);
-
-int pipe_eof(int fd);
-
-int fd_wait_for_event(int fd, int event, usec_t timeout);
-
-ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length);
-
-#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;
-}
-
-static inline bool FILE_SIZE_VALID(uint64_t l) {
- /* ftruncate() and friends take an unsigned file size, but actually cannot deal with file sizes larger than
- * 2^63 since the kernel internally handles it as signed value. This call allows checking for this early. */
-
- return (l >> 63) == 0;
-}
-
-static inline bool FILE_SIZE_VALID_OR_INFINITY(uint64_t l) {
-
- /* Same as above, but allows one extra value: -1 as indication for infinity. */
-
- if (l == (uint64_t) -1)
- return true;
-
- return FILE_SIZE_VALID(l);
-
-}
diff --git a/src/basic/ioprio.h b/src/basic/ioprio.h
deleted file mode 100644
index d8bb6eb497..0000000000
--- a/src/basic/ioprio.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef IOPRIO_H
-#define IOPRIO_H
-
-/* This is minimal version of Linux' linux/ioprio.h header file, which
- * is licensed GPL2 */
-
-#include <sys/syscall.h>
-#include <unistd.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/basic/label.c b/src/basic/label.c
deleted file mode 100644
index f5ab855d32..0000000000
--- a/src/basic/label.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/***
- 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 <sys/stat.h>
-#include <unistd.h>
-
-#include "label.h"
-#include "macro.h"
-#include "selinux-util.h"
-#include "smack-util.h"
-
-int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
- int r, q;
-
- r = mac_selinux_fix(path, ignore_enoent, ignore_erofs);
- q = mac_smack_fix(path, ignore_enoent, ignore_erofs);
-
- if (r < 0)
- return r;
- if (q < 0)
- return q;
-
- return 0;
-}
-
-int mkdir_label(const char *path, mode_t mode) {
- int r;
-
- assert(path);
-
- r = mac_selinux_create_file_prepare(path, S_IFDIR);
- if (r < 0)
- return r;
-
- if (mkdir(path, mode) < 0)
- r = -errno;
-
- mac_selinux_create_file_clear();
-
- if (r < 0)
- return r;
-
- return mac_smack_fix(path, false, false);
-}
-
-int symlink_label(const char *old_path, const char *new_path) {
- int r;
-
- assert(old_path);
- assert(new_path);
-
- r = mac_selinux_create_file_prepare(new_path, S_IFLNK);
- if (r < 0)
- return r;
-
- if (symlink(old_path, new_path) < 0)
- r = -errno;
-
- mac_selinux_create_file_clear();
-
- if (r < 0)
- return r;
-
- return mac_smack_fix(new_path, false, false);
-}
diff --git a/src/basic/label.h b/src/basic/label.h
deleted file mode 100644
index 3e9251aa71..0000000000
--- a/src/basic/label.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#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 <sys/types.h>
-
-int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
-
-int mkdir_label(const char *path, mode_t mode);
-int symlink_label(const char *old_path, const char *new_path);
diff --git a/src/basic/list.h b/src/basic/list.h
deleted file mode 100644
index c3771a177f..0000000000
--- a/src/basic/list.h
+++ /dev/null
@@ -1,184 +0,0 @@
-#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/>.
-***/
-
-/* The head of the linked list. Use this in the structure that shall
- * contain the head of the linked list */
-#define LIST_HEAD(t,name) \
- t *name
-
-/* The pointers in the linked list's items. Use this in the item structure */
-#define LIST_FIELDS(t,name) \
- t *name##_next, *name##_prev
-
-/* Initialize the list's head */
-#define LIST_HEAD_INIT(head) \
- do { \
- (head) = NULL; } \
- while (false)
-
-/* Initialize a list item */
-#define LIST_INIT(name,item) \
- do { \
- typeof(*(item)) *_item = (item); \
- assert(_item); \
- _item->name##_prev = _item->name##_next = NULL; \
- } while (false)
-
-/* Prepend an item to the list */
-#define LIST_PREPEND(name,head,item) \
- do { \
- typeof(*(head)) **_head = &(head), *_item = (item); \
- assert(_item); \
- if ((_item->name##_next = *_head)) \
- _item->name##_next->name##_prev = _item; \
- _item->name##_prev = NULL; \
- *_head = _item; \
- } while (false)
-
-/* Append an item to the list */
-#define LIST_APPEND(name,head,item) \
- do { \
- typeof(*(head)) *_tail; \
- LIST_FIND_TAIL(name,head,_tail); \
- LIST_INSERT_AFTER(name,head,_tail,item); \
- } while (false)
-
-/* Remove an item from the list */
-#define LIST_REMOVE(name,head,item) \
- do { \
- typeof(*(head)) **_head = &(head), *_item = (item); \
- assert(_item); \
- if (_item->name##_next) \
- _item->name##_next->name##_prev = _item->name##_prev; \
- if (_item->name##_prev) \
- _item->name##_prev->name##_next = _item->name##_next; \
- else { \
- assert(*_head == _item); \
- *_head = _item->name##_next; \
- } \
- _item->name##_next = _item->name##_prev = NULL; \
- } while (false)
-
-/* Find the head of the list */
-#define LIST_FIND_HEAD(name,item,head) \
- do { \
- typeof(*(item)) *_item = (item); \
- if (!_item) \
- (head) = NULL; \
- else { \
- while (_item->name##_prev) \
- _item = _item->name##_prev; \
- (head) = _item; \
- } \
- } while (false)
-
-/* Find the tail of the list */
-#define LIST_FIND_TAIL(name,item,tail) \
- do { \
- typeof(*(item)) *_item = (item); \
- if (!_item) \
- (tail) = NULL; \
- else { \
- while (_item->name##_next) \
- _item = _item->name##_next; \
- (tail) = _item; \
- } \
- } while (false)
-
-/* Insert an item after another one (a = where, b = what) */
-#define LIST_INSERT_AFTER(name,head,a,b) \
- do { \
- typeof(*(head)) **_head = &(head), *_a = (a), *_b = (b); \
- assert(_b); \
- if (!_a) { \
- if ((_b->name##_next = *_head)) \
- _b->name##_next->name##_prev = _b; \
- _b->name##_prev = NULL; \
- *_head = _b; \
- } else { \
- if ((_b->name##_next = _a->name##_next)) \
- _b->name##_next->name##_prev = _b; \
- _b->name##_prev = _a; \
- _a->name##_next = _b; \
- } \
- } while (false)
-
-/* Insert an item before another one (a = where, b = what) */
-#define LIST_INSERT_BEFORE(name,head,a,b) \
- do { \
- typeof(*(head)) **_head = &(head), *_a = (a), *_b = (b); \
- assert(_b); \
- if (!_a) { \
- if (!*_head) { \
- _b->name##_next = NULL; \
- _b->name##_prev = NULL; \
- *_head = _b; \
- } else { \
- typeof(*(head)) *_tail = (head); \
- while (_tail->name##_next) \
- _tail = _tail->name##_next; \
- _b->name##_next = NULL; \
- _b->name##_prev = _tail; \
- _tail->name##_next = _b; \
- } \
- } else { \
- if ((_b->name##_prev = _a->name##_prev)) \
- _b->name##_prev->name##_next = _b; \
- else \
- *_head = _b; \
- _b->name##_next = _a; \
- _a->name##_prev = _b; \
- } \
- } while (false)
-
-#define LIST_JUST_US(name,item) \
- (!(item)->name##_prev && !(item)->name##_next) \
-
-#define LIST_FOREACH(name,i,head) \
- for ((i) = (head); (i); (i) = (i)->name##_next)
-
-#define LIST_FOREACH_SAFE(name,i,n,head) \
- for ((i) = (head); (i) && (((n) = (i)->name##_next), 1); (i) = (n))
-
-#define LIST_FOREACH_BEFORE(name,i,p) \
- for ((i) = (p)->name##_prev; (i); (i) = (i)->name##_prev)
-
-#define LIST_FOREACH_AFTER(name,i,p) \
- for ((i) = (p)->name##_next; (i); (i) = (i)->name##_next)
-
-/* Iterate through all the members of the list p is included in, but skip over p */
-#define LIST_FOREACH_OTHERS(name,i,p) \
- for (({ \
- (i) = (p); \
- while ((i) && (i)->name##_prev) \
- (i) = (i)->name##_prev; \
- if ((i) == (p)) \
- (i) = (p)->name##_next; \
- }); \
- (i); \
- (i) = (i)->name##_next == (p) ? (p)->name##_next : (i)->name##_next)
-
-/* Loop starting from p->next until p->prev.
- p can be adjusted meanwhile. */
-#define LIST_LOOP_BUT_ONE(name,i,head,p) \
- for ((i) = (p)->name##_next ? (p)->name##_next : (head); \
- (i) != (p); \
- (i) = (i)->name##_next ? (i)->name##_next : (head))
diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c
deleted file mode 100644
index ada0a28cd8..0000000000
--- a/src/basic/locale-util.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 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 <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <langinfo.h>
-#include <libintl.h>
-#include <locale.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-
-#include "dirent-util.h"
-#include "fd-util.h"
-#include "hashmap.h"
-#include "locale-util.h"
-#include "path-util.h"
-#include "set.h"
-#include "string-table.h"
-#include "string-util.h"
-#include "strv.h"
-#include "utf8.h"
-
-static int add_locales_from_archive(Set *locales) {
- /* Stolen from glibc... */
-
- struct locarhead {
- uint32_t magic;
- /* Serial number. */
- uint32_t serial;
- /* Name hash table. */
- uint32_t namehash_offset;
- uint32_t namehash_used;
- uint32_t namehash_size;
- /* String table. */
- uint32_t string_offset;
- uint32_t string_used;
- uint32_t string_size;
- /* Table with locale records. */
- uint32_t locrectab_offset;
- uint32_t locrectab_used;
- uint32_t locrectab_size;
- /* MD5 sum hash table. */
- uint32_t sumhash_offset;
- uint32_t sumhash_used;
- uint32_t sumhash_size;
- };
-
- struct namehashent {
- /* Hash value of the name. */
- uint32_t hashval;
- /* Offset of the name in the string table. */
- uint32_t name_offset;
- /* Offset of the locale record. */
- uint32_t locrec_offset;
- };
-
- const struct locarhead *h;
- const struct namehashent *e;
- const void *p = MAP_FAILED;
- _cleanup_close_ int fd = -1;
- size_t sz = 0;
- struct stat st;
- unsigned i;
- int r;
-
- fd = open("/usr/lib/locale/locale-archive", O_RDONLY|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return errno == ENOENT ? 0 : -errno;
-
- if (fstat(fd, &st) < 0)
- return -errno;
-
- if (!S_ISREG(st.st_mode))
- return -EBADMSG;
-
- if (st.st_size < (off_t) sizeof(struct locarhead))
- return -EBADMSG;
-
- p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
- if (p == MAP_FAILED)
- return -errno;
-
- h = (const struct locarhead *) p;
- if (h->magic != 0xde020109 ||
- h->namehash_offset + h->namehash_size > st.st_size ||
- h->string_offset + h->string_size > st.st_size ||
- h->locrectab_offset + h->locrectab_size > st.st_size ||
- h->sumhash_offset + h->sumhash_size > st.st_size) {
- r = -EBADMSG;
- goto finish;
- }
-
- e = (const struct namehashent*) ((const uint8_t*) p + h->namehash_offset);
- for (i = 0; i < h->namehash_size; i++) {
- char *z;
-
- if (e[i].locrec_offset == 0)
- continue;
-
- if (!utf8_is_valid((char*) p + e[i].name_offset))
- continue;
-
- z = strdup((char*) p + e[i].name_offset);
- if (!z) {
- r = -ENOMEM;
- goto finish;
- }
-
- r = set_consume(locales, z);
- if (r < 0)
- goto finish;
- }
-
- r = 0;
-
- finish:
- if (p != MAP_FAILED)
- munmap((void*) p, sz);
-
- return r;
-}
-
-static int add_locales_from_libdir (Set *locales) {
- _cleanup_closedir_ DIR *dir = NULL;
- struct dirent *entry;
- int r;
-
- dir = opendir("/usr/lib/locale");
- if (!dir)
- return errno == ENOENT ? 0 : -errno;
-
- FOREACH_DIRENT(entry, dir, return -errno) {
- char *z;
-
- dirent_ensure_type(dir, entry);
-
- if (entry->d_type != DT_DIR)
- continue;
-
- z = strdup(entry->d_name);
- if (!z)
- return -ENOMEM;
-
- r = set_consume(locales, z);
- if (r < 0 && r != -EEXIST)
- return r;
- }
-
- return 0;
-}
-
-int get_locales(char ***ret) {
- _cleanup_set_free_ Set *locales = NULL;
- _cleanup_strv_free_ char **l = NULL;
- int r;
-
- locales = set_new(&string_hash_ops);
- if (!locales)
- return -ENOMEM;
-
- r = add_locales_from_archive(locales);
- if (r < 0 && r != -ENOENT)
- return r;
-
- r = add_locales_from_libdir(locales);
- if (r < 0)
- return r;
-
- l = set_get_strv(locales);
- if (!l)
- return -ENOMEM;
-
- strv_sort(l);
-
- *ret = l;
- l = NULL;
-
- return 0;
-}
-
-bool locale_is_valid(const char *name) {
-
- if (isempty(name))
- return false;
-
- if (strlen(name) >= 128)
- return false;
-
- if (!utf8_is_valid(name))
- return false;
-
- if (!filename_is_valid(name))
- return false;
-
- if (!string_is_safe(name))
- return false;
-
- return true;
-}
-
-void init_gettext(void) {
- setlocale(LC_ALL, "");
- textdomain(GETTEXT_PACKAGE);
-}
-
-bool is_locale_utf8(void) {
- const char *set;
- static int cached_answer = -1;
-
- /* Note that we default to 'true' here, since today UTF8 is
- * pretty much supported everywhere. */
-
- 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;
- }
-
- if (streq(set, "UTF-8")) {
- cached_answer = true;
- goto out;
- }
-
- /* For LC_CTYPE=="C" return true, because CTYPE is effectly
- * unset and everything can do to UTF-8 nowadays. */
- set = setlocale(LC_CTYPE, NULL);
- if (!set) {
- cached_answer = true;
- goto out;
- }
-
- /* Check result, but ignore the result if C was set
- * explicitly. */
- cached_answer =
- STR_IN_SET(set, "C", "POSIX") &&
- !getenv("LC_ALL") &&
- !getenv("LC_CTYPE") &&
- !getenv("LANG");
-
-out:
- return (bool) cached_answer;
-}
-
-
-const char *special_glyph(SpecialGlyph code) {
-
- static const char* const draw_table[2][_SPECIAL_GLYPH_MAX] = {
- /* ASCII fallback */
- [false] = {
- [TREE_VERTICAL] = "| ",
- [TREE_BRANCH] = "|-",
- [TREE_RIGHT] = "`-",
- [TREE_SPACE] = " ",
- [TRIANGULAR_BULLET] = ">",
- [BLACK_CIRCLE] = "*",
- [ARROW] = "->",
- [MDASH] = "-",
- },
-
- /* UTF-8 */
- [ true ] = {
- [TREE_VERTICAL] = "\342\224\202 ", /* │ */
- [TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */
- [TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */
- [TREE_SPACE] = " ", /* */
- [TRIANGULAR_BULLET] = "\342\200\243", /* ‣ */
- [BLACK_CIRCLE] = "\342\227\217", /* ● */
- [ARROW] = "\342\206\222", /* → */
- [MDASH] = "\342\200\223", /* – */
- },
- };
-
- return draw_table[is_locale_utf8()][code];
-}
-
-static const char * const locale_variable_table[_VARIABLE_LC_MAX] = {
- [VARIABLE_LANG] = "LANG",
- [VARIABLE_LANGUAGE] = "LANGUAGE",
- [VARIABLE_LC_CTYPE] = "LC_CTYPE",
- [VARIABLE_LC_NUMERIC] = "LC_NUMERIC",
- [VARIABLE_LC_TIME] = "LC_TIME",
- [VARIABLE_LC_COLLATE] = "LC_COLLATE",
- [VARIABLE_LC_MONETARY] = "LC_MONETARY",
- [VARIABLE_LC_MESSAGES] = "LC_MESSAGES",
- [VARIABLE_LC_PAPER] = "LC_PAPER",
- [VARIABLE_LC_NAME] = "LC_NAME",
- [VARIABLE_LC_ADDRESS] = "LC_ADDRESS",
- [VARIABLE_LC_TELEPHONE] = "LC_TELEPHONE",
- [VARIABLE_LC_MEASUREMENT] = "LC_MEASUREMENT",
- [VARIABLE_LC_IDENTIFICATION] = "LC_IDENTIFICATION"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(locale_variable, LocaleVariable);
diff --git a/src/basic/locale-util.h b/src/basic/locale-util.h
deleted file mode 100644
index 0630a034ab..0000000000
--- a/src/basic/locale-util.h
+++ /dev/null
@@ -1,73 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 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 <libintl.h>
-#include <stdbool.h>
-
-#include "macro.h"
-
-typedef enum LocaleVariable {
- /* We don't list LC_ALL here on purpose. People should be
- * using LANG instead. */
-
- VARIABLE_LANG,
- VARIABLE_LANGUAGE,
- VARIABLE_LC_CTYPE,
- VARIABLE_LC_NUMERIC,
- VARIABLE_LC_TIME,
- VARIABLE_LC_COLLATE,
- VARIABLE_LC_MONETARY,
- VARIABLE_LC_MESSAGES,
- VARIABLE_LC_PAPER,
- VARIABLE_LC_NAME,
- VARIABLE_LC_ADDRESS,
- VARIABLE_LC_TELEPHONE,
- VARIABLE_LC_MEASUREMENT,
- VARIABLE_LC_IDENTIFICATION,
- _VARIABLE_LC_MAX,
- _VARIABLE_LC_INVALID = -1
-} LocaleVariable;
-
-int get_locales(char ***l);
-bool locale_is_valid(const char *name);
-
-#define _(String) gettext(String)
-#define N_(String) String
-void init_gettext(void);
-
-bool is_locale_utf8(void);
-
-typedef enum {
- TREE_VERTICAL,
- TREE_BRANCH,
- TREE_RIGHT,
- TREE_SPACE,
- TRIANGULAR_BULLET,
- BLACK_CIRCLE,
- ARROW,
- MDASH,
- _SPECIAL_GLYPH_MAX
-} SpecialGlyph;
-
-const char *special_glyph(SpecialGlyph code) _const_;
-
-const char* locale_variable_to_string(LocaleVariable i) _const_;
-LocaleVariable locale_variable_from_string(const char *s) _pure_;
diff --git a/src/basic/lockfile-util.c b/src/basic/lockfile-util.c
deleted file mode 100644
index 3ee4191e4d..0000000000
--- a/src/basic/lockfile-util.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/***
- 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 <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-
-#include "alloc-util.h"
-#include "fd-util.h"
-#include "fs-util.h"
-#include "lockfile-util.h"
-#include "macro.h"
-#include "path-util.h"
-
-int make_lock_file(const char *p, int operation, LockFile *ret) {
- _cleanup_close_ int fd = -1;
- _cleanup_free_ char *t = NULL;
- int r;
-
- /*
- * We use UNPOSIX locks if they are available. They have nice
- * semantics, and are mostly compatible with NFS. However,
- * they are only available on new kernels. When we detect we
- * are running on an older kernel, then we fall back to good
- * old BSD locks. They also have nice semantics, but are
- * slightly problematic on NFS, where they are upgraded to
- * POSIX locks, even though locally they are orthogonal to
- * POSIX locks.
- */
-
- t = strdup(p);
- if (!t)
- return -ENOMEM;
-
- for (;;) {
- struct flock fl = {
- .l_type = (operation & ~LOCK_NB) == LOCK_EX ? F_WRLCK : F_RDLCK,
- .l_whence = SEEK_SET,
- };
- struct stat st;
-
- fd = open(p, O_CREAT|O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NOCTTY, 0600);
- if (fd < 0)
- return -errno;
-
- r = fcntl(fd, (operation & LOCK_NB) ? F_OFD_SETLK : F_OFD_SETLKW, &fl);
- if (r < 0) {
-
- /* If the kernel is too old, use good old BSD locks */
- if (errno == EINVAL)
- r = flock(fd, operation);
-
- if (r < 0)
- return errno == EAGAIN ? -EBUSY : -errno;
- }
-
- /* If we acquired the lock, let's check if the file
- * still exists in the file system. If not, then the
- * previous exclusive owner removed it and then closed
- * it. In such a case our acquired lock is worthless,
- * hence try again. */
-
- r = fstat(fd, &st);
- if (r < 0)
- return -errno;
- if (st.st_nlink > 0)
- break;
-
- fd = safe_close(fd);
- }
-
- ret->path = t;
- ret->fd = fd;
- ret->operation = operation;
-
- fd = -1;
- t = NULL;
-
- return r;
-}
-
-int make_lock_file_for(const char *p, int operation, LockFile *ret) {
- const char *fn;
- char *t;
-
- assert(p);
- assert(ret);
-
- fn = basename(p);
- if (!filename_is_valid(fn))
- return -EINVAL;
-
- t = newa(char, strlen(p) + 2 + 4 + 1);
- stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), fn), ".lck");
-
- return make_lock_file(t, operation, ret);
-}
-
-void release_lock_file(LockFile *f) {
- int r;
-
- if (!f)
- return;
-
- if (f->path) {
-
- /* If we are the exclusive owner we can safely delete
- * the lock file itself. If we are not the exclusive
- * owner, we can try becoming it. */
-
- if (f->fd >= 0 &&
- (f->operation & ~LOCK_NB) == LOCK_SH) {
- static const struct flock fl = {
- .l_type = F_WRLCK,
- .l_whence = SEEK_SET,
- };
-
- r = fcntl(f->fd, F_OFD_SETLK, &fl);
- if (r < 0 && errno == EINVAL)
- r = flock(f->fd, LOCK_EX|LOCK_NB);
-
- if (r >= 0)
- f->operation = LOCK_EX|LOCK_NB;
- }
-
- if ((f->operation & ~LOCK_NB) == LOCK_EX)
- unlink_noerrno(f->path);
-
- f->path = mfree(f->path);
- }
-
- f->fd = safe_close(f->fd);
- f->operation = 0;
-}
diff --git a/src/basic/lockfile-util.h b/src/basic/lockfile-util.h
deleted file mode 100644
index 22491ee8e1..0000000000
--- a/src/basic/lockfile-util.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 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 <stddef.h>
-
-#include "macro.h"
-#include "missing.h"
-
-typedef struct LockFile {
- char *path;
- int fd;
- int operation;
-} LockFile;
-
-int make_lock_file(const char *p, int operation, LockFile *ret);
-int make_lock_file_for(const char *p, int operation, LockFile *ret);
-void release_lock_file(LockFile *f);
-
-#define _cleanup_release_lock_file_ _cleanup_(release_lock_file)
-
-#define LOCK_FILE_INIT { .fd = -1, .path = NULL }
diff --git a/src/basic/log.c b/src/basic/log.c
deleted file mode 100644
index 4919d175da..0000000000
--- a/src/basic/log.c
+++ /dev/null
@@ -1,1177 +0,0 @@
-/***
- 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 <fcntl.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/signalfd.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/uio.h>
-#include <sys/un.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "sd-messages.h"
-
-#include "alloc-util.h"
-#include "fd-util.h"
-#include "formats-util.h"
-#include "io-util.h"
-#include "log.h"
-#include "macro.h"
-#include "missing.h"
-#include "parse-util.h"
-#include "proc-cmdline.h"
-#include "process-util.h"
-#include "signal-util.h"
-#include "socket-util.h"
-#include "stdio-util.h"
-#include "string-table.h"
-#include "string-util.h"
-#include "syslog-util.h"
-#include "terminal-util.h"
-#include "time-util.h"
-#include "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;
-
-static bool upgrade_syslog_to_journal = 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)
- safe_close(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) {
- kmsg_fd = safe_close(kmsg_fd);
-}
-
-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) {
- syslog_fd = safe_close(syslog_fd);
-}
-
-static int create_log_socket(int type) {
- struct timeval tv;
- int fd;
-
- fd = socket(AF_UNIX, type|SOCK_CLOEXEC, 0);
- if (fd < 0)
- return -errno;
-
- (void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
-
- /* We need a blocking fd here since we'd otherwise lose
- messages way too early. However, let's not hang forever in the
- unlikely case of a deadlock. */
- if (getpid() == 1)
- timeval_store(&tv, 10 * USEC_PER_MSEC);
- else
- timeval_store(&tv, 10 * USEC_PER_SEC);
- (void) setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
-
- return fd;
-}
-
-static int log_open_syslog(void) {
-
- static const union sockaddr_union sa = {
- .un.sun_family = AF_UNIX,
- .un.sun_path = "/dev/log",
- };
-
- int r;
-
- if (syslog_fd >= 0)
- return 0;
-
- syslog_fd = create_log_socket(SOCK_DGRAM);
- if (syslog_fd < 0) {
- r = syslog_fd;
- goto fail;
- }
-
- if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
- safe_close(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, SOCKADDR_UN_LEN(sa.un)) < 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) {
- journal_fd = safe_close(journal_fd);
-}
-
-static int log_open_journal(void) {
-
- static const union sockaddr_union sa = {
- .un.sun_family = AF_UNIX,
- .un.sun_path = "/run/systemd/journal/socket",
- };
-
- int r;
-
- if (journal_fd >= 0)
- return 0;
-
- journal_fd = create_log_socket(SOCK_DGRAM);
- if (journal_fd < 0) {
- r = journal_fd;
- goto fail;
- }
-
- if (connect(journal_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 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();
-
- return log_open_console();
-}
-
-void log_set_target(LogTarget target) {
- assert(target >= 0);
- assert(target < _LOG_TARGET_MAX);
-
- if (upgrade_syslog_to_journal) {
- if (target == LOG_TARGET_SYSLOG)
- target = LOG_TARGET_JOURNAL;
- else if (target == LOG_TARGET_SYSLOG_OR_KMSG)
- target = LOG_TARGET_JOURNAL_OR_KMSG;
- }
-
- 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,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *buffer) {
-
- char location[256], prefix[1 + DECIMAL_STR_MAX(int) + 2];
- struct iovec iovec[6] = {};
- unsigned n = 0;
- bool highlight;
-
- if (console_fd < 0)
- return 0;
-
- if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
- xsprintf(prefix, "<%i>", level);
- IOVEC_SET_STRING(iovec[n++], prefix);
- }
-
- highlight = LOG_PRI(level) <= LOG_ERR && show_color;
-
- if (show_location) {
- snprintf(location, sizeof(location), "(%s:%i) ", file, line);
- IOVEC_SET_STRING(iovec[n++], location);
- }
-
- if (highlight)
- IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_RED);
- IOVEC_SET_STRING(iovec[n++], buffer);
- if (highlight)
- IOVEC_SET_STRING(iovec[n++], ANSI_NORMAL);
- IOVEC_SET_STRING(iovec[n++], "\n");
-
- if (writev(console_fd, iovec, n) < 0) {
-
- if (errno == EIO && getpid() == 1) {
-
- /* If somebody tried to kick us from our
- * console tty (via vhangup() or suchlike),
- * try to reconnect */
-
- log_close_console();
- log_open_console();
-
- if (console_fd < 0)
- return 0;
-
- if (writev(console_fd, iovec, n) < 0)
- return -errno;
- } else
- return -errno;
- }
-
- return 1;
-}
-
-static int write_to_syslog(
- int level,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *buffer) {
-
- char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
- header_time[64],
- header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
- struct iovec iovec[5] = {};
- struct msghdr msghdr = {
- .msg_iov = iovec,
- .msg_iovlen = ELEMENTSOF(iovec),
- };
- time_t t;
- struct tm *tm;
-
- if (syslog_fd < 0)
- return 0;
-
- xsprintf(header_priority, "<%i>", level);
-
- t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
- tm = localtime(&t);
- if (!tm)
- return -EINVAL;
-
- if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
- return -EINVAL;
-
- xsprintf(header_pid, "["PID_FMT"]: ", getpid());
-
- 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++;
-
- 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,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *buffer) {
-
- char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
- header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
- struct iovec iovec[5] = {};
-
- if (kmsg_fd < 0)
- return 0;
-
- xsprintf(header_priority, "<%i>", level);
- xsprintf(header_pid, "["PID_FMT"]: ", getpid());
-
- 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 log_do_header(
- char *header,
- size_t size,
- int level,
- int error,
- const char *file, int line, const char *func,
- const char *object_field, const char *object,
- const char *extra_field, const char *extra) {
-
- snprintf(header, size,
- "PRIORITY=%i\n"
- "SYSLOG_FACILITY=%i\n"
- "%s%s%s"
- "%s%.*i%s"
- "%s%s%s"
- "%s%.*i%s"
- "%s%s%s"
- "%s%s%s"
- "SYSLOG_IDENTIFIER=%s\n",
- LOG_PRI(level),
- LOG_FAC(level),
- isempty(file) ? "" : "CODE_FILE=",
- isempty(file) ? "" : file,
- isempty(file) ? "" : "\n",
- line ? "CODE_LINE=" : "",
- line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
- line ? "\n" : "",
- isempty(func) ? "" : "CODE_FUNCTION=",
- isempty(func) ? "" : func,
- isempty(func) ? "" : "\n",
- error ? "ERRNO=" : "",
- error ? 1 : 0, error,
- error ? "\n" : "",
- isempty(object) ? "" : object_field,
- isempty(object) ? "" : object,
- isempty(object) ? "" : "\n",
- isempty(extra) ? "" : extra_field,
- isempty(extra) ? "" : extra,
- isempty(extra) ? "" : "\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int write_to_journal(
- int level,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *object_field,
- const char *object,
- const char *extra_field,
- const char *extra,
- const char *buffer) {
-
- char header[LINE_MAX];
- struct iovec iovec[4] = {};
- struct msghdr mh = {};
-
- if (journal_fd < 0)
- return 0;
-
- log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object, extra_field, extra);
-
- IOVEC_SET_STRING(iovec[0], header);
- IOVEC_SET_STRING(iovec[1], "MESSAGE=");
- IOVEC_SET_STRING(iovec[2], buffer);
- IOVEC_SET_STRING(iovec[3], "\n");
-
- 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,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *object_field,
- const char *object,
- const char *extra,
- const char *extra_field,
- char *buffer) {
-
- assert(buffer);
-
- if (error < 0)
- error = -error;
-
- if (log_target == LOG_TARGET_NULL)
- return -error;
-
- /* 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, error, file, line, func, object_field, object, extra_field, extra, buffer);
- if (k < 0) {
- if (k != -EAGAIN)
- log_close_journal();
- log_open_kmsg();
- }
- }
-
- if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
- log_target == LOG_TARGET_SYSLOG) {
-
- k = write_to_syslog(level, error, file, line, func, buffer);
- if (k < 0) {
- if (k != -EAGAIN)
- log_close_syslog();
- log_open_kmsg();
- }
- }
-
- 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, error, file, line, func, buffer);
- if (k < 0) {
- log_close_kmsg();
- log_open_console();
- }
- }
-
- if (k <= 0)
- (void) write_to_console(level, error, file, line, func, buffer);
-
- buffer = e;
- } while (buffer);
-
- return -error;
-}
-
-int log_dump_internal(
- int level,
- int error,
- const char *file,
- int line,
- const char *func,
- char *buffer) {
-
- PROTECT_ERRNO;
-
- /* This modifies the buffer... */
-
- if (error < 0)
- error = -error;
-
- if (_likely_(LOG_PRI(level) > log_max_level))
- return -error;
-
- return log_dispatch(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
-}
-
-int log_internalv(
- int level,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *format,
- va_list ap) {
-
- PROTECT_ERRNO;
- char buffer[LINE_MAX];
-
- if (error < 0)
- error = -error;
-
- if (_likely_(LOG_PRI(level) > log_max_level))
- return -error;
-
- /* Make sure that %m maps to the specified error */
- if (error != 0)
- errno = error;
-
- vsnprintf(buffer, sizeof(buffer), format, ap);
-
- return log_dispatch(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
-}
-
-int log_internal(
- int level,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *format, ...) {
-
- va_list ap;
- int r;
-
- va_start(ap, format);
- r = log_internalv(level, error, file, line, func, format, ap);
- va_end(ap);
-
- return r;
-}
-
-int log_object_internalv(
- int level,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *object_field,
- const char *object,
- const char *extra_field,
- const char *extra,
- const char *format,
- va_list ap) {
-
- PROTECT_ERRNO;
- char *buffer, *b;
- size_t l;
-
- if (error < 0)
- error = -error;
-
- if (_likely_(LOG_PRI(level) > log_max_level))
- return -error;
-
- /* Make sure that %m maps to the specified error */
- if (error != 0)
- errno = error;
-
- /* Prepend the object name before the message */
- if (object) {
- size_t n;
-
- n = strlen(object);
- l = n + 2 + LINE_MAX;
-
- buffer = newa(char, l);
- b = stpcpy(stpcpy(buffer, object), ": ");
- } else {
- l = LINE_MAX;
- b = buffer = newa(char, l);
- }
-
- vsnprintf(b, l, format, ap);
-
- return log_dispatch(level, error, file, line, func, object_field, object, extra_field, extra, buffer);
-}
-
-int log_object_internal(
- int level,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *object_field,
- const char *object,
- const char *extra_field,
- const char *extra,
- const char *format, ...) {
-
- va_list ap;
- int r;
-
- va_start(ap, format);
- r = log_object_internalv(level, error, file, line, func, object_field, object, extra_field, extra, format, ap);
- va_end(ap);
-
- return r;
-}
-
-static void log_assert(
- int level,
- const char *text,
- const char *file,
- int line,
- const char *func,
- const char *format) {
-
- static char buffer[LINE_MAX];
-
- if (_likely_(LOG_PRI(level) > log_max_level))
- return;
-
- DISABLE_WARNING_FORMAT_NONLITERAL;
- snprintf(buffer, sizeof buffer, format, text, file, line, func);
- REENABLE_WARNING;
-
- log_abort_msg = buffer;
-
- log_dispatch(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer);
-}
-
-noreturn void log_assert_failed(const char *text, const char *file, int line, const char *func) {
- log_assert(LOG_CRIT, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
- abort();
-}
-
-noreturn void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) {
- log_assert(LOG_CRIT, text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
- abort();
-}
-
-void log_assert_failed_return(const char *text, const char *file, int line, const char *func) {
- PROTECT_ERRNO;
- log_assert(LOG_DEBUG, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
-}
-
-int log_oom_internal(const char *file, int line, const char *func) {
- log_internal(LOG_ERR, ENOMEM, file, line, func, "Out of memory.");
- return -ENOMEM;
-}
-
-int log_format_iovec(
- struct iovec *iovec,
- unsigned iovec_len,
- unsigned *n,
- bool newline_separator,
- int error,
- const char *format,
- va_list ap) {
-
- static const char nl = '\n';
-
- while (format && *n + 1 < iovec_len) {
- va_list aq;
- char *m;
- int r;
-
- /* We need to copy the va_list structure,
- * since vasprintf() leaves it afterwards at
- * an undefined location */
-
- if (error != 0)
- errno = error;
-
- va_copy(aq, ap);
- r = vasprintf(&m, format, aq);
- va_end(aq);
- if (r < 0)
- return -EINVAL;
-
- /* Now, jump enough ahead, so that we point to
- * the next format string */
- VA_FORMAT_ADVANCE(format, ap);
-
- IOVEC_SET_STRING(iovec[(*n)++], m);
-
- if (newline_separator) {
- iovec[*n].iov_base = (char*) &nl;
- iovec[*n].iov_len = 1;
- (*n)++;
- }
-
- format = va_arg(ap, char *);
- }
- return 0;
-}
-
-int log_struct_internal(
- int level,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *format, ...) {
-
- char buf[LINE_MAX];
- bool found = false;
- PROTECT_ERRNO;
- va_list ap;
-
- if (error < 0)
- error = -error;
-
- if (_likely_(LOG_PRI(level) > log_max_level))
- return -error;
-
- if (log_target == LOG_TARGET_NULL)
- return -error;
-
- if ((level & LOG_FACMASK) == 0)
- level = log_facility | LOG_PRI(level);
-
- 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;
- int r;
- struct msghdr mh = {
- .msg_iov = iovec,
- };
- bool fallback = false;
-
- /* If the journal is available do structured logging */
- log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
- IOVEC_SET_STRING(iovec[n++], header);
-
- va_start(ap, format);
- r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, true, error, format, ap);
- if (r < 0)
- fallback = true;
- else {
- mh.msg_iovlen = n;
- (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
- }
-
- va_end(ap);
- for (i = 1; i < n; i += 2)
- free(iovec[i].iov_base);
-
- if (!fallback)
- return -error;
- }
-
- /* Fallback if journal logging is not available or didn't work. */
-
- va_start(ap, format);
- while (format) {
- va_list aq;
-
- if (error != 0)
- errno = error;
-
- va_copy(aq, ap);
- vsnprintf(buf, sizeof(buf), format, aq);
- va_end(aq);
-
- if (startswith(buf, "MESSAGE=")) {
- found = true;
- break;
- }
-
- VA_FORMAT_ADVANCE(format, ap);
-
- format = va_arg(ap, char *);
- }
- va_end(ap);
-
- if (!found)
- return -error;
-
- return log_dispatch(level, error, file, line, func, NULL, NULL, NULL, NULL, buf + 8);
-}
-
-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 -EINVAL;
-
- log_set_max_level(t);
- return 0;
-}
-
-static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
-
- /*
- * The systemd.log_xyz= settings are parsed by all tools, and
- * so is "debug".
- *
- * However, "quiet" is only parsed by PID 1, and only turns of
- * status output to /dev/console, but does not alter the log
- * level.
- */
-
- if (streq(key, "debug") && !value)
- log_set_max_level(LOG_DEBUG);
-
- else if (streq(key, "systemd.log_target") && value) {
-
- if (log_set_target_from_string(value) < 0)
- log_warning("Failed to parse log target '%s'. Ignoring.", value);
-
- } else if (streq(key, "systemd.log_level") && value) {
-
- if (log_set_max_level_from_string(value) < 0)
- log_warning("Failed to parse log level '%s'. Ignoring.", value);
-
- } else if (streq(key, "systemd.log_color") && value) {
-
- if (log_show_color_from_string(value) < 0)
- log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
-
- } else if (streq(key, "systemd.log_location") && value) {
-
- if (log_show_location_from_string(value) < 0)
- log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
- }
-
- return 0;
-}
-
-void log_parse_environment(void) {
- const char *e;
-
- if (get_ctty_devnr(0, NULL) < 0)
- /* Only try to read the command line in daemons.
- We assume that anything that has a controlling
- tty is user stuff. */
- (void) parse_proc_cmdline(parse_proc_cmdline_item, NULL, true);
-
- e = secure_getenv("SYSTEMD_LOG_TARGET");
- if (e && log_set_target_from_string(e) < 0)
- log_warning("Failed to parse log target '%s'. Ignoring.", e);
-
- e = secure_getenv("SYSTEMD_LOG_LEVEL");
- if (e && log_set_max_level_from_string(e) < 0)
- log_warning("Failed to parse log level '%s'. Ignoring.", e);
-
- e = secure_getenv("SYSTEMD_LOG_COLOR");
- if (e && log_show_color_from_string(e) < 0)
- log_warning("Failed to parse bool '%s'. Ignoring.", e);
-
- e = secure_getenv("SYSTEMD_LOG_LOCATION");
- if (e && log_show_location_from_string(e) < 0)
- log_warning("Failed to parse bool '%s'. Ignoring.", e);
-}
-
-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;
-}
-
-bool log_get_show_color(void) {
- return show_color;
-}
-
-void log_show_location(bool b) {
- show_location = b;
-}
-
-bool log_get_show_location(void) {
- return show_location;
-}
-
-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 ||
- log_target == LOG_TARGET_CONSOLE_PREFIXED)
- return true;
-
- return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
-}
-
-static const char *const log_target_table[_LOG_TARGET_MAX] = {
- [LOG_TARGET_CONSOLE] = "console",
- [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed",
- [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);
-
-void log_received_signal(int level, const struct signalfd_siginfo *si) {
- if (si->ssi_pid > 0) {
- _cleanup_free_ char *p = NULL;
-
- get_process_comm(si->ssi_pid, &p);
-
- log_full(level,
- "Received SIG%s from PID %"PRIu32" (%s).",
- signal_to_string(si->ssi_signo),
- si->ssi_pid, strna(p));
- } else
- log_full(level,
- "Received SIG%s.",
- signal_to_string(si->ssi_signo));
-
-}
-
-void log_set_upgrade_syslog_to_journal(bool b) {
- upgrade_syslog_to_journal = b;
-}
-
-int log_syntax_internal(
- const char *unit,
- int level,
- const char *config_file,
- unsigned config_line,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *format, ...) {
-
- PROTECT_ERRNO;
- char buffer[LINE_MAX];
- int r;
- va_list ap;
-
- if (error < 0)
- error = -error;
-
- if (_likely_(LOG_PRI(level) > log_max_level))
- return -error;
-
- if (log_target == LOG_TARGET_NULL)
- return -error;
-
- if (error != 0)
- errno = error;
-
- va_start(ap, format);
- vsnprintf(buffer, sizeof(buffer), format, ap);
- va_end(ap);
-
- if (unit)
- r = log_struct_internal(
- level, error,
- file, line, func,
- getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s", unit,
- LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
- "CONFIG_FILE=%s", config_file,
- "CONFIG_LINE=%u", config_line,
- LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),
- NULL);
- else
- r = log_struct_internal(
- level, error,
- file, line, func,
- LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
- "CONFIG_FILE=%s", config_file,
- "CONFIG_LINE=%u", config_line,
- LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),
- NULL);
-
- return r;
-}
diff --git a/src/basic/log.h b/src/basic/log.h
deleted file mode 100644
index 2afee20bb5..0000000000
--- a/src/basic/log.h
+++ /dev/null
@@ -1,253 +0,0 @@
-#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 <errno.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <sys/signalfd.h>
-#include <sys/socket.h>
-#include <syslog.h>
-
-#include "sd-id128.h"
-
-#include "macro.h"
-
-typedef enum LogTarget{
- LOG_TARGET_CONSOLE,
- LOG_TARGET_CONSOLE_PREFIXED,
- 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);
-bool log_get_show_color(void) _pure_;
-void log_show_location(bool b);
-bool log_get_show_location(void) _pure_;
-
-int log_show_color_from_string(const char *e);
-int log_show_location_from_string(const char *e);
-
-LogTarget log_get_target(void) _pure_;
-int log_get_max_level(void) _pure_;
-
-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);
-
-void log_parse_environment(void);
-
-int log_internal(
- int level,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *format, ...) _printf_(6,7);
-
-int log_internalv(
- int level,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *format,
- va_list ap) _printf_(6,0);
-
-int log_object_internal(
- int level,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *object_field,
- const char *object,
- const char *extra_field,
- const char *extra,
- const char *format, ...) _printf_(10,11);
-
-int log_object_internalv(
- int level,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *object_field,
- const char *object,
- const char *extra_field,
- const char *extra,
- const char *format,
- va_list ap) _printf_(9,0);
-
-int log_struct_internal(
- int level,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *format, ...) _printf_(6,0) _sentinel_;
-
-int log_oom_internal(
- const char *file,
- int line,
- const char *func);
-
-int log_format_iovec(
- struct iovec *iovec,
- unsigned iovec_len,
- unsigned *n,
- bool newline_separator,
- int error,
- const char *format,
- va_list ap);
-
-/* This modifies the buffer passed! */
-int log_dump_internal(
- int level,
- int error,
- const char *file,
- int line,
- const char *func,
- char *buffer);
-
-/* Logging for various assertions */
-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);
-
-void log_assert_failed_return(
- const char *text,
- const char *file,
- int line,
- const char *func);
-
-/* Logging with level */
-#define log_full_errno(level, error, ...) \
- ({ \
- int _level = (level), _e = (error); \
- (log_get_max_level() >= LOG_PRI(_level)) \
- ? log_internal(_level, _e, __FILE__, __LINE__, __func__, __VA_ARGS__) \
- : -abs(_e); \
- })
-
-#define log_full(level, ...) log_full_errno(level, 0, __VA_ARGS__)
-
-/* Normal logging */
-#define log_debug(...) log_full(LOG_DEBUG, __VA_ARGS__)
-#define log_info(...) log_full(LOG_INFO, __VA_ARGS__)
-#define log_notice(...) log_full(LOG_NOTICE, __VA_ARGS__)
-#define log_warning(...) log_full(LOG_WARNING, __VA_ARGS__)
-#define log_error(...) log_full(LOG_ERR, __VA_ARGS__)
-#define log_emergency(...) log_full(getpid() == 1 ? LOG_EMERG : LOG_ERR, __VA_ARGS__)
-
-/* Logging triggered by an errno-like error */
-#define log_debug_errno(error, ...) log_full_errno(LOG_DEBUG, error, __VA_ARGS__)
-#define log_info_errno(error, ...) log_full_errno(LOG_INFO, error, __VA_ARGS__)
-#define log_notice_errno(error, ...) log_full_errno(LOG_NOTICE, error, __VA_ARGS__)
-#define log_warning_errno(error, ...) log_full_errno(LOG_WARNING, error, __VA_ARGS__)
-#define log_error_errno(error, ...) log_full_errno(LOG_ERR, error, __VA_ARGS__)
-#define log_emergency_errno(error, ...) log_full_errno(getpid() == 1 ? LOG_EMERG : LOG_ERR, error, __VA_ARGS__)
-
-#ifdef LOG_TRACE
-# define log_trace(...) log_debug(__VA_ARGS__)
-#else
-# define log_trace(...) do {} while (0)
-#endif
-
-/* Structured logging */
-#define log_struct(level, ...) log_struct_internal(level, 0, __FILE__, __LINE__, __func__, __VA_ARGS__)
-#define log_struct_errno(level, error, ...) log_struct_internal(level, error, __FILE__, __LINE__, __func__, __VA_ARGS__)
-
-/* This modifies the buffer passed! */
-#define log_dump(level, buffer) log_dump_internal(level, 0, __FILE__, __LINE__, __func__, buffer)
-
-#define log_oom() log_oom_internal(__FILE__, __LINE__, __func__)
-
-bool log_on_console(void) _pure_;
-
-const char *log_target_to_string(LogTarget target) _const_;
-LogTarget log_target_from_string(const char *s) _pure_;
-
-/* Helpers to prepare various fields for structured logging */
-#define LOG_MESSAGE(fmt, ...) "MESSAGE=" fmt, ##__VA_ARGS__
-#define LOG_MESSAGE_ID(x) "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(x)
-
-void log_received_signal(int level, const struct signalfd_siginfo *si);
-
-void log_set_upgrade_syslog_to_journal(bool b);
-
-int log_syntax_internal(
- const char *unit,
- int level,
- const char *config_file,
- unsigned config_line,
- int error,
- const char *file,
- int line,
- const char *func,
- const char *format, ...) _printf_(9, 10);
-
-#define log_syntax(unit, level, config_file, config_line, error, ...) \
- ({ \
- int _level = (level), _e = (error); \
- (log_get_max_level() >= LOG_PRI(_level)) \
- ? log_syntax_internal(unit, _level, config_file, config_line, _e, __FILE__, __LINE__, __func__, __VA_ARGS__) \
- : -abs(_e); \
- })
-
-#define log_syntax_invalid_utf8(unit, level, config_file, config_line, rvalue) \
- ({ \
- int _level = (level); \
- if (log_get_max_level() >= LOG_PRI(_level)) { \
- _cleanup_free_ char *_p = NULL; \
- _p = utf8_escape_invalid(rvalue); \
- log_syntax_internal(unit, _level, config_file, config_line, 0, __FILE__, __LINE__, __func__, \
- "String is not UTF-8 clean, ignoring assignment: %s", strna(_p)); \
- } \
- })
diff --git a/src/basic/login-util.c b/src/basic/login-util.c
deleted file mode 100644
index 339e94f12d..0000000000
--- a/src/basic/login-util.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- 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 <string.h>
-
-#include "login-util.h"
-#include "string-util.h"
-
-bool session_id_valid(const char *id) {
-
- if (isempty(id))
- return false;
-
- return id[strspn(id, LETTERS DIGITS)] == '\0';
-}
diff --git a/src/basic/login-util.h b/src/basic/login-util.h
deleted file mode 100644
index b01ee25c88..0000000000
--- a/src/basic/login-util.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- 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 <unistd.h>
-
-bool session_id_valid(const char *id);
-
-static inline bool logind_running(void) {
- return access("/run/systemd/seats/", F_OK) >= 0;
-}
diff --git a/src/basic/macro.h b/src/basic/macro.h
deleted file mode 100644
index 6b2aeb933f..0000000000
--- a/src/basic/macro.h
+++ /dev/null
@@ -1,415 +0,0 @@
-#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 <inttypes.h>
-#include <stdbool.h>
-#include <sys/param.h>
-#include <sys/sysmacros.h>
-#include <sys/types.h>
-
-#define _printf_(a,b) __attribute__ ((format (printf, a, b)))
-#ifdef __clang__
-# define _alloc_(...)
-#else
-# define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__)))
-#endif
-#define _sentinel_ __attribute__ ((sentinel))
-#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 _alignas_(x) __attribute__((aligned(__alignof(x))))
-#define _cleanup_(x) __attribute__((cleanup(x)))
-
-/* Temporarily disable some warnings */
-#define DISABLE_WARNING_DECLARATION_AFTER_STATEMENT \
- _Pragma("GCC diagnostic push"); \
- _Pragma("GCC diagnostic ignored \"-Wdeclaration-after-statement\"")
-
-#define DISABLE_WARNING_FORMAT_NONLITERAL \
- _Pragma("GCC diagnostic push"); \
- _Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"")
-
-#define DISABLE_WARNING_MISSING_PROTOTYPES \
- _Pragma("GCC diagnostic push"); \
- _Pragma("GCC diagnostic ignored \"-Wmissing-prototypes\"")
-
-#define DISABLE_WARNING_NONNULL \
- _Pragma("GCC diagnostic push"); \
- _Pragma("GCC diagnostic ignored \"-Wnonnull\"")
-
-#define DISABLE_WARNING_SHADOW \
- _Pragma("GCC diagnostic push"); \
- _Pragma("GCC diagnostic ignored \"-Wshadow\"")
-
-#define DISABLE_WARNING_INCOMPATIBLE_POINTER_TYPES \
- _Pragma("GCC diagnostic push"); \
- _Pragma("GCC diagnostic ignored \"-Wincompatible-pointer-types\"")
-
-#define REENABLE_WARNING \
- _Pragma("GCC diagnostic pop")
-
-/* automake test harness */
-#define EXIT_TEST_SKIP 77
-
-#define XSTRINGIFY(x) #x
-#define STRINGIFY(x) XSTRINGIFY(x)
-
-#define XCONCATENATE(x, y) x ## y
-#define CONCATENATE(x, y) XCONCATENATE(x, y)
-
-#define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq))
-#define UNIQ __COUNTER__
-
-/* builtins */
-#if __SIZEOF_INT__ == 4
-#define BUILTIN_FFS_U32(x) __builtin_ffs(x);
-#elif __SIZEOF_LONG__ == 4
-#define BUILTIN_FFS_U32(x) __builtin_ffsl(x);
-#else
-#error "neither int nor long are four bytes long?!?"
-#endif
-
-/* Rounds up */
-
-#define ALIGN4(l) (((l) + 3) & ~3)
-#define ALIGN8(l) (((l) + 7) & ~7)
-
-#if __SIZEOF_POINTER__ == 8
-#define ALIGN(l) ALIGN8(l)
-#elif __SIZEOF_POINTER__ == 4
-#define ALIGN(l) ALIGN4(l)
-#else
-#error "Wut? Pointers are neither 4 nor 8 bytes long?"
-#endif
-
-#define ALIGN_PTR(p) ((void*) ALIGN((unsigned long) (p)))
-#define ALIGN4_PTR(p) ((void*) ALIGN4((unsigned long) (p)))
-#define ALIGN8_PTR(p) ((void*) ALIGN8((unsigned long) (p)))
-
-static inline size_t ALIGN_TO(size_t l, size_t ali) {
- return ((l + ali - 1) & ~(ali - 1));
-}
-
-#define ALIGN_TO_PTR(p, ali) ((void*) ALIGN_TO((unsigned long) (p), (ali)))
-
-/* align to next higher power-of-2 (except for: 0 => 0, overflow => 0) */
-static inline unsigned long ALIGN_POWER2(unsigned long u) {
- /* clz(0) is undefined */
- if (u == 1)
- return 1;
-
- /* left-shift overflow is undefined */
- if (__builtin_clzl(u - 1UL) < 1)
- return 0;
-
- return 1UL << (sizeof(u) * 8 - __builtin_clzl(u - 1UL));
-}
-
-#define ELEMENTSOF(x) \
- __extension__ (__builtin_choose_expr( \
- !__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \
- sizeof(x)/sizeof((x)[0]), \
- (void)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) __container_of(UNIQ, (ptr), type, member)
-#define __container_of(uniq, ptr, type, member) \
- __extension__ ({ \
- const typeof( ((type*)0)->member ) *UNIQ_T(A, uniq) = (ptr); \
- (type*)( (char *)UNIQ_T(A, uniq) - offsetof(type,member) ); \
- })
-
-#undef MAX
-#define MAX(a, b) __MAX(UNIQ, (a), UNIQ, (b))
-#define __MAX(aq, a, bq, b) \
- __extension__ ({ \
- const typeof(a) UNIQ_T(A, aq) = (a); \
- const typeof(b) UNIQ_T(B, bq) = (b); \
- UNIQ_T(A,aq) > UNIQ_T(B,bq) ? UNIQ_T(A,aq) : UNIQ_T(B,bq); \
- })
-
-/* evaluates to (void) if _A or _B are not constant or of different types */
-#define CONST_MAX(_A, _B) \
- __extension__ (__builtin_choose_expr( \
- __builtin_constant_p(_A) && \
- __builtin_constant_p(_B) && \
- __builtin_types_compatible_p(typeof(_A), typeof(_B)), \
- ((_A) > (_B)) ? (_A) : (_B), \
- (void)0))
-
-/* takes two types and returns the size of the larger one */
-#define MAXSIZE(A, B) (sizeof(union _packed_ { typeof(A) a; typeof(B) b; }))
-
-#define MAX3(x,y,z) \
- __extension__ ({ \
- const typeof(x) _c = MAX(x,y); \
- MAX(_c, z); \
- })
-
-#undef MIN
-#define MIN(a, b) __MIN(UNIQ, (a), UNIQ, (b))
-#define __MIN(aq, a, bq, b) \
- __extension__ ({ \
- const typeof(a) UNIQ_T(A, aq) = (a); \
- const typeof(b) UNIQ_T(B, bq) = (b); \
- UNIQ_T(A,aq) < UNIQ_T(B,bq) ? UNIQ_T(A,aq) : UNIQ_T(B,bq); \
- })
-
-#define MIN3(x,y,z) \
- __extension__ ({ \
- const typeof(x) _c = MIN(x,y); \
- MIN(_c, z); \
- })
-
-#define LESS_BY(a, b) __LESS_BY(UNIQ, (a), UNIQ, (b))
-#define __LESS_BY(aq, a, bq, b) \
- __extension__ ({ \
- const typeof(a) UNIQ_T(A, aq) = (a); \
- const typeof(b) UNIQ_T(B, bq) = (b); \
- UNIQ_T(A,aq) > UNIQ_T(B,bq) ? UNIQ_T(A,aq) - UNIQ_T(B,bq) : 0; \
- })
-
-#undef CLAMP
-#define CLAMP(x, low, high) __CLAMP(UNIQ, (x), UNIQ, (low), UNIQ, (high))
-#define __CLAMP(xq, x, lowq, low, highq, high) \
- __extension__ ({ \
- const typeof(x) UNIQ_T(X,xq) = (x); \
- const typeof(low) UNIQ_T(LOW,lowq) = (low); \
- const typeof(high) UNIQ_T(HIGH,highq) = (high); \
- UNIQ_T(X,xq) > UNIQ_T(HIGH,highq) ? \
- UNIQ_T(HIGH,highq) : \
- UNIQ_T(X,xq) < UNIQ_T(LOW,lowq) ? \
- UNIQ_T(LOW,lowq) : \
- UNIQ_T(X,xq); \
- })
-
-/* [(x + y - 1) / y] suffers from an integer overflow, even though the
- * computation should be possible in the given type. Therefore, we use
- * [x / y + !!(x % y)]. Note that on "Real CPUs" a division returns both the
- * quotient and the remainder, so both should be equally fast. */
-#define DIV_ROUND_UP(_x, _y) \
- __extension__ ({ \
- const typeof(_x) __x = (_x); \
- const typeof(_y) __y = (_y); \
- (__x / __y + !!(__x % __y)); \
- })
-
-#define assert_message_se(expr, message) \
- do { \
- if (_unlikely_(!(expr))) \
- log_assert_failed(message, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
- } while (false)
-
-#define assert_se(expr) assert_message_se(expr, #expr)
-
-/* We override the glibc assert() here. */
-#undef assert
-#ifdef NDEBUG
-#define assert(expr) do {} while (false)
-#else
-#define assert(expr) assert_message_se(expr, #expr)
-#endif
-
-#define assert_not_reached(t) \
- do { \
- log_assert_failed_unreachable(t, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
- } while (false)
-
-#if defined(static_assert)
-/* static_assert() is sometimes defined in a way that trips up
- * -Wdeclaration-after-statement, hence let's temporarily turn off
- * this warning around it. */
-#define assert_cc(expr) \
- DISABLE_WARNING_DECLARATION_AFTER_STATEMENT; \
- static_assert(expr, #expr); \
- REENABLE_WARNING
-#else
-#define assert_cc(expr) \
- DISABLE_WARNING_DECLARATION_AFTER_STATEMENT; \
- struct CONCATENATE(_assert_struct_, __COUNTER__) { \
- char x[(expr) ? 0 : -1]; \
- }; \
- REENABLE_WARNING
-#endif
-
-#define assert_log(expr, message) ((_likely_(expr)) \
- ? (true) \
- : (log_assert_failed_return(message, __FILE__, __LINE__, __PRETTY_FUNCTION__), false))
-
-#define assert_return(expr, r) \
- do { \
- if (!assert_log(expr, #expr)) \
- return (r); \
- } while (false)
-
-#define assert_return_errno(expr, r, err) \
- do { \
- if (!assert_log(expr, #expr)) { \
- errno = err; \
- return (r); \
- } \
- } while (false)
-
-#define PTR_TO_INT(p) ((int) ((intptr_t) (p)))
-#define INT_TO_PTR(u) ((void *) ((intptr_t) (u)))
-#define PTR_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
-#define UINT_TO_PTR(u) ((void *) ((uintptr_t) (u)))
-
-#define PTR_TO_LONG(p) ((long) ((intptr_t) (p)))
-#define LONG_TO_PTR(u) ((void *) ((intptr_t) (u)))
-#define PTR_TO_ULONG(p) ((unsigned long) ((uintptr_t) (p)))
-#define ULONG_TO_PTR(u) ((void *) ((uintptr_t) (u)))
-
-#define PTR_TO_INT32(p) ((int32_t) ((intptr_t) (p)))
-#define INT32_TO_PTR(u) ((void *) ((intptr_t) (u)))
-#define PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p)))
-#define UINT32_TO_PTR(u) ((void *) ((uintptr_t) (u)))
-
-#define PTR_TO_INT64(p) ((int64_t) ((intptr_t) (p)))
-#define INT64_TO_PTR(u) ((void *) ((intptr_t) (u)))
-#define PTR_TO_UINT64(p) ((uint64_t) ((uintptr_t) (p)))
-#define UINT64_TO_PTR(u) ((void *) ((uintptr_t) (u)))
-
-#define PTR_TO_SIZE(p) ((size_t) ((uintptr_t) (p)))
-#define SIZE_TO_PTR(u) ((void *) ((uintptr_t) (u)))
-
-#define CHAR_TO_STR(x) ((char[2]) { x, 0 })
-
-#define char_array_0(x) x[sizeof(x)-1] = 0;
-
-/* Returns the number of chars needed to format variables of the
- * specified type as a decimal string. Adds in extra space for a
- * negative '-' prefix (hence works correctly on signed
- * types). Includes space for the trailing NUL. */
-#define DECIMAL_STR_MAX(type) \
- (2+(sizeof(type) <= 1 ? 3 : \
- sizeof(type) <= 2 ? 5 : \
- sizeof(type) <= 4 ? 10 : \
- sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)])))
-
-#define DECIMAL_STR_WIDTH(x) \
- ({ \
- typeof(x) _x_ = (x); \
- unsigned ans = 1; \
- while (_x_ /= 10) \
- ans++; \
- ans; \
- })
-
-#define SET_FLAG(v, flag, b) \
- (v) = (b) ? ((v) | (flag)) : ((v) & ~(flag))
-
-#define CASE_F(X) case X:
-#define CASE_F_1(CASE, X) CASE_F(X)
-#define CASE_F_2(CASE, X, ...) CASE(X) CASE_F_1(CASE, __VA_ARGS__)
-#define CASE_F_3(CASE, X, ...) CASE(X) CASE_F_2(CASE, __VA_ARGS__)
-#define CASE_F_4(CASE, X, ...) CASE(X) CASE_F_3(CASE, __VA_ARGS__)
-#define CASE_F_5(CASE, X, ...) CASE(X) CASE_F_4(CASE, __VA_ARGS__)
-#define CASE_F_6(CASE, X, ...) CASE(X) CASE_F_5(CASE, __VA_ARGS__)
-#define CASE_F_7(CASE, X, ...) CASE(X) CASE_F_6(CASE, __VA_ARGS__)
-#define CASE_F_8(CASE, X, ...) CASE(X) CASE_F_7(CASE, __VA_ARGS__)
-#define CASE_F_9(CASE, X, ...) CASE(X) CASE_F_8(CASE, __VA_ARGS__)
-#define CASE_F_10(CASE, X, ...) CASE(X) CASE_F_9(CASE, __VA_ARGS__)
-#define CASE_F_11(CASE, X, ...) CASE(X) CASE_F_10(CASE, __VA_ARGS__)
-#define CASE_F_12(CASE, X, ...) CASE(X) CASE_F_11(CASE, __VA_ARGS__)
-#define CASE_F_13(CASE, X, ...) CASE(X) CASE_F_12(CASE, __VA_ARGS__)
-#define CASE_F_14(CASE, X, ...) CASE(X) CASE_F_13(CASE, __VA_ARGS__)
-#define CASE_F_15(CASE, X, ...) CASE(X) CASE_F_14(CASE, __VA_ARGS__)
-#define CASE_F_16(CASE, X, ...) CASE(X) CASE_F_15(CASE, __VA_ARGS__)
-#define CASE_F_17(CASE, X, ...) CASE(X) CASE_F_16(CASE, __VA_ARGS__)
-#define CASE_F_18(CASE, X, ...) CASE(X) CASE_F_17(CASE, __VA_ARGS__)
-#define CASE_F_19(CASE, X, ...) CASE(X) CASE_F_18(CASE, __VA_ARGS__)
-#define CASE_F_20(CASE, X, ...) CASE(X) CASE_F_19(CASE, __VA_ARGS__)
-
-#define GET_CASE_F(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,NAME,...) NAME
-#define FOR_EACH_MAKE_CASE(...) \
- GET_CASE_F(__VA_ARGS__,CASE_F_20,CASE_F_19,CASE_F_18,CASE_F_17,CASE_F_16,CASE_F_15,CASE_F_14,CASE_F_13,CASE_F_12,CASE_F_11, \
- CASE_F_10,CASE_F_9,CASE_F_8,CASE_F_7,CASE_F_6,CASE_F_5,CASE_F_4,CASE_F_3,CASE_F_2,CASE_F_1) \
- (CASE_F,__VA_ARGS__)
-
-#define IN_SET(x, ...) \
- ({ \
- bool _found = false; \
- /* If the build breaks in the line below, you need to extend the case macros */ \
- static _unused_ char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){__VA_ARGS__})/sizeof(int)]; \
- switch(x) { \
- FOR_EACH_MAKE_CASE(__VA_ARGS__) \
- _found = true; \
- break; \
- default: \
- break; \
- } \
- _found; \
- })
-
-#define SWAP_TWO(x, y) do { \
- typeof(x) _t = (x); \
- (x) = (y); \
- (y) = (_t); \
- } while (false)
-
-/* Define C11 thread_local attribute even on older gcc compiler
- * version */
-#ifndef thread_local
-/*
- * Don't break on glibc < 2.16 that doesn't define __STDC_NO_THREADS__
- * see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769
- */
-#if __STDC_VERSION__ >= 201112L && !(defined(__STDC_NO_THREADS__) || (defined(__GNU_LIBRARY__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16))
-#define thread_local _Thread_local
-#else
-#define thread_local __thread
-#endif
-#endif
-
-/* Define C11 noreturn without <stdnoreturn.h> and even on older gcc
- * compiler versions */
-#ifndef noreturn
-#if __STDC_VERSION__ >= 201112L
-#define noreturn _Noreturn
-#else
-#define noreturn __attribute__((noreturn))
-#endif
-#endif
-
-#define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \
- static inline void func##p(type *p) { \
- if (*p) \
- func(*p); \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
-
-#include "log.h"
diff --git a/src/basic/memfd-util.c b/src/basic/memfd-util.c
deleted file mode 100644
index 8c8cc78ebf..0000000000
--- a/src/basic/memfd-util.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 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 <fcntl.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#ifdef HAVE_LINUX_MEMFD_H
-#include <linux/memfd.h>
-#endif
-#include <stdio.h>
-#include <sys/mman.h>
-#include <sys/prctl.h>
-
-#include "alloc-util.h"
-#include "fd-util.h"
-#include "macro.h"
-#include "memfd-util.h"
-#include "missing.h"
-#include "string-util.h"
-#include "utf8.h"
-
-int memfd_new(const char *name) {
- _cleanup_free_ char *g = NULL;
- int fd;
-
- if (!name) {
- char pr[17] = {};
-
- /* If no name is specified we generate one. We include
- * a hint indicating our library implementation, and
- * add the thread name to it */
-
- assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
-
- if (isempty(pr))
- name = "sd";
- else {
- _cleanup_free_ char *e = NULL;
-
- e = utf8_escape_invalid(pr);
- if (!e)
- return -ENOMEM;
-
- g = strappend("sd-", e);
- if (!g)
- return -ENOMEM;
-
- name = g;
- }
- }
-
- fd = memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- return fd;
-}
-
-int memfd_map(int fd, uint64_t offset, size_t size, void **p) {
- void *q;
- int sealed;
-
- assert(fd >= 0);
- assert(size > 0);
- assert(p);
-
- sealed = memfd_get_sealed(fd);
- if (sealed < 0)
- return sealed;
-
- if (sealed)
- q = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, offset);
- else
- q = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
-
- if (q == MAP_FAILED)
- return -errno;
-
- *p = q;
- return 0;
-}
-
-int memfd_set_sealed(int fd) {
- int r;
-
- assert(fd >= 0);
-
- r = fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
- if (r < 0)
- return -errno;
-
- return 0;
-}
-
-int memfd_get_sealed(int fd) {
- int r;
-
- assert(fd >= 0);
-
- r = fcntl(fd, F_GET_SEALS);
- if (r < 0)
- return -errno;
-
- return r == (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
-}
-
-int memfd_get_size(int fd, uint64_t *sz) {
- struct stat stat;
- int r;
-
- assert(fd >= 0);
- assert(sz);
-
- r = fstat(fd, &stat);
- if (r < 0)
- return -errno;
-
- *sz = stat.st_size;
- return 0;
-}
-
-int memfd_set_size(int fd, uint64_t sz) {
- int r;
-
- assert(fd >= 0);
-
- r = ftruncate(fd, sz);
- if (r < 0)
- return -errno;
-
- return 0;
-}
-
-int memfd_new_and_map(const char *name, size_t sz, void **p) {
- _cleanup_close_ int fd = -1;
- int r;
-
- assert(sz > 0);
- assert(p);
-
- fd = memfd_new(name);
- if (fd < 0)
- return fd;
-
- r = memfd_set_size(fd, sz);
- if (r < 0)
- return r;
-
- r = memfd_map(fd, 0, sz, p);
- if (r < 0)
- return r;
-
- r = fd;
- fd = -1;
-
- return r;
-}
diff --git a/src/basic/memfd-util.h b/src/basic/memfd-util.h
deleted file mode 100644
index 46d4989e4c..0000000000
--- a/src/basic/memfd-util.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 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 <stddef.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-int memfd_new(const char *name);
-int memfd_new_and_map(const char *name, size_t sz, void **p);
-
-int memfd_map(int fd, uint64_t offset, size_t size, void **p);
-
-int memfd_set_sealed(int fd);
-int memfd_get_sealed(int fd);
-
-int memfd_get_size(int fd, uint64_t *sz);
-int memfd_set_size(int fd, uint64_t sz);
diff --git a/src/basic/mempool.c b/src/basic/mempool.c
deleted file mode 100644
index f95e2beb0f..0000000000
--- a/src/basic/mempool.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010-2014 Lennart Poettering
- Copyright 2014 Michal Schmidt
-
- 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 <stdint.h>
-#include <stdlib.h>
-
-#include "macro.h"
-#include "mempool.h"
-#include "util.h"
-
-struct pool {
- struct pool *next;
- unsigned n_tiles;
- unsigned n_used;
-};
-
-void* mempool_alloc_tile(struct mempool *mp) {
- unsigned i;
-
- /* When a tile is released we add it to the list and simply
- * place the next pointer at its offset 0. */
-
- assert(mp->tile_size >= sizeof(void*));
- assert(mp->at_least > 0);
-
- if (mp->freelist) {
- void *r;
-
- r = mp->freelist;
- mp->freelist = * (void**) mp->freelist;
- return r;
- }
-
- if (_unlikely_(!mp->first_pool) ||
- _unlikely_(mp->first_pool->n_used >= mp->first_pool->n_tiles)) {
- unsigned n;
- size_t size;
- struct pool *p;
-
- n = mp->first_pool ? mp->first_pool->n_tiles : 0;
- n = MAX(mp->at_least, n * 2);
- size = PAGE_ALIGN(ALIGN(sizeof(struct pool)) + n*mp->tile_size);
- n = (size - ALIGN(sizeof(struct pool))) / mp->tile_size;
-
- p = malloc(size);
- if (!p)
- return NULL;
-
- p->next = mp->first_pool;
- p->n_tiles = n;
- p->n_used = 0;
-
- mp->first_pool = p;
- }
-
- i = mp->first_pool->n_used++;
-
- return ((uint8_t*) mp->first_pool) + ALIGN(sizeof(struct pool)) + i*mp->tile_size;
-}
-
-void* mempool_alloc0_tile(struct mempool *mp) {
- void *p;
-
- p = mempool_alloc_tile(mp);
- if (p)
- memzero(p, mp->tile_size);
- return p;
-}
-
-void mempool_free_tile(struct mempool *mp, void *p) {
- * (void**) p = mp->freelist;
- mp->freelist = p;
-}
-
-#ifdef VALGRIND
-
-void mempool_drop(struct mempool *mp) {
- struct pool *p = mp->first_pool;
- while (p) {
- struct pool *n;
- n = p->next;
- free(p);
- p = n;
- }
-}
-
-#endif
diff --git a/src/basic/mempool.h b/src/basic/mempool.h
deleted file mode 100644
index 0618b8dd22..0000000000
--- a/src/basic/mempool.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011-2014 Lennart Poettering
- Copyright 2014 Michal Schmidt
-
- 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 <stddef.h>
-
-struct pool;
-
-struct mempool {
- struct pool *first_pool;
- void *freelist;
- size_t tile_size;
- unsigned at_least;
-};
-
-void* mempool_alloc_tile(struct mempool *mp);
-void* mempool_alloc0_tile(struct mempool *mp);
-void mempool_free_tile(struct mempool *mp, void *p);
-
-#define DEFINE_MEMPOOL(pool_name, tile_type, alloc_at_least) \
-static struct mempool pool_name = { \
- .tile_size = sizeof(tile_type), \
- .at_least = alloc_at_least, \
-}
-
-
-#ifdef VALGRIND
-void mempool_drop(struct mempool *mp);
-#endif
diff --git a/src/basic/missing.h b/src/basic/missing.h
deleted file mode 100644
index 4c013be608..0000000000
--- a/src/basic/missing.h
+++ /dev/null
@@ -1,1081 +0,0 @@
-#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 <errno.h>
-#include <fcntl.h>
-#include <linux/audit.h>
-#include <linux/capability.h>
-#include <linux/if_link.h>
-#include <linux/input.h>
-#include <linux/loop.h>
-#include <linux/neighbour.h>
-#include <linux/oom.h>
-#include <linux/rtnetlink.h>
-#include <net/ethernet.h>
-#include <stdlib.h>
-#include <sys/resource.h>
-#include <sys/syscall.h>
-#include <uchar.h>
-#include <unistd.h>
-
-#ifdef HAVE_AUDIT
-#include <libaudit.h>
-#endif
-
-#ifdef ARCH_MIPS
-#include <asm/sgidefs.h>
-#endif
-
-#ifdef HAVE_LINUX_BTRFS_H
-#include <linux/btrfs.h>
-#endif
-
-#include "macro.h"
-
-#ifndef RLIMIT_RTTIME
-#define RLIMIT_RTTIME 15
-#endif
-
-/* If RLIMIT_RTTIME is not defined, then we cannot use RLIMIT_NLIMITS as is */
-#define _RLIMIT_MAX (RLIMIT_RTTIME+1 > RLIMIT_NLIMITS ? RLIMIT_RTTIME+1 : RLIMIT_NLIMITS)
-
-#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 F_ADD_SEALS
-#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
-#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
-
-#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
-#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
-#define F_SEAL_GROW 0x0004 /* prevent file from growing */
-#define F_SEAL_WRITE 0x0008 /* prevent writes */
-#endif
-
-#ifndef F_OFD_GETLK
-#define F_OFD_GETLK 36
-#define F_OFD_SETLK 37
-#define F_OFD_SETLKW 38
-#endif
-
-#ifndef MFD_ALLOW_SEALING
-#define MFD_ALLOW_SEALING 0x0002U
-#endif
-
-#ifndef MFD_CLOEXEC
-#define MFD_CLOEXEC 0x0001U
-#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
-
-#ifndef SOL_NETLINK
-#define SOL_NETLINK 270
-#endif
-
-#ifndef NETLINK_LIST_MEMBERSHIPS
-#define NETLINK_LIST_MEMBERSHIPS 9
-#endif
-
-#ifndef SOL_SCTP
-#define SOL_SCTP 132
-#endif
-
-#ifndef GRND_NONBLOCK
-#define GRND_NONBLOCK 0x0001
-#endif
-
-#ifndef GRND_RANDOM
-#define GRND_RANDOM 0x0002
-#endif
-
-#ifndef BTRFS_IOCTL_MAGIC
-#define BTRFS_IOCTL_MAGIC 0x94
-#endif
-
-#ifndef BTRFS_PATH_NAME_MAX
-#define BTRFS_PATH_NAME_MAX 4087
-#endif
-
-#ifndef BTRFS_DEVICE_PATH_NAME_MAX
-#define BTRFS_DEVICE_PATH_NAME_MAX 1024
-#endif
-
-#ifndef BTRFS_FSID_SIZE
-#define BTRFS_FSID_SIZE 16
-#endif
-
-#ifndef BTRFS_UUID_SIZE
-#define BTRFS_UUID_SIZE 16
-#endif
-
-#ifndef BTRFS_SUBVOL_RDONLY
-#define BTRFS_SUBVOL_RDONLY (1ULL << 1)
-#endif
-
-#ifndef BTRFS_SUBVOL_NAME_MAX
-#define BTRFS_SUBVOL_NAME_MAX 4039
-#endif
-
-#ifndef BTRFS_INO_LOOKUP_PATH_MAX
-#define BTRFS_INO_LOOKUP_PATH_MAX 4080
-#endif
-
-#ifndef BTRFS_SEARCH_ARGS_BUFSIZE
-#define BTRFS_SEARCH_ARGS_BUFSIZE (4096 - sizeof(struct btrfs_ioctl_search_key))
-#endif
-
-#ifndef BTRFS_QGROUP_LEVEL_SHIFT
-#define BTRFS_QGROUP_LEVEL_SHIFT 48
-#endif
-
-#ifndef HAVE_LINUX_BTRFS_H
-struct btrfs_ioctl_vol_args {
- int64_t fd;
- char name[BTRFS_PATH_NAME_MAX + 1];
-};
-
-struct btrfs_qgroup_limit {
- __u64 flags;
- __u64 max_rfer;
- __u64 max_excl;
- __u64 rsv_rfer;
- __u64 rsv_excl;
-};
-
-struct btrfs_qgroup_inherit {
- __u64 flags;
- __u64 num_qgroups;
- __u64 num_ref_copies;
- __u64 num_excl_copies;
- struct btrfs_qgroup_limit lim;
- __u64 qgroups[0];
-};
-
-struct btrfs_ioctl_qgroup_limit_args {
- __u64 qgroupid;
- struct btrfs_qgroup_limit lim;
-};
-
-struct btrfs_ioctl_vol_args_v2 {
- __s64 fd;
- __u64 transid;
- __u64 flags;
- union {
- struct {
- __u64 size;
- struct btrfs_qgroup_inherit *qgroup_inherit;
- };
- __u64 unused[4];
- };
- char name[BTRFS_SUBVOL_NAME_MAX + 1];
-};
-
-struct btrfs_ioctl_dev_info_args {
- uint64_t devid; /* in/out */
- uint8_t uuid[BTRFS_UUID_SIZE]; /* in/out */
- uint64_t bytes_used; /* out */
- uint64_t total_bytes; /* out */
- uint64_t unused[379]; /* pad to 4k */
- char path[BTRFS_DEVICE_PATH_NAME_MAX]; /* out */
-};
-
-struct btrfs_ioctl_fs_info_args {
- uint64_t max_id; /* out */
- uint64_t num_devices; /* out */
- uint8_t fsid[BTRFS_FSID_SIZE]; /* out */
- uint64_t reserved[124]; /* pad to 1k */
-};
-
-struct btrfs_ioctl_ino_lookup_args {
- __u64 treeid;
- __u64 objectid;
- char name[BTRFS_INO_LOOKUP_PATH_MAX];
-};
-
-struct btrfs_ioctl_search_key {
- /* which root are we searching. 0 is the tree of tree roots */
- __u64 tree_id;
-
- /* keys returned will be >= min and <= max */
- __u64 min_objectid;
- __u64 max_objectid;
-
- /* keys returned will be >= min and <= max */
- __u64 min_offset;
- __u64 max_offset;
-
- /* max and min transids to search for */
- __u64 min_transid;
- __u64 max_transid;
-
- /* keys returned will be >= min and <= max */
- __u32 min_type;
- __u32 max_type;
-
- /*
- * how many items did userland ask for, and how many are we
- * returning
- */
- __u32 nr_items;
-
- /* align to 64 bits */
- __u32 unused;
-
- /* some extra for later */
- __u64 unused1;
- __u64 unused2;
- __u64 unused3;
- __u64 unused4;
-};
-
-struct btrfs_ioctl_search_header {
- __u64 transid;
- __u64 objectid;
- __u64 offset;
- __u32 type;
- __u32 len;
-};
-
-
-struct btrfs_ioctl_search_args {
- struct btrfs_ioctl_search_key key;
- char buf[BTRFS_SEARCH_ARGS_BUFSIZE];
-};
-
-struct btrfs_ioctl_clone_range_args {
- __s64 src_fd;
- __u64 src_offset, src_length;
- __u64 dest_offset;
-};
-
-#define BTRFS_QUOTA_CTL_ENABLE 1
-#define BTRFS_QUOTA_CTL_DISABLE 2
-#define BTRFS_QUOTA_CTL_RESCAN__NOTUSED 3
-struct btrfs_ioctl_quota_ctl_args {
- __u64 cmd;
- __u64 status;
-};
-#endif
-
-#ifndef BTRFS_IOC_DEFRAG
-#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \
- struct btrfs_ioctl_vol_args)
-#endif
-
-#ifndef BTRFS_IOC_RESIZE
-#define BTRFS_IOC_RESIZE _IOW(BTRFS_IOCTL_MAGIC, 3, \
- struct btrfs_ioctl_vol_args)
-#endif
-
-#ifndef BTRFS_IOC_CLONE
-#define BTRFS_IOC_CLONE _IOW(BTRFS_IOCTL_MAGIC, 9, int)
-#endif
-
-#ifndef BTRFS_IOC_CLONE_RANGE
-#define BTRFS_IOC_CLONE_RANGE _IOW(BTRFS_IOCTL_MAGIC, 13, \
- struct btrfs_ioctl_clone_range_args)
-#endif
-
-#ifndef BTRFS_IOC_SUBVOL_CREATE
-#define BTRFS_IOC_SUBVOL_CREATE _IOW(BTRFS_IOCTL_MAGIC, 14, \
- struct btrfs_ioctl_vol_args)
-#endif
-
-#ifndef BTRFS_IOC_SNAP_DESTROY
-#define BTRFS_IOC_SNAP_DESTROY _IOW(BTRFS_IOCTL_MAGIC, 15, \
- struct btrfs_ioctl_vol_args)
-#endif
-
-#ifndef BTRFS_IOC_TREE_SEARCH
-#define BTRFS_IOC_TREE_SEARCH _IOWR(BTRFS_IOCTL_MAGIC, 17, \
- struct btrfs_ioctl_search_args)
-#endif
-
-#ifndef BTRFS_IOC_INO_LOOKUP
-#define BTRFS_IOC_INO_LOOKUP _IOWR(BTRFS_IOCTL_MAGIC, 18, \
- struct btrfs_ioctl_ino_lookup_args)
-#endif
-
-#ifndef BTRFS_IOC_SNAP_CREATE_V2
-#define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \
- struct btrfs_ioctl_vol_args_v2)
-#endif
-
-#ifndef BTRFS_IOC_SUBVOL_GETFLAGS
-#define BTRFS_IOC_SUBVOL_GETFLAGS _IOR(BTRFS_IOCTL_MAGIC, 25, __u64)
-#endif
-
-#ifndef BTRFS_IOC_SUBVOL_SETFLAGS
-#define BTRFS_IOC_SUBVOL_SETFLAGS _IOW(BTRFS_IOCTL_MAGIC, 26, __u64)
-#endif
-
-#ifndef BTRFS_IOC_DEV_INFO
-#define BTRFS_IOC_DEV_INFO _IOWR(BTRFS_IOCTL_MAGIC, 30, \
- struct btrfs_ioctl_dev_info_args)
-#endif
-
-#ifndef BTRFS_IOC_FS_INFO
-#define BTRFS_IOC_FS_INFO _IOR(BTRFS_IOCTL_MAGIC, 31, \
- struct btrfs_ioctl_fs_info_args)
-#endif
-
-#ifndef BTRFS_IOC_DEVICES_READY
-#define BTRFS_IOC_DEVICES_READY _IOR(BTRFS_IOCTL_MAGIC, 39, \
- struct btrfs_ioctl_vol_args)
-#endif
-
-#ifndef BTRFS_IOC_QUOTA_CTL
-#define BTRFS_IOC_QUOTA_CTL _IOWR(BTRFS_IOCTL_MAGIC, 40, \
- struct btrfs_ioctl_quota_ctl_args)
-#endif
-
-#ifndef BTRFS_IOC_QGROUP_LIMIT
-#define BTRFS_IOC_QGROUP_LIMIT _IOR(BTRFS_IOCTL_MAGIC, 43, \
- struct btrfs_ioctl_qgroup_limit_args)
-#endif
-
-#ifndef BTRFS_IOC_QUOTA_RESCAN_WAIT
-#define BTRFS_IOC_QUOTA_RESCAN_WAIT _IO(BTRFS_IOCTL_MAGIC, 46)
-#endif
-
-#ifndef BTRFS_FIRST_FREE_OBJECTID
-#define BTRFS_FIRST_FREE_OBJECTID 256
-#endif
-
-#ifndef BTRFS_LAST_FREE_OBJECTID
-#define BTRFS_LAST_FREE_OBJECTID -256ULL
-#endif
-
-#ifndef BTRFS_ROOT_TREE_OBJECTID
-#define BTRFS_ROOT_TREE_OBJECTID 1
-#endif
-
-#ifndef BTRFS_QUOTA_TREE_OBJECTID
-#define BTRFS_QUOTA_TREE_OBJECTID 8ULL
-#endif
-
-#ifndef BTRFS_ROOT_ITEM_KEY
-#define BTRFS_ROOT_ITEM_KEY 132
-#endif
-
-#ifndef BTRFS_QGROUP_STATUS_KEY
-#define BTRFS_QGROUP_STATUS_KEY 240
-#endif
-
-#ifndef BTRFS_QGROUP_INFO_KEY
-#define BTRFS_QGROUP_INFO_KEY 242
-#endif
-
-#ifndef BTRFS_QGROUP_LIMIT_KEY
-#define BTRFS_QGROUP_LIMIT_KEY 244
-#endif
-
-#ifndef BTRFS_QGROUP_RELATION_KEY
-#define BTRFS_QGROUP_RELATION_KEY 246
-#endif
-
-#ifndef BTRFS_ROOT_BACKREF_KEY
-#define BTRFS_ROOT_BACKREF_KEY 144
-#endif
-
-#ifndef BTRFS_SUPER_MAGIC
-#define BTRFS_SUPER_MAGIC 0x9123683E
-#endif
-
-#ifndef CGROUP_SUPER_MAGIC
-#define CGROUP_SUPER_MAGIC 0x27e0eb
-#endif
-
-#ifndef CGROUP2_SUPER_MAGIC
-#define CGROUP2_SUPER_MAGIC 0x63677270
-#endif
-
-#ifndef CLONE_NEWCGROUP
-#define CLONE_NEWCGROUP 0x02000000
-#endif
-
-#ifndef TMPFS_MAGIC
-#define TMPFS_MAGIC 0x01021994
-#endif
-
-#ifndef MQUEUE_MAGIC
-#define MQUEUE_MAGIC 0x19800202
-#endif
-
-#ifndef SECURITYFS_MAGIC
-#define SECURITYFS_MAGIC 0x73636673
-#endif
-
-#ifndef TRACEFS_MAGIC
-#define TRACEFS_MAGIC 0x74726163
-#endif
-
-#ifndef BPF_FS_MAGIC
-#define BPF_FS_MAGIC 0xcafe4a11
-#endif
-
-#ifndef MS_MOVE
-#define MS_MOVE 8192
-#endif
-
-#ifndef MS_REC
-#define MS_REC 16384
-#endif
-
-#ifndef MS_PRIVATE
-#define MS_PRIVATE (1<<18)
-#endif
-
-#ifndef MS_REC
-#define MS_REC (1<<19)
-#endif
-
-#ifndef MS_SHARED
-#define MS_SHARED (1<<20)
-#endif
-
-#ifndef MS_RELATIME
-#define MS_RELATIME (1<<21)
-#endif
-
-#ifndef MS_KERNMOUNT
-#define MS_KERNMOUNT (1<<22)
-#endif
-
-#ifndef MS_I_VERSION
-#define MS_I_VERSION (1<<23)
-#endif
-
-#ifndef MS_STRICTATIME
-#define MS_STRICTATIME (1<<24)
-#endif
-
-#ifndef MS_LAZYTIME
-#define MS_LAZYTIME (1<<25)
-#endif
-
-#ifndef SCM_SECURITY
-#define SCM_SECURITY 0x03
-#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
-
-#ifndef HAVE_SECURE_GETENV
-# ifdef HAVE___SECURE_GETENV
-# define secure_getenv __secure_getenv
-# else
-# error "neither secure_getenv nor __secure_getenv are available"
-# endif
-#endif
-
-#ifndef CIFS_MAGIC_NUMBER
-# define CIFS_MAGIC_NUMBER 0xFF534D42
-#endif
-
-#ifndef TFD_TIMER_CANCEL_ON_SET
-# define TFD_TIMER_CANCEL_ON_SET (1 << 1)
-#endif
-
-#ifndef SO_REUSEPORT
-# define SO_REUSEPORT 15
-#endif
-
-#ifndef EVIOCREVOKE
-# define EVIOCREVOKE _IOW('E', 0x91, int)
-#endif
-
-#ifndef DRM_IOCTL_SET_MASTER
-# define DRM_IOCTL_SET_MASTER _IO('d', 0x1e)
-#endif
-
-#ifndef DRM_IOCTL_DROP_MASTER
-# define DRM_IOCTL_DROP_MASTER _IO('d', 0x1f)
-#endif
-
-/* The precise definition of __O_TMPFILE is arch specific; use the
- * values defined by the kernel (note: some are hexa, some are octal,
- * duplicated as-is from the kernel definitions):
- * - alpha, parisc, sparc: each has a specific value;
- * - others: they use the "generic" value.
- */
-
-#ifndef __O_TMPFILE
-#if defined(__alpha__)
-#define __O_TMPFILE 0100000000
-#elif defined(__parisc__) || defined(__hppa__)
-#define __O_TMPFILE 0400000000
-#elif defined(__sparc__) || defined(__sparc64__)
-#define __O_TMPFILE 0x2000000
-#else
-#define __O_TMPFILE 020000000
-#endif
-
-/* a horrid kludge trying to make sure that this will fail on old kernels */
-#ifndef O_TMPFILE
-#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
-#endif
-
-#endif
-
-#if !HAVE_DECL_LO_FLAGS_PARTSCAN
-#define LO_FLAGS_PARTSCAN 8
-#endif
-
-#ifndef LOOP_CTL_REMOVE
-#define LOOP_CTL_REMOVE 0x4C81
-#endif
-
-#ifndef LOOP_CTL_GET_FREE
-#define LOOP_CTL_GET_FREE 0x4C82
-#endif
-
-#if !HAVE_DECL_IFLA_INET6_ADDR_GEN_MODE
-#define IFLA_INET6_UNSPEC 0
-#define IFLA_INET6_FLAGS 1
-#define IFLA_INET6_CONF 2
-#define IFLA_INET6_STATS 3
-#define IFLA_INET6_MCAST 4
-#define IFLA_INET6_CACHEINFO 5
-#define IFLA_INET6_ICMP6STATS 6
-#define IFLA_INET6_TOKEN 7
-#define IFLA_INET6_ADDR_GEN_MODE 8
-#define __IFLA_INET6_MAX 9
-
-#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1)
-
-#define IN6_ADDR_GEN_MODE_EUI64 0
-#define IN6_ADDR_GEN_MODE_NONE 1
-#endif
-
-#if !HAVE_DECL_IN6_ADDR_GEN_MODE_STABLE_PRIVACY
-#define IN6_ADDR_GEN_MODE_STABLE_PRIVACY 2
-#endif
-
-#if !HAVE_DECL_IFLA_MACVLAN_FLAGS
-#define IFLA_MACVLAN_UNSPEC 0
-#define IFLA_MACVLAN_MODE 1
-#define IFLA_MACVLAN_FLAGS 2
-#define __IFLA_MACVLAN_MAX 3
-
-#define IFLA_MACVLAN_MAX (__IFLA_MACVLAN_MAX - 1)
-#endif
-
-#if !HAVE_DECL_IFLA_IPVLAN_MODE
-#define IFLA_IPVLAN_UNSPEC 0
-#define IFLA_IPVLAN_MODE 1
-#define __IFLA_IPVLAN_MAX 2
-
-#define IFLA_IPVLAN_MAX (__IFLA_IPVLAN_MAX - 1)
-
-#define IPVLAN_MODE_L2 0
-#define IPVLAN_MODE_L3 1
-#define IPVLAN_MAX 2
-#endif
-
-#if !HAVE_DECL_IFLA_VTI_REMOTE
-#define IFLA_VTI_UNSPEC 0
-#define IFLA_VTI_LINK 1
-#define IFLA_VTI_IKEY 2
-#define IFLA_VTI_OKEY 3
-#define IFLA_VTI_LOCAL 4
-#define IFLA_VTI_REMOTE 5
-#define __IFLA_VTI_MAX 6
-
-#define IFLA_VTI_MAX (__IFLA_VTI_MAX - 1)
-#endif
-
-#if !HAVE_DECL_IFLA_PHYS_PORT_ID
-#define IFLA_EXT_MASK 29
-#undef IFLA_PROMISCUITY
-#define IFLA_PROMISCUITY 30
-#define IFLA_NUM_TX_QUEUES 31
-#define IFLA_NUM_RX_QUEUES 32
-#define IFLA_CARRIER 33
-#define IFLA_PHYS_PORT_ID 34
-#define __IFLA_MAX 35
-
-#define IFLA_MAX (__IFLA_MAX - 1)
-#endif
-
-#if !HAVE_DECL_IFLA_BOND_AD_INFO
-#define IFLA_BOND_UNSPEC 0
-#define IFLA_BOND_MODE 1
-#define IFLA_BOND_ACTIVE_SLAVE 2
-#define IFLA_BOND_MIIMON 3
-#define IFLA_BOND_UPDELAY 4
-#define IFLA_BOND_DOWNDELAY 5
-#define IFLA_BOND_USE_CARRIER 6
-#define IFLA_BOND_ARP_INTERVAL 7
-#define IFLA_BOND_ARP_IP_TARGET 8
-#define IFLA_BOND_ARP_VALIDATE 9
-#define IFLA_BOND_ARP_ALL_TARGETS 10
-#define IFLA_BOND_PRIMARY 11
-#define IFLA_BOND_PRIMARY_RESELECT 12
-#define IFLA_BOND_FAIL_OVER_MAC 13
-#define IFLA_BOND_XMIT_HASH_POLICY 14
-#define IFLA_BOND_RESEND_IGMP 15
-#define IFLA_BOND_NUM_PEER_NOTIF 16
-#define IFLA_BOND_ALL_SLAVES_ACTIVE 17
-#define IFLA_BOND_MIN_LINKS 18
-#define IFLA_BOND_LP_INTERVAL 19
-#define IFLA_BOND_PACKETS_PER_SLAVE 20
-#define IFLA_BOND_AD_LACP_RATE 21
-#define IFLA_BOND_AD_SELECT 22
-#define IFLA_BOND_AD_INFO 23
-#define __IFLA_BOND_MAX 24
-
-#define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1)
-#endif
-
-#if !HAVE_DECL_IFLA_VLAN_PROTOCOL
-#define IFLA_VLAN_UNSPEC 0
-#define IFLA_VLAN_ID 1
-#define IFLA_VLAN_FLAGS 2
-#define IFLA_VLAN_EGRESS_QOS 3
-#define IFLA_VLAN_INGRESS_QOS 4
-#define IFLA_VLAN_PROTOCOL 5
-#define __IFLA_VLAN_MAX 6
-
-#define IFLA_VLAN_MAX (__IFLA_VLAN_MAX - 1)
-#endif
-
-#if !HAVE_DECL_IFLA_VXLAN_REMCSUM_NOPARTIAL
-#define IFLA_VXLAN_UNSPEC 0
-#define IFLA_VXLAN_ID 1
-#define IFLA_VXLAN_GROUP 2
-#define IFLA_VXLAN_LINK 3
-#define IFLA_VXLAN_LOCAL 4
-#define IFLA_VXLAN_TTL 5
-#define IFLA_VXLAN_TOS 6
-#define IFLA_VXLAN_LEARNING 7
-#define IFLA_VXLAN_AGEING 8
-#define IFLA_VXLAN_LIMIT 9
-#define IFLA_VXLAN_PORT_RANGE 10
-#define IFLA_VXLAN_PROXY 11
-#define IFLA_VXLAN_RSC 12
-#define IFLA_VXLAN_L2MISS 13
-#define IFLA_VXLAN_L3MISS 14
-#define IFLA_VXLAN_PORT 15
-#define IFLA_VXLAN_GROUP6 16
-#define IFLA_VXLAN_LOCAL6 17
-#define IFLA_VXLAN_UDP_CSUM 18
-#define IFLA_VXLAN_UDP_ZERO_CSUM6_TX 19
-#define IFLA_VXLAN_UDP_ZERO_CSUM6_RX 20
-#define IFLA_VXLAN_REMCSUM_TX 21
-#define IFLA_VXLAN_REMCSUM_RX 22
-#define IFLA_VXLAN_GBP 23
-#define IFLA_VXLAN_REMCSUM_NOPARTIAL 24
-#define __IFLA_VXLAN_MAX 25
-
-#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
-#endif
-
-#if !HAVE_DECL_IFLA_IPTUN_ENCAP_DPORT
-#define IFLA_IPTUN_UNSPEC 0
-#define IFLA_IPTUN_LINK 1
-#define IFLA_IPTUN_LOCAL 2
-#define IFLA_IPTUN_REMOTE 3
-#define IFLA_IPTUN_TTL 4
-#define IFLA_IPTUN_TOS 5
-#define IFLA_IPTUN_ENCAP_LIMIT 6
-#define IFLA_IPTUN_FLOWINFO 7
-#define IFLA_IPTUN_FLAGS 8
-#define IFLA_IPTUN_PROTO 9
-#define IFLA_IPTUN_PMTUDISC 10
-#define IFLA_IPTUN_6RD_PREFIX 11
-#define IFLA_IPTUN_6RD_RELAY_PREFIX 12
-#define IFLA_IPTUN_6RD_PREFIXLEN 13
-#define IFLA_IPTUN_6RD_RELAY_PREFIXLEN 14
-#define IFLA_IPTUN_ENCAP_TYPE 15
-#define IFLA_IPTUN_ENCAP_FLAGS 16
-#define IFLA_IPTUN_ENCAP_SPORT 17
-#define IFLA_IPTUN_ENCAP_DPORT 18
-
-#define __IFLA_IPTUN_MAX 19
-
-#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
-#endif
-
-#if !HAVE_DECL_IFLA_GRE_ENCAP_DPORT
-#define IFLA_GRE_UNSPEC 0
-#define IFLA_GRE_LINK 1
-#define IFLA_GRE_IFLAGS 2
-#define IFLA_GRE_OFLAGS 3
-#define IFLA_GRE_IKEY 4
-#define IFLA_GRE_OKEY 5
-#define IFLA_GRE_LOCAL 6
-#define IFLA_GRE_REMOTE 7
-#define IFLA_GRE_TTL 8
-#define IFLA_GRE_TOS 9
-#define IFLA_GRE_PMTUDISC 10
-#define IFLA_GRE_ENCAP_LIMIT 11
-#define IFLA_GRE_FLOWINFO 12
-#define IFLA_GRE_FLAGS 13
-#define IFLA_GRE_ENCAP_TYPE 14
-#define IFLA_GRE_ENCAP_FLAGS 15
-#define IFLA_GRE_ENCAP_SPORT 16
-#define IFLA_GRE_ENCAP_DPORT 17
-
-#define __IFLA_GRE_MAX 18
-
-#define IFLA_GRE_MAX (__IFLA_GRE_MAX - 1)
-#endif
-
-#if !HAVE_DECL_IFLA_BRIDGE_VLAN_INFO
-#define IFLA_BRIDGE_FLAGS 0
-#define IFLA_BRIDGE_MODE 1
-#define IFLA_BRIDGE_VLAN_INFO 2
-#define __IFLA_BRIDGE_MAX 3
-
-#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1)
-#endif
-
-#ifndef BRIDGE_VLAN_INFO_RANGE_BEGIN
-#define BRIDGE_VLAN_INFO_RANGE_BEGIN (1<<3) /* VLAN is start of vlan range */
-#endif
-
-#ifndef BRIDGE_VLAN_INFO_RANGE_END
-#define BRIDGE_VLAN_INFO_RANGE_END (1<<4) /* VLAN is end of vlan range */
-#endif
-
-#if !HAVE_DECL_IFLA_BR_VLAN_DEFAULT_PVID
-#define IFLA_BR_UNSPEC 0
-#define IFLA_BR_FORWARD_DELAY 1
-#define IFLA_BR_HELLO_TIME 2
-#define IFLA_BR_MAX_AGE 3
-#define IFLA_BR_AGEING_TIME 4
-#define IFLA_BR_STP_STATE 5
-#define IFLA_BR_PRIORITY 6
-#define IFLA_BR_VLAN_FILTERING 7
-#define IFLA_BR_VLAN_PROTOCOL 8
-#define IFLA_BR_GROUP_FWD_MASK 9
-#define IFLA_BR_ROOT_ID 10
-#define IFLA_BR_BRIDGE_ID 11
-#define IFLA_BR_ROOT_PORT 12
-#define IFLA_BR_ROOT_PATH_COST 13
-#define IFLA_BR_TOPOLOGY_CHANGE 14
-#define IFLA_BR_TOPOLOGY_CHANGE_DETECTED 15
-#define IFLA_BR_HELLO_TIMER 16
-#define IFLA_BR_TCN_TIMER 17
-#define IFLA_BR_TOPOLOGY_CHANGE_TIMER 18
-#define IFLA_BR_GC_TIMER 19
-#define IFLA_BR_GROUP_ADDR 20
-#define IFLA_BR_FDB_FLUSH 21
-#define IFLA_BR_MCAST_ROUTER 22
-#define IFLA_BR_MCAST_SNOOPING 23
-#define IFLA_BR_MCAST_QUERY_USE_IFADDR 24
-#define IFLA_BR_MCAST_QUERIER 25
-#define IFLA_BR_MCAST_HASH_ELASTICITY 26
-#define IFLA_BR_MCAST_HASH_MAX 27
-#define IFLA_BR_MCAST_LAST_MEMBER_CNT 28
-#define IFLA_BR_MCAST_STARTUP_QUERY_CNT 29
-#define IFLA_BR_MCAST_LAST_MEMBER_INTVL 30
-#define IFLA_BR_MCAST_MEMBERSHIP_INTVL 31
-#define IFLA_BR_MCAST_QUERIER_INTVL 32
-#define IFLA_BR_MCAST_QUERY_INTVL 33
-#define IFLA_BR_MCAST_QUERY_RESPONSE_INTVL 34
-#define IFLA_BR_MCAST_STARTUP_QUERY_INTVL 35
-#define IFLA_BR_NF_CALL_IPTABLES 36
-#define IFLA_BR_NF_CALL_IP6TABLES 37
-#define IFLA_BR_NF_CALL_ARPTABLES 38
-#define IFLA_BR_VLAN_DEFAULT_PVID 39
-#define __IFLA_BR_MAX 40
-
-#define IFLA_BR_MAX (__IFLA_BR_MAX - 1)
-#endif
-
-#if !HAVE_DECL_IFLA_BRPORT_LEARNING_SYNC
-#define IFLA_BRPORT_UNSPEC 0
-#define IFLA_BRPORT_STATE 1
-#define IFLA_BRPORT_PRIORITY 2
-#define IFLA_BRPORT_COST 3
-#define IFLA_BRPORT_MODE 4
-#define IFLA_BRPORT_GUARD 5
-#define IFLA_BRPORT_PROTECT 6
-#define IFLA_BRPORT_FAST_LEAVE 7
-#define IFLA_BRPORT_LEARNING 8
-#define IFLA_BRPORT_UNICAST_FLOOD 9
-#define IFLA_BRPORT_LEARNING_SYNC 11
-#define __IFLA_BRPORT_MAX 12
-
-#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
-#endif
-
-#if !HAVE_DECL_IFLA_BRPORT_PROXYARP
-#define IFLA_BRPORT_PROXYARP 10
-#endif
-
-#if !HAVE_DECL_IFLA_VRF_TABLE
-#define IFLA_VRF_TABLE 1
-#endif
-
-#if !HAVE_DECL_NDA_IFINDEX
-#define NDA_UNSPEC 0
-#define NDA_DST 1
-#define NDA_LLADDR 2
-#define NDA_CACHEINFO 3
-#define NDA_PROBES 4
-#define NDA_VLAN 5
-#define NDA_PORT 6
-#define NDA_VNI 7
-#define NDA_IFINDEX 8
-#define __NDA_MAX 9
-
-#define NDA_MAX (__NDA_MAX - 1)
-#endif
-
-#ifndef RTA_PREF
-#define RTA_PREF 20
-#endif
-
-#ifndef IPV6_UNICAST_IF
-#define IPV6_UNICAST_IF 76
-#endif
-
-#ifndef IPV6_MIN_MTU
-#define IPV6_MIN_MTU 1280
-#endif
-
-#ifndef IFF_MULTI_QUEUE
-#define IFF_MULTI_QUEUE 0x100
-#endif
-
-#ifndef IFF_LOWER_UP
-#define IFF_LOWER_UP 0x10000
-#endif
-
-#ifndef IFF_DORMANT
-#define IFF_DORMANT 0x20000
-#endif
-
-#ifndef BOND_XMIT_POLICY_ENCAP23
-#define BOND_XMIT_POLICY_ENCAP23 3
-#endif
-
-#ifndef BOND_XMIT_POLICY_ENCAP34
-#define BOND_XMIT_POLICY_ENCAP34 4
-#endif
-
-#ifndef NET_ADDR_RANDOM
-# define NET_ADDR_RANDOM 1
-#endif
-
-#ifndef NET_NAME_UNKNOWN
-# define NET_NAME_UNKNOWN 0
-#endif
-
-#ifndef NET_NAME_ENUM
-# define NET_NAME_ENUM 1
-#endif
-
-#ifndef NET_NAME_PREDICTABLE
-# define NET_NAME_PREDICTABLE 2
-#endif
-
-#ifndef NET_NAME_USER
-# define NET_NAME_USER 3
-#endif
-
-#ifndef NET_NAME_RENAMED
-# define NET_NAME_RENAMED 4
-#endif
-
-#ifndef BPF_XOR
-# define BPF_XOR 0xa0
-#endif
-
-/* Note that LOOPBACK_IFINDEX is currently not exported by the
- * kernel/glibc, but hardcoded internally by the kernel. However, as
- * it is exported to userspace indirectly via rtnetlink and the
- * ioctls, and made use of widely we define it here too, in a way that
- * is compatible with the kernel's internal definition. */
-#ifndef LOOPBACK_IFINDEX
-#define LOOPBACK_IFINDEX 1
-#endif
-
-#if !HAVE_DECL_IFA_FLAGS
-#define IFA_FLAGS 8
-#endif
-
-#ifndef IFA_F_MANAGETEMPADDR
-#define IFA_F_MANAGETEMPADDR 0x100
-#endif
-
-#ifndef IFA_F_NOPREFIXROUTE
-#define IFA_F_NOPREFIXROUTE 0x200
-#endif
-
-#ifndef MAX_AUDIT_MESSAGE_LENGTH
-#define MAX_AUDIT_MESSAGE_LENGTH 8970
-#endif
-
-#ifndef AUDIT_NLGRP_MAX
-#define AUDIT_NLGRP_READLOG 1
-#endif
-
-#ifndef CAP_MAC_OVERRIDE
-#define CAP_MAC_OVERRIDE 32
-#endif
-
-#ifndef CAP_MAC_ADMIN
-#define CAP_MAC_ADMIN 33
-#endif
-
-#ifndef CAP_SYSLOG
-#define CAP_SYSLOG 34
-#endif
-
-#ifndef CAP_WAKE_ALARM
-#define CAP_WAKE_ALARM 35
-#endif
-
-#ifndef CAP_BLOCK_SUSPEND
-#define CAP_BLOCK_SUSPEND 36
-#endif
-
-#ifndef CAP_AUDIT_READ
-#define CAP_AUDIT_READ 37
-#endif
-
-#ifndef RENAME_NOREPLACE
-#define RENAME_NOREPLACE (1 << 0)
-#endif
-
-#ifndef KCMP_FILE
-#define KCMP_FILE 0
-#endif
-
-#ifndef INPUT_PROP_POINTING_STICK
-#define INPUT_PROP_POINTING_STICK 0x05
-#endif
-
-#ifndef INPUT_PROP_ACCELEROMETER
-#define INPUT_PROP_ACCELEROMETER 0x06
-#endif
-
-#ifndef HAVE_KEY_SERIAL_T
-typedef int32_t key_serial_t;
-#endif
-
-#ifndef KEYCTL_READ
-#define KEYCTL_READ 11
-#endif
-
-#ifndef KEYCTL_SET_TIMEOUT
-#define KEYCTL_SET_TIMEOUT 15
-#endif
-
-#ifndef KEY_SPEC_USER_KEYRING
-#define KEY_SPEC_USER_KEYRING -4
-#endif
-
-#ifndef PR_CAP_AMBIENT
-#define PR_CAP_AMBIENT 47
-#endif
-
-#ifndef PR_CAP_AMBIENT_IS_SET
-#define PR_CAP_AMBIENT_IS_SET 1
-#endif
-
-#ifndef PR_CAP_AMBIENT_RAISE
-#define PR_CAP_AMBIENT_RAISE 2
-#endif
-
-#ifndef PR_CAP_AMBIENT_CLEAR_ALL
-#define PR_CAP_AMBIENT_CLEAR_ALL 4
-#endif
-
-/* The following two defines are actually available in the kernel headers for longer, but we define them here anyway,
- * since that makes it easier to use them in conjunction with the glibc net/if.h header which conflicts with
- * linux/if.h. */
-#ifndef IF_OPER_UNKNOWN
-#define IF_OPER_UNKNOWN 0
-#endif
-
-#ifndef IF_OPER_UP
-#define IF_OPER_UP 6
-
-#ifndef HAVE_CHAR32_T
-#define char32_t uint32_t
-#endif
-
-#ifndef HAVE_CHAR16_T
-#define char16_t uint16_t
-#endif
-
-#ifndef ETHERTYPE_LLDP
-#define ETHERTYPE_LLDP 0x88cc
-#endif
-
-#ifndef IFA_F_MCAUTOJOIN
-#define IFA_F_MCAUTOJOIN 0x400
-#endif
-
-#endif
-
-#include "missing_syscall.h"
diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h
deleted file mode 100644
index e6fd67cb9d..0000000000
--- a/src/basic/missing_syscall.h
+++ /dev/null
@@ -1,300 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- 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 */
-
-#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
-
-/* ======================================================================= */
-
-#if !HAVE_DECL_MEMFD_CREATE
-# ifndef __NR_memfd_create
-# if defined __x86_64__
-# define __NR_memfd_create 319
-# elif defined __arm__
-# define __NR_memfd_create 385
-# elif defined __aarch64__
-# define __NR_memfd_create 279
-# elif defined __s390__
-# define __NR_memfd_create 350
-# elif defined _MIPS_SIM
-# if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __NR_memfd_create 4354
-# endif
-# if _MIPS_SIM == _MIPS_SIM_NABI32
-# define __NR_memfd_create 6318
-# endif
-# if _MIPS_SIM == _MIPS_SIM_ABI64
-# define __NR_memfd_create 5314
-# endif
-# elif defined __i386__
-# define __NR_memfd_create 356
-# else
-# warning "__NR_memfd_create unknown for your architecture"
-# endif
-# endif
-
-static inline int memfd_create(const char *name, unsigned int flags) {
-# ifdef __NR_memfd_create
- return syscall(__NR_memfd_create, name, flags);
-# else
- errno = ENOSYS;
- return -1;
-# endif
-}
-#endif
-
-/* ======================================================================= */
-
-#if !HAVE_DECL_GETRANDOM
-# ifndef __NR_getrandom
-# if defined __x86_64__
-# define __NR_getrandom 318
-# elif defined(__i386__)
-# define __NR_getrandom 355
-# elif defined(__arm__)
-# define __NR_getrandom 384
-# elif defined(__aarch64__)
-# define __NR_getrandom 278
-# elif defined(__ia64__)
-# define __NR_getrandom 1339
-# elif defined(__m68k__)
-# define __NR_getrandom 352
-# elif defined(__s390x__)
-# define __NR_getrandom 349
-# elif defined(__powerpc__)
-# define __NR_getrandom 359
-# elif defined _MIPS_SIM
-# if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __NR_getrandom 4353
-# endif
-# if _MIPS_SIM == _MIPS_SIM_NABI32
-# define __NR_getrandom 6317
-# endif
-# if _MIPS_SIM == _MIPS_SIM_ABI64
-# define __NR_getrandom 5313
-# endif
-# else
-# warning "__NR_getrandom unknown for your architecture"
-# endif
-# endif
-
-static inline int getrandom(void *buffer, size_t count, unsigned flags) {
-# ifdef __NR_getrandom
- return syscall(__NR_getrandom, buffer, count, flags);
-# else
- errno = ENOSYS;
- return -1;
-# endif
-}
-#endif
-
-/* ======================================================================= */
-
-#if !HAVE_DECL_GETTID
-static inline pid_t gettid(void) {
- return (pid_t) syscall(SYS_gettid);
-}
-#endif
-
-/* ======================================================================= */
-
-#if !HAVE_DECL_NAME_TO_HANDLE_AT
-# ifndef __NR_name_to_handle_at
-# if defined(__x86_64__)
-# define __NR_name_to_handle_at 303
-# elif defined(__i386__)
-# define __NR_name_to_handle_at 341
-# elif defined(__arm__)
-# define __NR_name_to_handle_at 370
-# elif defined(__powerpc__)
-# define __NR_name_to_handle_at 345
-# else
-# error "__NR_name_to_handle_at is not defined"
-# endif
-# endif
-
-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) {
-# ifdef __NR_name_to_handle_at
- return syscall(__NR_name_to_handle_at, fd, name, handle, mnt_id, flags);
-# else
- errno = ENOSYS;
- return -1;
-# endif
-}
-#endif
-
-/* ======================================================================= */
-
-#if !HAVE_DECL_SETNS
-# ifndef __NR_setns
-# if defined(__x86_64__)
-# define __NR_setns 308
-# elif defined(__i386__)
-# define __NR_setns 346
-# else
-# error "__NR_setns is not defined"
-# endif
-# endif
-
-static inline int setns(int fd, int nstype) {
-# ifdef __NR_setns
- return syscall(__NR_setns, fd, nstype);
-# else
- errno = ENOSYS;
- return -1;
-# endif
-}
-#endif
-
-/* ======================================================================= */
-
-static inline pid_t raw_getpid(void) {
-#if defined(__alpha__)
- return (pid_t) syscall(__NR_getxpid);
-#else
- return (pid_t) syscall(__NR_getpid);
-#endif
-}
-
-/* ======================================================================= */
-
-#if !HAVE_DECL_RENAMEAT2
-# ifndef __NR_renameat2
-# if defined __x86_64__
-# define __NR_renameat2 316
-# elif defined __arm__
-# define __NR_renameat2 382
-# elif defined _MIPS_SIM
-# if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __NR_renameat2 4351
-# endif
-# if _MIPS_SIM == _MIPS_SIM_NABI32
-# define __NR_renameat2 6315
-# endif
-# if _MIPS_SIM == _MIPS_SIM_ABI64
-# define __NR_renameat2 5311
-# endif
-# elif defined __i386__
-# define __NR_renameat2 353
-# else
-# warning "__NR_renameat2 unknown for your architecture"
-# endif
-# endif
-
-static inline int renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) {
-# ifdef __NR_renameat2
- return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags);
-# else
- errno = ENOSYS;
- return -1;
-# endif
-}
-#endif
-
-/* ======================================================================= */
-
-#if !HAVE_DECL_KCMP
-static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) {
-# ifdef __NR_kcmp
- return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
-# else
- errno = ENOSYS;
- return -1;
-# endif
-}
-#endif
-
-/* ======================================================================= */
-
-#if !HAVE_DECL_KEYCTL
-static inline long keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4,unsigned long arg5) {
-# ifdef __NR_keyctl
- return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
-# else
- errno = ENOSYS;
- return -1;
-# endif
-}
-
-static inline key_serial_t add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) {
-# ifdef __NR_add_key
- return syscall(__NR_add_key, type, description, payload, plen, ringid);
-# else
- errno = ENOSYS;
- return -1;
-# endif
-}
-
-static inline key_serial_t request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) {
-# ifdef __NR_request_key
- return syscall(__NR_request_key, type, description, callout_info, destringid);
-# else
- errno = ENOSYS;
- return -1;
-# endif
-}
-#endif
-
-/* ======================================================================= */
-
-#if !HAVE_DECL_COPY_FILE_RANGE
-# ifndef __NR_copy_file_range
-# if defined(__x86_64__)
-# define __NR_copy_file_range 326
-# elif defined(__i386__)
-# define __NR_copy_file_range 377
-# elif defined __s390__
-# define __NR_copy_file_range 375
-# elif defined __arm__
-# define __NR_copy_file_range 391
-# elif defined __aarch64__
-# define __NR_copy_file_range 285
-# elif defined __powerpc__
-# define __NR_copy_file_range 379
-# else
-# warning "__NR_copy_file_range not defined for your architecture"
-# endif
-# endif
-
-static inline ssize_t copy_file_range(int fd_in, loff_t *off_in,
- int fd_out, loff_t *off_out,
- size_t len,
- unsigned int flags) {
-# ifdef __NR_copy_file_range
- return syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags);
-# else
- errno = ENOSYS;
- return -1;
-# endif
-}
-#endif
diff --git a/src/basic/mkdir-label.c b/src/basic/mkdir-label.c
deleted file mode 100644
index aa6878cdf0..0000000000
--- a/src/basic/mkdir-label.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 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 <stdio.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "label.h"
-#include "mkdir.h"
-
-int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid) {
- return mkdir_safe_internal(path, mode, uid, gid, mkdir_label);
-}
-
-int mkdir_parents_label(const char *path, mode_t mode) {
- return mkdir_parents_internal(NULL, path, mode, mkdir_label);
-}
-
-int mkdir_p_label(const char *path, mode_t mode) {
- return mkdir_p_internal(NULL, path, mode, mkdir_label);
-}
diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c
deleted file mode 100644
index 6b1a98402c..0000000000
--- a/src/basic/mkdir.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/***
- 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 <stdbool.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#include "fs-util.h"
-#include "macro.h"
-#include "mkdir.h"
-#include "path-util.h"
-#include "stat-util.h"
-#include "user-util.h"
-
-int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, mkdir_func_t _mkdir) {
- struct stat st;
-
- if (_mkdir(path, mode) >= 0)
- if (chmod_and_chown(path, mode, uid, gid) < 0)
- return -errno;
-
- if (lstat(path, &st) < 0)
- return -errno;
-
- if ((st.st_mode & 0007) > (mode & 0007) ||
- (st.st_mode & 0070) > (mode & 0070) ||
- (st.st_mode & 0700) > (mode & 0700) ||
- (uid != UID_INVALID && st.st_uid != uid) ||
- (gid != GID_INVALID && st.st_gid != gid) ||
- !S_ISDIR(st.st_mode))
- return -EEXIST;
-
- return 0;
-}
-
-int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid) {
- return mkdir_safe_internal(path, mode, uid, gid, mkdir);
-}
-
-int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) {
- const char *p, *e;
- int r;
-
- assert(path);
-
- if (prefix && !path_startswith(path, prefix))
- return -ENOTDIR;
-
- /* return immediately if directory exists */
- e = strrchr(path, '/');
- if (!e)
- return -EINVAL;
-
- if (e == path)
- return 0;
-
- p = strndupa(path, e - path);
- r = is_dir(p, true);
- if (r > 0)
- return 0;
- if (r == 0)
- return -ENOTDIR;
-
- /* create every parent directory in the path, except the last component */
- p = path + strspn(path, "/");
- for (;;) {
- char t[strlen(path) + 1];
-
- e = p + strcspn(p, "/");
- p = e + strspn(e, "/");
-
- /* Is this the last component? If so, then we're
- * done */
- if (*p == 0)
- return 0;
-
- memcpy(t, path, e - path);
- t[e-path] = 0;
-
- if (prefix && path_startswith(prefix, t))
- continue;
-
- r = _mkdir(t, mode);
- if (r < 0 && errno != EEXIST)
- return -errno;
- }
-}
-
-int mkdir_parents(const char *path, mode_t mode) {
- return mkdir_parents_internal(NULL, path, mode, mkdir);
-}
-
-int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) {
- int r;
-
- /* Like mkdir -p */
-
- r = mkdir_parents_internal(prefix, path, mode, _mkdir);
- if (r < 0)
- return r;
-
- r = _mkdir(path, mode);
- if (r < 0 && (errno != EEXIST || is_dir(path, true) <= 0))
- return -errno;
-
- return 0;
-}
-
-int mkdir_p(const char *path, mode_t mode) {
- return mkdir_p_internal(NULL, path, mode, mkdir);
-}
diff --git a/src/basic/mkdir.h b/src/basic/mkdir.h
deleted file mode 100644
index d564a3547f..0000000000
--- a/src/basic/mkdir.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 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 <sys/types.h>
-
-int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid);
-int mkdir_parents(const char *path, mode_t mode);
-int mkdir_p(const char *path, mode_t mode);
-
-/* mandatory access control(MAC) versions */
-int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid);
-int mkdir_parents_label(const char *path, mode_t mode);
-int mkdir_p_label(const char *path, mode_t mode);
-
-/* internally used */
-typedef int (*mkdir_func_t)(const char *pathname, mode_t mode);
-int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, mkdir_func_t _mkdir);
-int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir);
-int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir);
diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c
deleted file mode 100644
index c8f8022578..0000000000
--- a/src/basic/mount-util.c
+++ /dev/null
@@ -1,689 +0,0 @@
-/***
- 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 <stdlib.h>
-#include <string.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <unistd.h>
-
-#include "alloc-util.h"
-#include "escape.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "hashmap.h"
-#include "mount-util.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "set.h"
-#include "stdio-util.h"
-#include "string-util.h"
-#include "strv.h"
-
-static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id) {
- char path[strlen("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)];
- _cleanup_free_ char *fdinfo = NULL;
- _cleanup_close_ int subfd = -1;
- char *p;
- int r;
-
- if ((flags & AT_EMPTY_PATH) && isempty(filename))
- xsprintf(path, "/proc/self/fdinfo/%i", fd);
- else {
- subfd = openat(fd, filename, O_CLOEXEC|O_PATH);
- if (subfd < 0)
- return -errno;
-
- xsprintf(path, "/proc/self/fdinfo/%i", subfd);
- }
-
- r = read_full_file(path, &fdinfo, NULL);
- if (r == -ENOENT) /* The fdinfo directory is a relatively new addition */
- return -EOPNOTSUPP;
- if (r < 0)
- return -errno;
-
- p = startswith(fdinfo, "mnt_id:");
- if (!p) {
- p = strstr(fdinfo, "\nmnt_id:");
- if (!p) /* The mnt_id field is a relatively new addition */
- return -EOPNOTSUPP;
-
- p += 8;
- }
-
- p += strspn(p, WHITESPACE);
- p[strcspn(p, WHITESPACE)] = 0;
-
- return safe_atoi(p, mnt_id);
-}
-
-int fd_is_mount_point(int fd, const char *filename, int flags) {
- union file_handle_union h = FILE_HANDLE_INIT, h_parent = FILE_HANDLE_INIT;
- int mount_id = -1, mount_id_parent = -1;
- bool nosupp = false, check_st_dev = true;
- struct stat a, b;
- int r;
-
- assert(fd >= 0);
- assert(filename);
-
- /* First we will try the name_to_handle_at() syscall, which
- * tells us the mount id and an opaque file "handle". It is
- * not supported everywhere though (kernel compile-time
- * option, not all file systems are hooked up). If it works
- * the mount id is usually good enough to tell us whether
- * something is a mount point.
- *
- * If that didn't work we will try to read the mount id from
- * /proc/self/fdinfo/<fd>. This is almost as good as
- * name_to_handle_at(), however, does not return the
- * opaque file handle. The opaque file handle is pretty useful
- * to detect the root directory, which we should always
- * consider a mount point. Hence we use this only as
- * fallback. Exporting the mnt_id in fdinfo is a pretty recent
- * kernel addition.
- *
- * As last fallback we do traditional fstat() based st_dev
- * comparisons. This is how things were traditionally done,
- * but unionfs breaks this since it exposes file
- * systems with a variety of st_dev reported. Also, btrfs
- * subvolumes have different st_dev, even though they aren't
- * real mounts of their own. */
-
- r = name_to_handle_at(fd, filename, &h.handle, &mount_id, flags);
- if (r < 0) {
- if (errno == ENOSYS)
- /* This kernel does not support name_to_handle_at()
- * fall back to simpler logic. */
- goto fallback_fdinfo;
- else if (errno == EOPNOTSUPP)
- /* This kernel or file system does not support
- * name_to_handle_at(), hence let's see if the
- * upper fs supports it (in which case it is a
- * mount point), otherwise fallback to the
- * traditional stat() logic */
- nosupp = true;
- else
- return -errno;
- }
-
- r = name_to_handle_at(fd, "", &h_parent.handle, &mount_id_parent, AT_EMPTY_PATH);
- if (r < 0) {
- if (errno == EOPNOTSUPP) {
- if (nosupp)
- /* Neither parent nor child do name_to_handle_at()?
- We have no choice but to fall back. */
- goto fallback_fdinfo;
- else
- /* 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. */
- return 1;
- } else
- return -errno;
- }
-
- /* The parent can do name_to_handle_at() but the
- * directory we are interested in can't? If so, it
- * must be a mount point. */
- if (nosupp)
- return 1;
-
- /* If the file handle for the directory we are
- * interested in and its parent are identical, we
- * assume this is the root directory, which is a mount
- * point. */
-
- if (h.handle.handle_bytes == h_parent.handle.handle_bytes &&
- h.handle.handle_type == h_parent.handle.handle_type &&
- memcmp(h.handle.f_handle, h_parent.handle.f_handle, h.handle.handle_bytes) == 0)
- return 1;
-
- return mount_id != mount_id_parent;
-
-fallback_fdinfo:
- r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id);
- if (IN_SET(r, -EOPNOTSUPP, -EACCES))
- goto fallback_fstat;
- if (r < 0)
- return r;
-
- r = fd_fdinfo_mnt_id(fd, "", AT_EMPTY_PATH, &mount_id_parent);
- if (r < 0)
- return r;
-
- if (mount_id != mount_id_parent)
- return 1;
-
- /* Hmm, so, the mount ids are the same. This leaves one
- * special case though for the root file system. For that,
- * let's see if the parent directory has the same inode as we
- * are interested in. Hence, let's also do fstat() checks now,
- * too, but avoid the st_dev comparisons, since they aren't
- * that useful on unionfs mounts. */
- check_st_dev = false;
-
-fallback_fstat:
- /* yay for fstatat() taking a different set of flags than the other
- * _at() above */
- if (flags & AT_SYMLINK_FOLLOW)
- flags &= ~AT_SYMLINK_FOLLOW;
- else
- flags |= AT_SYMLINK_NOFOLLOW;
- if (fstatat(fd, filename, &a, flags) < 0)
- return -errno;
-
- if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0)
- return -errno;
-
- /* A directory with same device and inode as its parent? Must
- * be the root directory */
- if (a.st_dev == b.st_dev &&
- a.st_ino == b.st_ino)
- return 1;
-
- return check_st_dev && (a.st_dev != b.st_dev);
-}
-
-/* flags can be AT_SYMLINK_FOLLOW or 0 */
-int path_is_mount_point(const char *t, int flags) {
- _cleanup_close_ int fd = -1;
- _cleanup_free_ char *canonical = NULL, *parent = NULL;
-
- assert(t);
-
- if (path_equal(t, "/"))
- return 1;
-
- /* we need to resolve symlinks manually, we can't just rely on
- * fd_is_mount_point() to do that for us; if we have a structure like
- * /bin -> /usr/bin/ and /usr is a mount point, then the parent that we
- * look at needs to be /usr, not /. */
- if (flags & AT_SYMLINK_FOLLOW) {
- canonical = canonicalize_file_name(t);
- if (!canonical)
- return -errno;
-
- t = canonical;
- }
-
- parent = dirname_malloc(t);
- if (!parent)
- return -ENOMEM;
-
- fd = openat(AT_FDCWD, parent, O_DIRECTORY|O_CLOEXEC|O_PATH);
- if (fd < 0)
- return -errno;
-
- return fd_is_mount_point(fd, basename(t), flags);
-}
-
-int umount_recursive(const char *prefix, int flags) {
- bool again;
- int n = 0, r;
-
- /* Try to umount everything recursively below a
- * directory. Also, take care of stacked mounts, and keep
- * unmounting them until they are gone. */
-
- do {
- _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
-
- again = false;
- r = 0;
-
- proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
- if (!proc_self_mountinfo)
- return -errno;
-
- for (;;) {
- _cleanup_free_ char *path = NULL, *p = NULL;
- int k;
-
- k = fscanf(proc_self_mountinfo,
- "%*s " /* (1) mount id */
- "%*s " /* (2) parent id */
- "%*s " /* (3) major:minor */
- "%*s " /* (4) root */
- "%ms " /* (5) mount point */
- "%*s" /* (6) mount options */
- "%*[^-]" /* (7) optional fields */
- "- " /* (8) separator */
- "%*s " /* (9) file system type */
- "%*s" /* (10) mount source */
- "%*s" /* (11) mount options 2 */
- "%*[^\n]", /* some rubbish at the end */
- &path);
- if (k != 1) {
- if (k == EOF)
- break;
-
- continue;
- }
-
- r = cunescape(path, UNESCAPE_RELAX, &p);
- if (r < 0)
- return r;
-
- if (!path_startswith(p, prefix))
- continue;
-
- if (umount2(p, flags) < 0) {
- r = log_debug_errno(errno, "Failed to umount %s: %m", p);
- continue;
- }
-
- log_debug("Successfully unmounted %s", p);
-
- again = true;
- n++;
-
- break;
- }
-
- } while (again);
-
- return r ? r : n;
-}
-
-static int get_mount_flags(const char *path, unsigned long *flags) {
- struct statvfs buf;
-
- if (statvfs(path, &buf) < 0)
- return -errno;
- *flags = buf.f_flag;
- return 0;
-}
-
-int bind_remount_recursive(const char *prefix, bool ro, char **blacklist) {
- _cleanup_set_free_free_ Set *done = NULL;
- _cleanup_free_ char *cleaned = NULL;
- int r;
-
- /* Recursively remount a directory (and all its submounts) read-only or read-write. If the directory is already
- * mounted, we reuse the mount and simply mark it MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write
- * operation). If it isn't we first make it one. Afterwards we apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to
- * all submounts we can access, too. When mounts are stacked on the same mount point we only care for each
- * individual "top-level" mount on each point, as we cannot influence/access the underlying mounts anyway. We
- * do not have any effect on future submounts that might get propagated, they migt be writable. This includes
- * future submounts that have been triggered via autofs.
- *
- * If the "blacklist" parameter is specified it may contain a list of subtrees to exclude from the
- * remount operation. Note that we'll ignore the blacklist for the top-level path. */
-
- cleaned = strdup(prefix);
- if (!cleaned)
- return -ENOMEM;
-
- path_kill_slashes(cleaned);
-
- done = set_new(&string_hash_ops);
- if (!done)
- return -ENOMEM;
-
- for (;;) {
- _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
- _cleanup_set_free_free_ Set *todo = NULL;
- bool top_autofs = false;
- char *x;
- unsigned long orig_flags;
-
- todo = set_new(&string_hash_ops);
- if (!todo)
- return -ENOMEM;
-
- proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
- if (!proc_self_mountinfo)
- return -errno;
-
- for (;;) {
- _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL;
- int k;
-
- k = fscanf(proc_self_mountinfo,
- "%*s " /* (1) mount id */
- "%*s " /* (2) parent id */
- "%*s " /* (3) major:minor */
- "%*s " /* (4) root */
- "%ms " /* (5) mount point */
- "%*s" /* (6) mount options (superblock) */
- "%*[^-]" /* (7) optional fields */
- "- " /* (8) separator */
- "%ms " /* (9) file system type */
- "%*s" /* (10) mount source */
- "%*s" /* (11) mount options (bind mount) */
- "%*[^\n]", /* some rubbish at the end */
- &path,
- &type);
- if (k != 2) {
- if (k == EOF)
- break;
-
- continue;
- }
-
- r = cunescape(path, UNESCAPE_RELAX, &p);
- if (r < 0)
- return r;
-
- if (!path_startswith(p, cleaned))
- continue;
-
- /* Ignore this mount if it is blacklisted, but only if it isn't the top-level mount we shall
- * operate on. */
- if (!path_equal(cleaned, p)) {
- bool blacklisted = false;
- char **i;
-
- STRV_FOREACH(i, blacklist) {
-
- if (path_equal(*i, cleaned))
- continue;
-
- if (!path_startswith(*i, cleaned))
- continue;
-
- if (path_startswith(p, *i)) {
- blacklisted = true;
- log_debug("Not remounting %s, because blacklisted by %s, called for %s", p, *i, cleaned);
- break;
- }
- }
- if (blacklisted)
- continue;
- }
-
- /* Let's ignore autofs mounts. If they aren't
- * triggered yet, we want to avoid triggering
- * them, as we don't make any guarantees for
- * future submounts anyway. If they are
- * already triggered, then we will find
- * another entry for this. */
- if (streq(type, "autofs")) {
- top_autofs = top_autofs || path_equal(cleaned, p);
- continue;
- }
-
- if (!set_contains(done, p)) {
- r = set_consume(todo, p);
- p = NULL;
- if (r == -EEXIST)
- continue;
- if (r < 0)
- return r;
- }
- }
-
- /* If we have no submounts to process anymore and if
- * the root is either already done, or an autofs, we
- * are done */
- if (set_isempty(todo) &&
- (top_autofs || set_contains(done, cleaned)))
- return 0;
-
- if (!set_contains(done, cleaned) &&
- !set_contains(todo, cleaned)) {
- /* The prefix directory itself is not yet a mount, make it one. */
- if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0)
- return -errno;
-
- orig_flags = 0;
- (void) get_mount_flags(cleaned, &orig_flags);
- orig_flags &= ~MS_RDONLY;
-
- if (mount(NULL, prefix, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0)
- return -errno;
-
- log_debug("Made top-level directory %s a mount point.", prefix);
-
- x = strdup(cleaned);
- if (!x)
- return -ENOMEM;
-
- r = set_consume(done, x);
- if (r < 0)
- return r;
- }
-
- while ((x = set_steal_first(todo))) {
-
- r = set_consume(done, x);
- if (r == -EEXIST || r == 0)
- continue;
- if (r < 0)
- return r;
-
- /* Deal with mount points that are obstructed by a later mount */
- r = path_is_mount_point(x, 0);
- if (r == -ENOENT || r == 0)
- continue;
- if (r < 0)
- return r;
-
- /* Try to reuse the original flag set */
- orig_flags = 0;
- (void) get_mount_flags(x, &orig_flags);
- orig_flags &= ~MS_RDONLY;
-
- if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0)
- return -errno;
-
- log_debug("Remounted %s read-only.", x);
- }
- }
-}
-
-int mount_move_root(const char *path) {
- assert(path);
-
- if (chdir(path) < 0)
- return -errno;
-
- if (mount(path, "/", NULL, MS_MOVE, NULL) < 0)
- return -errno;
-
- if (chroot(".") < 0)
- return -errno;
-
- if (chdir("/") < 0)
- return -errno;
-
- return 0;
-}
-
-bool fstype_is_network(const char *fstype) {
- static const char table[] =
- "afs\0"
- "cifs\0"
- "smbfs\0"
- "sshfs\0"
- "ncpfs\0"
- "ncp\0"
- "nfs\0"
- "nfs4\0"
- "gfs\0"
- "gfs2\0"
- "glusterfs\0"
- "pvfs2\0" /* OrangeFS */
- "ocfs2\0"
- "lustre\0"
- ;
-
- const char *x;
-
- x = startswith(fstype, "fuse.");
- if (x)
- fstype = x;
-
- return nulstr_contains(table, fstype);
-}
-
-int repeat_unmount(const char *path, int flags) {
- bool done = false;
-
- assert(path);
-
- /* If there are multiple mounts on a mount point, this
- * removes them all */
-
- for (;;) {
- if (umount2(path, flags) < 0) {
-
- if (errno == EINVAL)
- return done;
-
- return -errno;
- }
-
- done = true;
- }
-}
-
-const char* mode_to_inaccessible_node(mode_t mode) {
- /* This function maps a node type to the correspondent inaccessible node type.
- * Character and block inaccessible devices may not be created (because major=0 and minor=0),
- * in such case we map character and block devices to the inaccessible node type socket. */
- switch(mode & S_IFMT) {
- case S_IFREG:
- return "/run/systemd/inaccessible/reg";
- case S_IFDIR:
- return "/run/systemd/inaccessible/dir";
- case S_IFCHR:
- if (access("/run/systemd/inaccessible/chr", F_OK) == 0)
- return "/run/systemd/inaccessible/chr";
- return "/run/systemd/inaccessible/sock";
- case S_IFBLK:
- if (access("/run/systemd/inaccessible/blk", F_OK) == 0)
- return "/run/systemd/inaccessible/blk";
- return "/run/systemd/inaccessible/sock";
- case S_IFIFO:
- return "/run/systemd/inaccessible/fifo";
- case S_IFSOCK:
- return "/run/systemd/inaccessible/sock";
- }
- return NULL;
-}
-
-#define FLAG(name) (flags & name ? STRINGIFY(name) "|" : "")
-static char* mount_flags_to_string(long unsigned flags) {
- char *x;
- _cleanup_free_ char *y = NULL;
- long unsigned overflow;
-
- overflow = flags & ~(MS_RDONLY |
- MS_NOSUID |
- MS_NODEV |
- MS_NOEXEC |
- MS_SYNCHRONOUS |
- MS_REMOUNT |
- MS_MANDLOCK |
- MS_DIRSYNC |
- MS_NOATIME |
- MS_NODIRATIME |
- MS_BIND |
- MS_MOVE |
- MS_REC |
- MS_SILENT |
- MS_POSIXACL |
- MS_UNBINDABLE |
- MS_PRIVATE |
- MS_SLAVE |
- MS_SHARED |
- MS_RELATIME |
- MS_KERNMOUNT |
- MS_I_VERSION |
- MS_STRICTATIME |
- MS_LAZYTIME);
-
- if (flags == 0 || overflow != 0)
- if (asprintf(&y, "%lx", overflow) < 0)
- return NULL;
-
- x = strjoin(FLAG(MS_RDONLY),
- FLAG(MS_NOSUID),
- FLAG(MS_NODEV),
- FLAG(MS_NOEXEC),
- FLAG(MS_SYNCHRONOUS),
- FLAG(MS_REMOUNT),
- FLAG(MS_MANDLOCK),
- FLAG(MS_DIRSYNC),
- FLAG(MS_NOATIME),
- FLAG(MS_NODIRATIME),
- FLAG(MS_BIND),
- FLAG(MS_MOVE),
- FLAG(MS_REC),
- FLAG(MS_SILENT),
- FLAG(MS_POSIXACL),
- FLAG(MS_UNBINDABLE),
- FLAG(MS_PRIVATE),
- FLAG(MS_SLAVE),
- FLAG(MS_SHARED),
- FLAG(MS_RELATIME),
- FLAG(MS_KERNMOUNT),
- FLAG(MS_I_VERSION),
- FLAG(MS_STRICTATIME),
- FLAG(MS_LAZYTIME),
- y, NULL);
- if (!x)
- return NULL;
- if (!y)
- x[strlen(x) - 1] = '\0'; /* truncate the last | */
- return x;
-}
-
-int mount_verbose(
- int error_log_level,
- const char *what,
- const char *where,
- const char *type,
- unsigned long flags,
- const char *options) {
-
- _cleanup_free_ char *fl = NULL;
-
- fl = mount_flags_to_string(flags);
-
- if ((flags & MS_REMOUNT) && !what && !type)
- log_debug("Remounting %s (%s \"%s\")...",
- where, strnull(fl), strempty(options));
- else if (!what && !type)
- log_debug("Mounting %s (%s \"%s\")...",
- where, strnull(fl), strempty(options));
- else if ((flags & MS_BIND) && !type)
- log_debug("Bind-mounting %s on %s (%s \"%s\")...",
- what, where, strnull(fl), strempty(options));
- else
- log_debug("Mounting %s on %s (%s \"%s\")...",
- strna(type), where, strnull(fl), strempty(options));
- if (mount(what, where, type, flags, options) < 0)
- return log_full_errno(error_log_level, errno,
- "Failed to mount %s on %s (%s \"%s\"): %m",
- strna(type), where, strnull(fl), strempty(options));
- return 0;
-}
-
-int umount_verbose(const char *what) {
- log_debug("Umounting %s...", what);
- if (umount(what) < 0)
- return log_error_errno(errno, "Failed to unmount %s: %m", what);
- return 0;
-}
diff --git a/src/basic/mount-util.h b/src/basic/mount-util.h
deleted file mode 100644
index 4f305df19f..0000000000
--- a/src/basic/mount-util.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#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 <fcntl.h>
-#include <mntent.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "macro.h"
-#include "missing.h"
-
-int fd_is_mount_point(int fd, const char *filename, int flags);
-int path_is_mount_point(const char *path, int flags);
-
-int repeat_unmount(const char *path, int flags);
-
-int umount_recursive(const char *target, int flags);
-int bind_remount_recursive(const char *prefix, bool ro, char **blacklist);
-
-int mount_move_root(const char *path);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent);
-#define _cleanup_endmntent_ _cleanup_(endmntentp)
-
-bool fstype_is_network(const char *fstype);
-
-union file_handle_union {
- struct file_handle handle;
- char padding[sizeof(struct file_handle) + MAX_HANDLE_SZ];
-};
-
-const char* mode_to_inaccessible_node(mode_t mode);
-
-#define FILE_HANDLE_INIT { .handle.handle_bytes = MAX_HANDLE_SZ }
-
-int mount_verbose(
- int error_log_level,
- const char *what,
- const char *where,
- const char *type,
- unsigned long flags,
- const char *options);
-int umount_verbose(const char *where);
diff --git a/src/basic/nss-util.h b/src/basic/nss-util.h
deleted file mode 100644
index e7844fff96..0000000000
--- a/src/basic/nss-util.h
+++ /dev/null
@@ -1,199 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 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 <grp.h>
-#include <netdb.h>
-#include <nss.h>
-#include <pwd.h>
-#include <resolv.h>
-
-#define NSS_SIGNALS_BLOCK SIGALRM,SIGVTALRM,SIGPIPE,SIGCHLD,SIGTSTP,SIGIO,SIGHUP,SIGUSR1,SIGUSR2,SIGPROF,SIGURG,SIGWINCH
-
-#define NSS_GETHOSTBYNAME_PROTOTYPES(module) \
-enum nss_status _nss_##module##_gethostbyname4_r( \
- const char *name, \
- struct gaih_addrtuple **pat, \
- char *buffer, size_t buflen, \
- int *errnop, int *h_errnop, \
- int32_t *ttlp) _public_; \
-enum nss_status _nss_##module##_gethostbyname3_r( \
- const char *name, \
- int af, \
- struct hostent *host, \
- char *buffer, size_t buflen, \
- int *errnop, int *h_errnop, \
- int32_t *ttlp, \
- char **canonp) _public_; \
-enum nss_status _nss_##module##_gethostbyname2_r( \
- const char *name, \
- int af, \
- struct hostent *host, \
- char *buffer, size_t buflen, \
- int *errnop, int *h_errnop) _public_; \
-enum nss_status _nss_##module##_gethostbyname_r( \
- const char *name, \
- struct hostent *host, \
- char *buffer, size_t buflen, \
- int *errnop, int *h_errnop) _public_
-
-#define NSS_GETHOSTBYADDR_PROTOTYPES(module) \
-enum nss_status _nss_##module##_gethostbyaddr2_r( \
- const void* addr, socklen_t len, \
- int af, \
- struct hostent *host, \
- char *buffer, size_t buflen, \
- int *errnop, int *h_errnop, \
- int32_t *ttlp) _public_; \
-enum nss_status _nss_##module##_gethostbyaddr_r( \
- const void* addr, socklen_t len, \
- int af, \
- struct hostent *host, \
- char *buffer, size_t buflen, \
- int *errnop, int *h_errnop) _public_
-
-#define NSS_GETHOSTBYNAME_FALLBACKS(module) \
-enum nss_status _nss_##module##_gethostbyname2_r( \
- const char *name, \
- int af, \
- struct hostent *host, \
- char *buffer, size_t buflen, \
- int *errnop, int *h_errnop) { \
- return _nss_##module##_gethostbyname3_r( \
- name, \
- af, \
- host, \
- buffer, buflen, \
- errnop, h_errnop, \
- NULL, \
- NULL); \
-} \
-enum nss_status _nss_##module##_gethostbyname_r( \
- const char *name, \
- struct hostent *host, \
- char *buffer, size_t buflen, \
- int *errnop, int *h_errnop) { \
- enum nss_status ret = NSS_STATUS_NOTFOUND; \
- \
- if (_res.options & RES_USE_INET6) \
- ret = _nss_##module##_gethostbyname3_r( \
- name, \
- AF_INET6, \
- host, \
- buffer, buflen, \
- errnop, h_errnop, \
- NULL, \
- NULL); \
- if (ret == NSS_STATUS_NOTFOUND) \
- ret = _nss_##module##_gethostbyname3_r( \
- name, \
- AF_INET, \
- host, \
- buffer, buflen, \
- errnop, h_errnop, \
- NULL, \
- NULL); \
- return ret; \
-} \
-struct __useless_struct_to_allow_trailing_semicolon__
-
-#define NSS_GETHOSTBYADDR_FALLBACKS(module) \
-enum nss_status _nss_##module##_gethostbyaddr_r( \
- const void* addr, socklen_t len, \
- int af, \
- struct hostent *host, \
- char *buffer, size_t buflen, \
- int *errnop, int *h_errnop) { \
- return _nss_##module##_gethostbyaddr2_r( \
- addr, len, \
- af, \
- host, \
- buffer, buflen, \
- errnop, h_errnop, \
- NULL); \
-} \
-struct __useless_struct_to_allow_trailing_semicolon__
-
-#define NSS_GETPW_PROTOTYPES(module) \
-enum nss_status _nss_##module##_getpwnam_r( \
- const char *name, \
- struct passwd *pwd, \
- char *buffer, size_t buflen, \
- int *errnop) _public_; \
-enum nss_status _nss_##module##_getpwuid_r( \
- uid_t uid, \
- struct passwd *pwd, \
- char *buffer, size_t buflen, \
- int *errnop) _public_
-
-#define NSS_GETGR_PROTOTYPES(module) \
-enum nss_status _nss_##module##_getgrnam_r( \
- const char *name, \
- struct group *gr, \
- char *buffer, size_t buflen, \
- int *errnop) _public_; \
-enum nss_status _nss_##module##_getgrgid_r( \
- gid_t gid, \
- struct group *gr, \
- char *buffer, size_t buflen, \
- int *errnop) _public_
-
-typedef enum nss_status (*_nss_gethostbyname4_r_t)(
- const char *name,
- struct gaih_addrtuple **pat,
- char *buffer, size_t buflen,
- int *errnop, int *h_errnop,
- int32_t *ttlp);
-
-typedef enum nss_status (*_nss_gethostbyname3_r_t)(
- const char *name,
- int af,
- struct hostent *result,
- char *buffer, size_t buflen,
- int *errnop, int *h_errnop,
- int32_t *ttlp,
- char **canonp);
-
-typedef enum nss_status (*_nss_gethostbyname2_r_t)(
- const char *name,
- int af,
- struct hostent *result,
- char *buffer, size_t buflen,
- int *errnop, int *h_errnop);
-
-typedef enum nss_status (*_nss_gethostbyname_r_t)(
- const char *name,
- struct hostent *result,
- char *buffer, size_t buflen,
- int *errnop, int *h_errnop);
-
-typedef enum nss_status (*_nss_gethostbyaddr2_r_t)(
- const void* addr, socklen_t len,
- int af,
- struct hostent *result,
- char *buffer, size_t buflen,
- int *errnop, int *h_errnop,
- int32_t *ttlp);
-typedef enum nss_status (*_nss_gethostbyaddr_r_t)(
- const void* addr, socklen_t len,
- int af,
- struct hostent *host,
- char *buffer, size_t buflen,
- int *errnop, int *h_errnop);
diff --git a/src/basic/ordered-set.c b/src/basic/ordered-set.c
deleted file mode 100644
index 2e0bdf6488..0000000000
--- a/src/basic/ordered-set.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2016 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 "ordered-set.h"
-#include "strv.h"
-
-int ordered_set_consume(OrderedSet *s, void *p) {
- int r;
-
- r = ordered_set_put(s, p);
- if (r <= 0)
- free(p);
-
- return r;
-}
-
-int ordered_set_put_strdup(OrderedSet *s, const char *p) {
- char *c;
- int r;
-
- assert(s);
- assert(p);
-
- c = strdup(p);
- if (!c)
- return -ENOMEM;
-
- r = ordered_set_consume(s, c);
- if (r == -EEXIST)
- return 0;
-
- return r;
-}
-
-int ordered_set_put_strdupv(OrderedSet *s, char **l) {
- int n = 0, r;
- char **i;
-
- STRV_FOREACH(i, l) {
- r = ordered_set_put_strdup(s, *i);
- if (r < 0)
- return r;
-
- n += r;
- }
-
- return n;
-}
diff --git a/src/basic/ordered-set.h b/src/basic/ordered-set.h
deleted file mode 100644
index e1dfc86380..0000000000
--- a/src/basic/ordered-set.h
+++ /dev/null
@@ -1,74 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2015 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 "hashmap.h"
-
-typedef struct OrderedSet OrderedSet;
-
-static inline OrderedSet* ordered_set_new(const struct hash_ops *ops) {
- return (OrderedSet*) ordered_hashmap_new(ops);
-}
-
-static inline int ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops) {
- if (*s)
- return 0;
-
- *s = ordered_set_new(ops);
- if (!*s)
- return -ENOMEM;
-
- return 0;
-}
-
-static inline OrderedSet* ordered_set_free(OrderedSet *s) {
- ordered_hashmap_free((OrderedHashmap*) s);
- return NULL;
-}
-
-static inline OrderedSet* ordered_set_free_free(OrderedSet *s) {
- ordered_hashmap_free_free((OrderedHashmap*) s);
- return NULL;
-}
-
-static inline int ordered_set_put(OrderedSet *s, void *p) {
- return ordered_hashmap_put((OrderedHashmap*) s, p, p);
-}
-
-static inline bool ordered_set_isempty(OrderedSet *s) {
- return ordered_hashmap_isempty((OrderedHashmap*) s);
-}
-
-static inline bool ordered_set_iterate(OrderedSet *s, Iterator *i, void **value) {
- return ordered_hashmap_iterate((OrderedHashmap*) s, i, value, NULL);
-}
-
-int ordered_set_consume(OrderedSet *s, void *p);
-int ordered_set_put_strdup(OrderedSet *s, const char *p);
-int ordered_set_put_strdupv(OrderedSet *s, char **l);
-
-#define ORDERED_SET_FOREACH(e, s, i) \
- for ((i) = ITERATOR_FIRST; ordered_set_iterate((s), &(i), (void**)&(e)); )
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free_free);
-
-#define _cleanup_ordered_set_free_ _cleanup_(ordered_set_freep)
-#define _cleanup_ordered_set_free_free_ _cleanup_(ordered_set_free_freep)
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
deleted file mode 100644
index c98815b9bc..0000000000
--- a/src/basic/parse-util.c
+++ /dev/null
@@ -1,576 +0,0 @@
-/***
- 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 <inttypes.h>
-#include <locale.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <xlocale.h>
-
-#include "alloc-util.h"
-#include "extract-word.h"
-#include "macro.h"
-#include "parse-util.h"
-#include "process-util.h"
-#include "string-util.h"
-
-int parse_boolean(const char *v) {
- assert(v);
-
- if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on"))
- return 1;
- else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(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_mode(const char *s, mode_t *ret) {
- char *x;
- long l;
-
- assert(s);
- assert(ret);
-
- s += strspn(s, WHITESPACE);
- if (s[0] == '-')
- return -ERANGE;
-
- errno = 0;
- l = strtol(s, &x, 8);
- if (errno > 0)
- return -errno;
- if (!x || x == s || *x)
- return -EINVAL;
- if (l < 0 || l > 07777)
- return -ERANGE;
-
- *ret = (mode_t) l;
- return 0;
-}
-
-int parse_ifindex(const char *s, int *ret) {
- int ifi, r;
-
- r = safe_atoi(s, &ifi);
- if (r < 0)
- return r;
- if (ifi <= 0)
- return -EINVAL;
-
- *ret = ifi;
- return 0;
-}
-
-int parse_size(const char *t, uint64_t base, uint64_t *size) {
-
- /* Soo, sometimes we want to parse IEC binary suffixes, and
- * sometimes SI decimal suffixes. This function can parse
- * both. Which one is the right way depends on the
- * context. Wikipedia suggests that SI is customary for
- * hardware metrics and network speeds, while IEC is
- * customary for most data sizes used by software and volatile
- * (RAM) memory. Hence be careful which one you pick!
- *
- * In either case we use just K, M, G as suffix, and not Ki,
- * Mi, Gi or so (as IEC would suggest). That's because that's
- * frickin' ugly. But this means you really need to make sure
- * to document which base you are parsing when you use this
- * call. */
-
- struct table {
- const char *suffix;
- unsigned long long factor;
- };
-
- static const struct table iec[] = {
- { "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 },
- { "B", 1ULL },
- { "", 1ULL },
- };
-
- static const struct table si[] = {
- { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
- { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL },
- { "T", 1000ULL*1000ULL*1000ULL*1000ULL },
- { "G", 1000ULL*1000ULL*1000ULL },
- { "M", 1000ULL*1000ULL },
- { "K", 1000ULL },
- { "B", 1ULL },
- { "", 1ULL },
- };
-
- const struct table *table;
- const char *p;
- unsigned long long r = 0;
- unsigned n_entries, start_pos = 0;
-
- assert(t);
- assert(base == 1000 || base == 1024);
- assert(size);
-
- if (base == 1000) {
- table = si;
- n_entries = ELEMENTSOF(si);
- } else {
- table = iec;
- n_entries = ELEMENTSOF(iec);
- }
-
- p = t;
- do {
- unsigned long long l, tmp;
- double frac = 0;
- char *e;
- unsigned i;
-
- p += strspn(p, WHITESPACE);
-
- errno = 0;
- l = strtoull(p, &e, 10);
- if (errno > 0)
- return -errno;
- if (e == p)
- return -EINVAL;
- if (*p == '-')
- return -ERANGE;
-
- if (*e == '.') {
- e++;
-
- /* strtoull() itself would accept space/+/- */
- if (*e >= '0' && *e <= '9') {
- unsigned long long l2;
- char *e2;
-
- l2 = strtoull(e, &e2, 10);
- if (errno > 0)
- return -errno;
-
- /* Ignore failure. E.g. 10.M is valid */
- frac = l2;
- for (; e < e2; e++)
- frac /= 10;
- }
- }
-
- e += strspn(e, WHITESPACE);
-
- for (i = start_pos; i < n_entries; i++)
- if (startswith(e, table[i].suffix))
- break;
-
- if (i >= n_entries)
- return -EINVAL;
-
- if (l + (frac > 0) > ULLONG_MAX / table[i].factor)
- return -ERANGE;
-
- tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
- if (tmp > ULLONG_MAX - r)
- return -ERANGE;
-
- r += tmp;
- if ((unsigned long long) (uint64_t) r != r)
- return -ERANGE;
-
- p = e + strlen(table[i].suffix);
-
- start_pos = i + 1;
-
- } while (*p);
-
- *size = r;
-
- return 0;
-}
-
-int parse_range(const char *t, unsigned *lower, unsigned *upper) {
- _cleanup_free_ char *word = NULL;
- unsigned l, u;
- int r;
-
- assert(lower);
- assert(upper);
-
- /* Extract the lower bound. */
- r = extract_first_word(&t, &word, "-", EXTRACT_DONT_COALESCE_SEPARATORS);
- if (r < 0)
- return r;
- if (r == 0)
- return -EINVAL;
-
- r = safe_atou(word, &l);
- if (r < 0)
- return r;
-
- /* Check for the upper bound and extract it if needed */
- if (!t)
- /* Single number with no dashes. */
- u = l;
- else if (!*t)
- /* Trailing dash is an error. */
- return -EINVAL;
- else {
- r = safe_atou(t, &u);
- if (r < 0)
- return r;
- }
-
- *lower = l;
- *upper = u;
- return 0;
-}
-
-char *format_bytes(char *buf, size_t l, uint64_t t) {
- unsigned i;
-
- /* This only does IEC units so far */
-
- static const struct {
- const char *suffix;
- uint64_t factor;
- } table[] = {
- { "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
- { "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
- { "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
- { "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
- { "M", UINT64_C(1024)*UINT64_C(1024) },
- { "K", UINT64_C(1024) },
- };
-
- if (t == (uint64_t) -1)
- return NULL;
-
- for (i = 0; i < ELEMENTSOF(table); i++) {
-
- if (t >= table[i].factor) {
- snprintf(buf, l,
- "%" PRIu64 ".%" PRIu64 "%s",
- t / table[i].factor,
- ((t*UINT64_C(10)) / table[i].factor) % UINT64_C(10),
- table[i].suffix);
-
- goto finish;
- }
- }
-
- snprintf(buf, l, "%" PRIu64 "B", t);
-
-finish:
- buf[l-1] = 0;
- return buf;
-
-}
-
-int safe_atou(const char *s, unsigned *ret_u) {
- char *x = NULL;
- unsigned long l;
-
- assert(s);
- assert(ret_u);
-
- /* strtoul() is happy to parse negative values, and silently
- * converts them to unsigned values without generating an
- * error. We want a clean error, hence let's look for the "-"
- * prefix on our own, and generate an error. But let's do so
- * only after strtoul() validated that the string is clean
- * otherwise, so that we return EINVAL preferably over
- * ERANGE. */
-
- s += strspn(s, WHITESPACE);
-
- errno = 0;
- l = strtoul(s, &x, 0);
- if (errno > 0)
- return -errno;
- if (!x || x == s || *x)
- return -EINVAL;
- if (s[0] == '-')
- return -ERANGE;
- 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 (errno > 0)
- return -errno;
- if (!x || x == s || *x)
- return -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);
-
- s += strspn(s, WHITESPACE);
-
- errno = 0;
- l = strtoull(s, &x, 0);
- if (errno > 0)
- return -errno;
- if (!x || x == s || *x)
- return -EINVAL;
- if (*s == '-')
- return -ERANGE;
-
- *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 (errno > 0)
- return -errno;
- if (!x || x == s || *x)
- return -EINVAL;
-
- *ret_lli = l;
- return 0;
-}
-
-int safe_atou8(const char *s, uint8_t *ret) {
- char *x = NULL;
- unsigned long l;
-
- assert(s);
- assert(ret);
-
- s += strspn(s, WHITESPACE);
-
- errno = 0;
- l = strtoul(s, &x, 0);
- if (errno > 0)
- return -errno;
- if (!x || x == s || *x)
- return -EINVAL;
- if (s[0] == '-')
- return -ERANGE;
- if ((unsigned long) (uint8_t) l != l)
- return -ERANGE;
-
- *ret = (uint8_t) l;
- return 0;
-}
-
-int safe_atou16(const char *s, uint16_t *ret) {
- char *x = NULL;
- unsigned long l;
-
- assert(s);
- assert(ret);
-
- s += strspn(s, WHITESPACE);
-
- errno = 0;
- l = strtoul(s, &x, 0);
- if (errno > 0)
- return -errno;
- if (!x || x == s || *x)
- return -EINVAL;
- if (s[0] == '-')
- return -ERANGE;
- if ((unsigned long) (uint16_t) l != l)
- return -ERANGE;
-
- *ret = (uint16_t) l;
- return 0;
-}
-
-int safe_atoi16(const char *s, int16_t *ret) {
- char *x = NULL;
- long l;
-
- assert(s);
- assert(ret);
-
- errno = 0;
- l = strtol(s, &x, 0);
- if (errno > 0)
- return -errno;
- if (!x || x == s || *x)
- return -EINVAL;
- if ((long) (int16_t) l != l)
- return -ERANGE;
-
- *ret = (int16_t) l;
- return 0;
-}
-
-int safe_atod(const char *s, double *ret_d) {
- char *x = NULL;
- double d = 0;
- locale_t loc;
-
- assert(s);
- assert(ret_d);
-
- loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
- if (loc == (locale_t) 0)
- return -errno;
-
- errno = 0;
- d = strtod_l(s, &x, loc);
- if (errno > 0) {
- freelocale(loc);
- return -errno;
- }
- if (!x || x == s || *x) {
- freelocale(loc);
- return -EINVAL;
- }
-
- freelocale(loc);
- *ret_d = (double) d;
- return 0;
-}
-
-int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
- size_t i;
- unsigned val = 0;
- const char *s;
-
- s = *p;
-
- /* accept any number of digits, strtoull is limted to 19 */
- for (i=0; i < digits; i++,s++) {
- if (*s < '0' || *s > '9') {
- if (i == 0)
- return -EINVAL;
-
- /* too few digits, pad with 0 */
- for (; i < digits; i++)
- val *= 10;
-
- break;
- }
-
- val *= 10;
- val += *s - '0';
- }
-
- /* maybe round up */
- if (*s >= '5' && *s <= '9')
- val++;
-
- s += strspn(s, DIGITS);
-
- *p = s;
- *res = val;
-
- return 0;
-}
-
-int parse_percent_unbounded(const char *p) {
- const char *pc, *n;
- unsigned v;
- int r;
-
- pc = endswith(p, "%");
- if (!pc)
- return -EINVAL;
-
- n = strndupa(p, pc - p);
- r = safe_atou(n, &v);
- if (r < 0)
- return r;
-
- return (int) v;
-}
-
-int parse_percent(const char *p) {
- int v;
-
- v = parse_percent_unbounded(p);
- if (v > 100)
- return -ERANGE;
-
- return v;
-}
-
-int parse_nice(const char *p, int *ret) {
- int n, r;
-
- r = safe_atoi(p, &n);
- if (r < 0)
- return r;
-
- if (!nice_is_valid(n))
- return -ERANGE;
-
- *ret = n;
- return 0;
-}
diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h
deleted file mode 100644
index 461e1cd4d8..0000000000
--- a/src/basic/parse-util.h
+++ /dev/null
@@ -1,112 +0,0 @@
-#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 <limits.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include "macro.h"
-
-#define MODE_INVALID ((mode_t) -1)
-
-int parse_boolean(const char *v) _pure_;
-int parse_pid(const char *s, pid_t* ret_pid);
-int parse_mode(const char *s, mode_t *ret);
-int parse_ifindex(const char *s, int *ret);
-
-int parse_size(const char *t, uint64_t base, uint64_t *size);
-int parse_range(const char *t, unsigned *lower, unsigned *upper);
-
-#define FORMAT_BYTES_MAX 8
-char *format_bytes(char *buf, size_t l, uint64_t t);
-
-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);
-
-int safe_atou8(const char *s, uint8_t *ret);
-
-int safe_atou16(const char *s, uint16_t *ret);
-int safe_atoi16(const char *s, int16_t *ret);
-
-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);
-}
-
-#if LONG_MAX == INT_MAX
-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
-
-#if SIZE_MAX == UINT_MAX
-static inline int safe_atozu(const char *s, size_t *ret_u) {
- assert_cc(sizeof(size_t) == sizeof(unsigned));
- return safe_atou(s, (unsigned *) ret_u);
-}
-#else
-static inline int safe_atozu(const char *s, size_t *ret_u) {
- assert_cc(sizeof(size_t) == sizeof(long unsigned));
- return safe_atolu(s, ret_u);
-}
-#endif
-
-int safe_atod(const char *s, double *ret_d);
-
-int parse_fractional_part_u(const char **s, size_t digits, unsigned *res);
-
-int parse_percent_unbounded(const char *p);
-int parse_percent(const char *p);
-
-int parse_nice(const char *p, int *ret);
diff --git a/src/basic/path-util.c b/src/basic/path-util.c
deleted file mode 100644
index fd38f51c4c..0000000000
--- a/src/basic/path-util.c
+++ /dev/null
@@ -1,897 +0,0 @@
-/***
- 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 <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-/* When we include libgen.h because we need dirname() we immediately
- * undefine basename() since libgen.h defines it as a macro to the
- * POSIX version which is really broken. We prefer GNU basename(). */
-#include <libgen.h>
-#undef basename
-
-#include "alloc-util.h"
-#include "extract-word.h"
-#include "fs-util.h"
-#include "glob-util.h"
-#include "log.h"
-#include "macro.h"
-#include "missing.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "stat-util.h"
-#include "string-util.h"
-#include "strv.h"
-#include "time-util.h"
-
-bool path_is_absolute(const char *p) {
- return p[0] == '/';
-}
-
-bool is_path(const char *p) {
- return !!strchr(p, '/');
-}
-
-int path_split_and_make_absolute(const char *p, char ***ret) {
- char **l;
- int r;
-
- assert(p);
- assert(ret);
-
- l = strv_split(p, ":");
- if (!l)
- return -ENOMEM;
-
- r = path_strv_make_absolute_cwd(l);
- if (r < 0) {
- strv_free(l);
- return r;
- }
-
- *ret = l;
- return r;
-}
-
-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);
-}
-
-int path_make_absolute_cwd(const char *p, char **ret) {
- char *c;
-
- assert(p);
- assert(ret);
-
- /* Similar to path_make_absolute(), but prefixes with the
- * current working directory. */
-
- if (path_is_absolute(p))
- c = strdup(p);
- else {
- _cleanup_free_ char *cwd = NULL;
-
- cwd = get_current_dir_name();
- if (!cwd)
- return negative_errno();
-
- c = strjoin(cwd, "/", p, NULL);
- }
- if (!c)
- return -ENOMEM;
-
- *ret = c;
- return 0;
-}
-
-int path_make_relative(const char *from_dir, const char *to_path, char **_r) {
- char *r, *p;
- unsigned n_parents;
-
- assert(from_dir);
- assert(to_path);
- assert(_r);
-
- /* Strips the common part, and adds ".." elements as necessary. */
-
- if (!path_is_absolute(from_dir))
- return -EINVAL;
-
- if (!path_is_absolute(to_path))
- return -EINVAL;
-
- /* Skip the common part. */
- for (;;) {
- size_t a;
- size_t b;
-
- from_dir += strspn(from_dir, "/");
- to_path += strspn(to_path, "/");
-
- if (!*from_dir) {
- if (!*to_path)
- /* from_dir equals to_path. */
- r = strdup(".");
- else
- /* from_dir is a parent directory of to_path. */
- r = strdup(to_path);
-
- if (!r)
- return -ENOMEM;
-
- path_kill_slashes(r);
-
- *_r = r;
- return 0;
- }
-
- if (!*to_path)
- break;
-
- a = strcspn(from_dir, "/");
- b = strcspn(to_path, "/");
-
- if (a != b)
- break;
-
- if (memcmp(from_dir, to_path, a) != 0)
- break;
-
- from_dir += a;
- to_path += b;
- }
-
- /* If we're here, then "from_dir" has one or more elements that need to
- * be replaced with "..". */
-
- /* Count the number of necessary ".." elements. */
- for (n_parents = 0;;) {
- from_dir += strspn(from_dir, "/");
-
- if (!*from_dir)
- break;
-
- from_dir += strcspn(from_dir, "/");
- n_parents++;
- }
-
- r = malloc(n_parents * 3 + strlen(to_path) + 1);
- if (!r)
- return -ENOMEM;
-
- for (p = r; n_parents > 0; n_parents--, p += 3)
- memcpy(p, "../", 3);
-
- strcpy(p, to_path);
- path_kill_slashes(r);
-
- *_r = r;
- return 0;
-}
-
-int path_strv_make_absolute_cwd(char **l) {
- char **s;
- int r;
-
- /* 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;
-
- r = path_make_absolute_cwd(*s, &t);
- if (r < 0)
- return r;
-
- free(*s);
- *s = t;
- }
-
- return 0;
-}
-
-char **path_strv_resolve(char **l, const char *prefix) {
- 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;
- _cleanup_free_ char *orig = NULL;
-
- if (!path_is_absolute(*s)) {
- free(*s);
- continue;
- }
-
- if (prefix) {
- orig = *s;
- t = strappend(prefix, orig);
- if (!t) {
- enomem = true;
- continue;
- }
- } else
- t = *s;
-
- errno = 0;
- u = canonicalize_file_name(t);
- if (!u) {
- if (errno == ENOENT) {
- if (prefix) {
- u = orig;
- orig = NULL;
- free(t);
- } else
- u = t;
- } else {
- free(t);
- if (errno == ENOMEM || errno == 0)
- enomem = true;
-
- continue;
- }
- } else if (prefix) {
- char *x;
-
- free(t);
- x = path_startswith(u, prefix);
- if (x) {
- /* restore the slash if it was lost */
- if (!startswith(x, "/"))
- *(--x) = '/';
-
- t = strdup(x);
- free(u);
- if (!t) {
- enomem = true;
- continue;
- }
- u = t;
- } else {
- /* canonicalized path goes outside of
- * prefix, keep the original path instead */
- free_and_replace(u, orig);
- }
- } else
- free(t);
-
- l[k++] = u;
- }
-
- l[k] = NULL;
-
- if (enomem)
- return NULL;
-
- return l;
-}
-
-char **path_strv_resolve_uniq(char **l, const char *prefix) {
-
- if (strv_isempty(l))
- return l;
-
- if (!path_strv_resolve(l, prefix))
- return NULL;
-
- return strv_uniq(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);
-
- /* Returns a pointer to the start of the first component after the parts matched by
- * the prefix, iff
- * - both paths are absolute or both paths are relative,
- * and
- * - each component in prefix in turn matches a component in path at the same position.
- * An empty string will be returned when the prefix and path are equivalent.
- *
- * Returns NULL otherwise.
- */
-
- 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;
- }
-}
-
-int path_compare(const char *a, const char *b) {
- int d;
-
- assert(a);
- assert(b);
-
- /* A relative path and an abolute path must not compare as equal.
- * Which one is sorted before the other does not really matter.
- * Here a relative path is ordered before an absolute path. */
- d = (a[0] == '/') - (b[0] == '/');
- if (d != 0)
- return d;
-
- for (;;) {
- size_t j, k;
-
- a += strspn(a, "/");
- b += strspn(b, "/");
-
- if (*a == 0 && *b == 0)
- return 0;
-
- /* Order prefixes first: "/foo" before "/foo/bar" */
- if (*a == 0)
- return -1;
- if (*b == 0)
- return 1;
-
- j = strcspn(a, "/");
- k = strcspn(b, "/");
-
- /* Alphabetical sort: "/foo/aaa" before "/foo/b" */
- d = memcmp(a, b, MIN(j, k));
- if (d != 0)
- return (d > 0) - (d < 0); /* sign of d */
-
- /* Sort "/foo/a" before "/foo/aaa" */
- d = (j > k) - (j < k); /* sign of (j - k) */
- if (d != 0)
- return d;
-
- a += j;
- b += k;
- }
-}
-
-bool path_equal(const char *a, const char *b) {
- return path_compare(a, b) == 0;
-}
-
-bool path_equal_or_files_same(const char *a, const char *b) {
- return path_equal(a, b) || files_same(a, b) > 0;
-}
-
-char* path_join(const char *root, const char *path, const char *rest) {
- assert(path);
-
- if (!isempty(root))
- return strjoin(root, endswith(root, "/") ? "" : "/",
- path[0] == '/' ? path+1 : path,
- rest ? (endswith(path, "/") ? "" : "/") : NULL,
- rest && rest[0] == '/' ? rest+1 : rest,
- NULL);
- else
- return strjoin(path,
- rest ? (endswith(path, "/") ? "" : "/") : NULL,
- rest && rest[0] == '/' ? rest+1 : rest,
- NULL);
-}
-
-int find_binary(const char *name, char **ret) {
- int last_error, r;
- const char *p;
-
- assert(name);
-
- if (is_path(name)) {
- if (access(name, X_OK) < 0)
- return -errno;
-
- if (ret) {
- r = path_make_absolute_cwd(name, ret);
- if (r < 0)
- return r;
- }
-
- return 0;
- }
-
- /**
- * Plain getenv, not secure_getenv, because we want
- * to actually allow the user to pick the binary.
- */
- p = getenv("PATH");
- if (!p)
- p = DEFAULT_PATH;
-
- last_error = -ENOENT;
-
- for (;;) {
- _cleanup_free_ char *j = NULL, *element = NULL;
-
- r = extract_first_word(&p, &element, ":", EXTRACT_RELAX|EXTRACT_DONT_COALESCE_SEPARATORS);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- if (!path_is_absolute(element))
- continue;
-
- j = strjoin(element, "/", name, NULL);
- if (!j)
- return -ENOMEM;
-
- if (access(j, X_OK) >= 0) {
- /* Found it! */
-
- if (ret) {
- *ret = path_kill_slashes(j);
- j = NULL;
- }
-
- return 0;
- }
-
- last_error = -errno;
- }
-
- return last_error;
-}
-
-bool paths_check_timestamp(const char* const* paths, usec_t *timestamp, bool update) {
- bool changed = false;
- const char* const* i;
-
- assert(timestamp);
-
- if (paths == NULL)
- return false;
-
- STRV_FOREACH(i, paths) {
- struct stat stats;
- usec_t u;
-
- if (stat(*i, &stats) < 0)
- continue;
-
- u = timespec_load(&stats.st_mtim);
-
- /* first check */
- if (*timestamp >= u)
- continue;
-
- log_debug("timestamp of '%s' changed", *i);
-
- /* update timestamp */
- if (update) {
- *timestamp = u;
- changed = true;
- } else
- return true;
- }
-
- return changed;
-}
-
-static int binary_is_good(const char *binary) {
- _cleanup_free_ char *p = NULL, *d = NULL;
- int r;
-
- r = find_binary(binary, &p);
- if (r == -ENOENT)
- return 0;
- if (r < 0)
- return r;
-
- /* An fsck that is linked to /bin/true is a non-existent
- * fsck */
-
- r = readlink_malloc(p, &d);
- if (r == -EINVAL) /* not a symlink */
- return 1;
- if (r < 0)
- return r;
-
- return !PATH_IN_SET(d, "true"
- "/bin/true",
- "/usr/bin/true",
- "/dev/null");
-}
-
-int fsck_exists(const char *fstype) {
- const char *checker;
-
- assert(fstype);
-
- if (streq(fstype, "auto"))
- return -EINVAL;
-
- checker = strjoina("fsck.", fstype);
- return binary_is_good(checker);
-}
-
-int mkfs_exists(const char *fstype) {
- const char *mkfs;
-
- assert(fstype);
-
- if (streq(fstype, "auto"))
- return -EINVAL;
-
- mkfs = strjoina("mkfs.", fstype);
- return binary_is_good(mkfs);
-}
-
-char *prefix_root(const char *root, const char *path) {
- char *n, *p;
- size_t l;
-
- /* If root is passed, prefixes path with it. Otherwise returns
- * it as is. */
-
- assert(path);
-
- /* First, drop duplicate prefixing slashes from the path */
- while (path[0] == '/' && path[1] == '/')
- path++;
-
- if (isempty(root) || path_equal(root, "/"))
- return strdup(path);
-
- l = strlen(root) + 1 + strlen(path) + 1;
-
- n = new(char, l);
- if (!n)
- return NULL;
-
- p = stpcpy(n, root);
-
- while (p > n && p[-1] == '/')
- p--;
-
- if (path[0] != '/')
- *(p++) = '/';
-
- strcpy(p, path);
- return n;
-}
-
-int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg) {
- char *p;
- int r;
-
- /*
- * This function is intended to be used in command line
- * parsers, to handle paths that are passed in. It makes the
- * path absolute, and reduces it to NULL if omitted or
- * root (the latter optionally).
- *
- * NOTE THAT THIS WILL FREE THE PREVIOUS ARGUMENT POINTER ON
- * SUCCESS! Hence, do not pass in uninitialized pointers.
- */
-
- if (isempty(path)) {
- *arg = mfree(*arg);
- return 0;
- }
-
- r = path_make_absolute_cwd(path, &p);
- if (r < 0)
- return log_error_errno(r, "Failed to parse path \"%s\" and make it absolute: %m", path);
-
- path_kill_slashes(p);
- if (suppress_root && path_equal(p, "/"))
- p = mfree(p);
-
- free(*arg);
- *arg = p;
- return 0;
-}
-
-char* dirname_malloc(const char *path) {
- char *d, *dir, *dir2;
-
- assert(path);
-
- d = strdup(path);
- if (!d)
- return NULL;
-
- dir = dirname(d);
- assert(dir);
-
- if (dir == d)
- return d;
-
- dir2 = strdup(dir);
- free(d);
-
- return dir2;
-}
-
-bool filename_is_valid(const char *p) {
- const char *e;
-
- if (isempty(p))
- return false;
-
- if (streq(p, "."))
- return false;
-
- if (streq(p, ".."))
- return false;
-
- e = strchrnul(p, '/');
- if (*e != 0)
- return false;
-
- if (e - p > FILENAME_MAX)
- return false;
-
- return true;
-}
-
-bool path_is_safe(const char *p) {
-
- if (isempty(p))
- return false;
-
- if (streq(p, "..") || startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
- return false;
-
- if (strlen(p)+1 > PATH_MAX)
- return false;
-
- /* The following two checks are not really dangerous, but hey, they still are confusing */
- if (streq(p, ".") || startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
- return false;
-
- if (strstr(p, "//"))
- return false;
-
- return true;
-}
-
-char *file_in_same_dir(const char *path, const char *filename) {
- char *e, *ret;
- 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);
-
- e = strrchr(path, '/');
- if (!e)
- return strdup(filename);
-
- k = strlen(filename);
- ret = new(char, (e + 1 - path) + k + 1);
- if (!ret)
- return NULL;
-
- memcpy(mempcpy(ret, path, e + 1 - path), filename, k + 1);
- return ret;
-}
-
-bool hidden_or_backup_file(const char *filename) {
- const char *p;
-
- assert(filename);
-
- if (filename[0] == '.' ||
- streq(filename, "lost+found") ||
- streq(filename, "aquota.user") ||
- streq(filename, "aquota.group") ||
- endswith(filename, "~"))
- return true;
-
- p = strrchr(filename, '.');
- if (!p)
- return false;
-
- /* Please, let's not add more entries to the list below. If external projects think it's a good idea to come up
- * with always new suffixes and that everybody else should just adjust to that, then it really should be on
- * them. Hence, in future, let's not add any more entries. Instead, let's ask those packages to instead adopt
- * one of the generic suffixes/prefixes for hidden files or backups, possibly augmented with an additional
- * string. Specifically: there's now:
- *
- * The generic suffixes "~" and ".bak" for backup files
- * The generic prefix "." for hidden files
- *
- * Thus, if a new package manager "foopkg" wants its own set of ".foopkg-new", ".foopkg-old", ".foopkg-dist"
- * or so registered, let's refuse that and ask them to use ".foopkg.new", ".foopkg.old" or ".foopkg~" instead.
- */
-
- return STR_IN_SET(p + 1,
- "rpmnew",
- "rpmsave",
- "rpmorig",
- "dpkg-old",
- "dpkg-new",
- "dpkg-tmp",
- "dpkg-dist",
- "dpkg-bak",
- "dpkg-backup",
- "dpkg-remove",
- "ucf-new",
- "ucf-old",
- "ucf-dist",
- "swp",
- "bak",
- "old",
- "new");
-}
-
-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/");
-}
-
-bool is_deviceallow_pattern(const char *path) {
- return path_startswith(path, "/dev/") ||
- startswith(path, "block-") ||
- startswith(path, "char-");
-}
-
-int systemd_installation_has_version(const char *root, unsigned minimal_version) {
- const char *pattern;
- int r;
-
- /* Try to guess if systemd installation is later than the specified version. This
- * is hacky and likely to yield false negatives, particularly if the installation
- * is non-standard. False positives should be relatively rare.
- */
-
- NULSTR_FOREACH(pattern,
- /* /lib works for systems without usr-merge, and for systems with a sane
- * usr-merge, where /lib is a symlink to /usr/lib. /usr/lib is necessary
- * for Gentoo which does a merge without making /lib a symlink.
- */
- "lib/systemd/libsystemd-shared-*.so\0"
- "usr/lib/systemd/libsystemd-shared-*.so\0") {
-
- _cleanup_strv_free_ char **names = NULL;
- _cleanup_free_ char *path = NULL;
- char *c, **name;
-
- path = prefix_root(root, pattern);
- if (!path)
- return -ENOMEM;
-
- r = glob_extend(&names, path);
- if (r == -ENOENT)
- continue;
- if (r < 0)
- return r;
-
- assert_se((c = endswith(path, "*.so")));
- *c = '\0'; /* truncate the glob part */
-
- STRV_FOREACH(name, names) {
- /* This is most likely to run only once, hence let's not optimize anything. */
- char *t, *t2;
- unsigned version;
-
- t = startswith(*name, path);
- if (!t)
- continue;
-
- t2 = endswith(t, ".so");
- if (!t2)
- continue;
-
- t2[0] = '\0'; /* truncate the suffix */
-
- r = safe_atou(t, &version);
- if (r < 0) {
- log_debug_errno(r, "Found libsystemd shared at \"%s.so\", but failed to parse version: %m", *name);
- continue;
- }
-
- log_debug("Found libsystemd shared at \"%s.so\", version %u (%s).",
- *name, version,
- version >= minimal_version ? "OK" : "too old");
- if (version >= minimal_version)
- return true;
- }
- }
-
- return false;
-}
diff --git a/src/basic/path-util.h b/src/basic/path-util.h
deleted file mode 100644
index 66545f52d9..0000000000
--- a/src/basic/path-util.h
+++ /dev/null
@@ -1,130 +0,0 @@
-#pragma once
-
-/***
- 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 <alloca.h>
-#include <stdbool.h>
-#include <stddef.h>
-
-#include "macro.h"
-#include "time-util.h"
-
-#define DEFAULT_PATH_NORMAL "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
-#define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":/sbin:/bin"
-
-#ifdef HAVE_SPLIT_USR
-# define DEFAULT_PATH DEFAULT_PATH_SPLIT_USR
-#else
-# define DEFAULT_PATH DEFAULT_PATH_NORMAL
-#endif
-
-bool is_path(const char *p) _pure_;
-int path_split_and_make_absolute(const char *p, char ***ret);
-bool path_is_absolute(const char *p) _pure_;
-char* path_make_absolute(const char *p, const char *prefix);
-int path_make_absolute_cwd(const char *p, char **ret);
-int path_make_relative(const char *from_dir, const char *to_path, char **_r);
-char* path_kill_slashes(char *path);
-char* path_startswith(const char *path, const char *prefix) _pure_;
-int path_compare(const char *a, const char *b) _pure_;
-bool path_equal(const char *a, const char *b) _pure_;
-bool path_equal_or_files_same(const char *a, const char *b);
-char* path_join(const char *root, const char *path, const char *rest);
-
-static inline bool path_equal_ptr(const char *a, const char *b) {
- return !!a == !!b && (!a || path_equal(a, b));
-}
-
-/* Note: the search terminates on the first NULL item. */
-#define PATH_IN_SET(p, ...) \
- ({ \
- char **s; \
- bool _found = false; \
- STRV_FOREACH(s, STRV_MAKE(__VA_ARGS__)) \
- if (path_equal(p, *s)) { \
- _found = true; \
- break; \
- } \
- _found; \
- })
-
-int path_strv_make_absolute_cwd(char **l);
-char** path_strv_resolve(char **l, const char *prefix);
-char** path_strv_resolve_uniq(char **l, const char *prefix);
-
-int find_binary(const char *name, char **filename);
-
-bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update);
-
-int fsck_exists(const char *fstype);
-int mkfs_exists(const char *fstype);
-
-/* Iterates through the path prefixes of the specified path, going up
- * the tree, to root. Also returns "" (and not "/"!) for the root
- * directory. Excludes the specified directory itself */
-#define PATH_FOREACH_PREFIX(prefix, path) \
- for (char *_slash = ({ path_kill_slashes(strcpy(prefix, path)); streq(prefix, "/") ? NULL : strrchr(prefix, '/'); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
-
-/* Same as PATH_FOREACH_PREFIX but also includes the specified path itself */
-#define PATH_FOREACH_PREFIX_MORE(prefix, path) \
- for (char *_slash = ({ path_kill_slashes(strcpy(prefix, path)); if (streq(prefix, "/")) prefix[0] = 0; strrchr(prefix, 0); }); _slash && ((*_slash = 0), true); _slash = strrchr((prefix), '/'))
-
-char *prefix_root(const char *root, const char *path);
-
-/* Similar to prefix_root(), but returns an alloca() buffer, or
- * possibly a const pointer into the path parameter */
-#define prefix_roota(root, path) \
- ({ \
- const char* _path = (path), *_root = (root), *_ret; \
- char *_p, *_n; \
- size_t _l; \
- while (_path[0] == '/' && _path[1] == '/') \
- _path ++; \
- if (isempty(_root) || path_equal(_root, "/")) \
- _ret = _path; \
- else { \
- _l = strlen(_root) + 1 + strlen(_path) + 1; \
- _n = alloca(_l); \
- _p = stpcpy(_n, _root); \
- while (_p > _n && _p[-1] == '/') \
- _p--; \
- if (_path[0] != '/') \
- *(_p++) = '/'; \
- strcpy(_p, _path); \
- _ret = _n; \
- } \
- _ret; \
- })
-
-int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg);
-
-char* dirname_malloc(const char *path);
-
-bool filename_is_valid(const char *p) _pure_;
-bool path_is_safe(const char *p) _pure_;
-
-char *file_in_same_dir(const char *path, const char *filename);
-
-bool hidden_or_backup_file(const char *filename) _pure_;
-
-bool is_device_path(const char *path);
-bool is_deviceallow_pattern(const char *path);
-
-int systemd_installation_has_version(const char *root, unsigned minimal_version);
diff --git a/src/basic/prioq.c b/src/basic/prioq.c
deleted file mode 100644
index 4570b8e4ba..0000000000
--- a/src/basic/prioq.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 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/>.
-***/
-
-/*
- * Priority Queue
- * The prioq object implements a priority queue. That is, it orders objects by
- * their priority and allows O(1) access to the object with the highest
- * priority. Insertion and removal are Θ(log n). Optionally, the caller can
- * provide a pointer to an index which will be kept up-to-date by the prioq.
- *
- * The underlying algorithm used in this implementation is a Heap.
- */
-
-#include <errno.h>
-#include <stdlib.h>
-
-#include "alloc-util.h"
-#include "hashmap.h"
-#include "prioq.h"
-
-struct prioq_item {
- void *data;
- unsigned *idx;
-};
-
-struct Prioq {
- compare_func_t compare_func;
- unsigned n_items, n_allocated;
-
- struct prioq_item *items;
-};
-
-Prioq *prioq_new(compare_func_t compare_func) {
- Prioq *q;
-
- q = new0(Prioq, 1);
- if (!q)
- return q;
-
- q->compare_func = compare_func;
- return q;
-}
-
-Prioq* prioq_free(Prioq *q) {
- if (!q)
- return NULL;
-
- free(q->items);
- return mfree(q);
-}
-
-int prioq_ensure_allocated(Prioq **q, compare_func_t compare_func) {
- assert(q);
-
- if (*q)
- return 0;
-
- *q = prioq_new(compare_func);
- if (!*q)
- return -ENOMEM;
-
- return 0;
-}
-
-static void swap(Prioq *q, unsigned j, unsigned k) {
- void *saved_data;
- unsigned *saved_idx;
-
- assert(q);
- assert(j < q->n_items);
- assert(k < q->n_items);
-
- assert(!q->items[j].idx || *(q->items[j].idx) == j);
- assert(!q->items[k].idx || *(q->items[k].idx) == k);
-
- saved_data = q->items[j].data;
- saved_idx = q->items[j].idx;
- q->items[j].data = q->items[k].data;
- q->items[j].idx = q->items[k].idx;
- q->items[k].data = saved_data;
- q->items[k].idx = saved_idx;
-
- if (q->items[j].idx)
- *q->items[j].idx = j;
-
- if (q->items[k].idx)
- *q->items[k].idx = k;
-}
-
-static unsigned shuffle_up(Prioq *q, unsigned idx) {
- assert(q);
-
- while (idx > 0) {
- unsigned k;
-
- k = (idx-1)/2;
-
- if (q->compare_func(q->items[k].data, q->items[idx].data) <= 0)
- break;
-
- swap(q, idx, k);
- idx = k;
- }
-
- return idx;
-}
-
-static unsigned shuffle_down(Prioq *q, unsigned idx) {
- assert(q);
-
- for (;;) {
- unsigned j, k, s;
-
- k = (idx+1)*2; /* right child */
- j = k-1; /* left child */
-
- if (j >= q->n_items)
- break;
-
- if (q->compare_func(q->items[j].data, q->items[idx].data) < 0)
-
- /* So our left child is smaller than we are, let's
- * remember this fact */
- s = j;
- else
- s = idx;
-
- if (k < q->n_items &&
- q->compare_func(q->items[k].data, q->items[s].data) < 0)
-
- /* So our right child is smaller than we are, let's
- * remember this fact */
- s = k;
-
- /* s now points to the smallest of the three items */
-
- if (s == idx)
- /* No swap necessary, we're done */
- break;
-
- swap(q, idx, s);
- idx = s;
- }
-
- return idx;
-}
-
-int prioq_put(Prioq *q, void *data, unsigned *idx) {
- struct prioq_item *i;
- unsigned k;
-
- assert(q);
-
- if (q->n_items >= q->n_allocated) {
- unsigned n;
- struct prioq_item *j;
-
- n = MAX((q->n_items+1) * 2, 16u);
- j = realloc(q->items, sizeof(struct prioq_item) * n);
- if (!j)
- return -ENOMEM;
-
- q->items = j;
- q->n_allocated = n;
- }
-
- k = q->n_items++;
- i = q->items + k;
- i->data = data;
- i->idx = idx;
-
- if (idx)
- *idx = k;
-
- shuffle_up(q, k);
-
- return 0;
-}
-
-static void remove_item(Prioq *q, struct prioq_item *i) {
- struct prioq_item *l;
-
- assert(q);
- assert(i);
-
- l = q->items + q->n_items - 1;
-
- if (i == l)
- /* Last entry, let's just remove it */
- q->n_items--;
- else {
- unsigned k;
-
- /* Not last entry, let's replace the last entry with
- * this one, and reshuffle */
-
- k = i - q->items;
-
- i->data = l->data;
- i->idx = l->idx;
- if (i->idx)
- *i->idx = k;
- q->n_items--;
-
- k = shuffle_down(q, k);
- shuffle_up(q, k);
- }
-}
-
-_pure_ static struct prioq_item* find_item(Prioq *q, void *data, unsigned *idx) {
- struct prioq_item *i;
-
- assert(q);
-
- if (idx) {
- if (*idx == PRIOQ_IDX_NULL ||
- *idx > q->n_items)
- return NULL;
-
- i = q->items + *idx;
- if (i->data != data)
- return NULL;
-
- return i;
- } else {
- for (i = q->items; i < q->items + q->n_items; i++)
- if (i->data == data)
- return i;
- return NULL;
- }
-}
-
-int prioq_remove(Prioq *q, void *data, unsigned *idx) {
- struct prioq_item *i;
-
- if (!q)
- return 0;
-
- i = find_item(q, data, idx);
- if (!i)
- return 0;
-
- remove_item(q, i);
- return 1;
-}
-
-int prioq_reshuffle(Prioq *q, void *data, unsigned *idx) {
- struct prioq_item *i;
- unsigned k;
-
- assert(q);
-
- i = find_item(q, data, idx);
- if (!i)
- return 0;
-
- k = i - q->items;
- k = shuffle_down(q, k);
- shuffle_up(q, k);
- return 1;
-}
-
-void *prioq_peek(Prioq *q) {
-
- if (!q)
- return NULL;
-
- if (q->n_items <= 0)
- return NULL;
-
- return q->items[0].data;
-}
-
-void *prioq_pop(Prioq *q) {
- void *data;
-
- if (!q)
- return NULL;
-
- if (q->n_items <= 0)
- return NULL;
-
- data = q->items[0].data;
- remove_item(q, q->items);
- return data;
-}
-
-unsigned prioq_size(Prioq *q) {
-
- if (!q)
- return 0;
-
- return q->n_items;
-}
-
-bool prioq_isempty(Prioq *q) {
-
- if (!q)
- return true;
-
- return q->n_items <= 0;
-}
diff --git a/src/basic/prioq.h b/src/basic/prioq.h
deleted file mode 100644
index 113c73d040..0000000000
--- a/src/basic/prioq.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 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 "hashmap.h"
-#include "macro.h"
-
-typedef struct Prioq Prioq;
-
-#define PRIOQ_IDX_NULL ((unsigned) -1)
-
-Prioq *prioq_new(compare_func_t compare);
-Prioq *prioq_free(Prioq *q);
-int prioq_ensure_allocated(Prioq **q, compare_func_t compare_func);
-
-int prioq_put(Prioq *q, void *data, unsigned *idx);
-int prioq_remove(Prioq *q, void *data, unsigned *idx);
-int prioq_reshuffle(Prioq *q, void *data, unsigned *idx);
-
-void *prioq_peek(Prioq *q) _pure_;
-void *prioq_pop(Prioq *q);
-
-unsigned prioq_size(Prioq *q) _pure_;
-bool prioq_isempty(Prioq *q) _pure_;
diff --git a/src/basic/proc-cmdline.c b/src/basic/proc-cmdline.c
deleted file mode 100644
index 8297a222b7..0000000000
--- a/src/basic/proc-cmdline.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/***
- 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 <stddef.h>
-#include <string.h>
-
-#include "alloc-util.h"
-#include "extract-word.h"
-#include "fileio.h"
-#include "macro.h"
-#include "parse-util.h"
-#include "proc-cmdline.h"
-#include "process-util.h"
-#include "special.h"
-#include "string-util.h"
-#include "util.h"
-#include "virt.h"
-
-int proc_cmdline(char **ret) {
- assert(ret);
-
- if (detect_container() > 0)
- return get_process_cmdline(1, 0, false, ret);
- else
- return read_one_line_file("/proc/cmdline", ret);
-}
-
-int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value, void *data),
- void *data,
- bool strip_prefix) {
- _cleanup_free_ char *line = NULL;
- const char *p;
- int r;
-
- assert(parse_item);
-
- r = proc_cmdline(&line);
- if (r < 0)
- return r;
-
- p = line;
- for (;;) {
- _cleanup_free_ char *word = NULL;
- char *value = NULL, *unprefixed;
-
- r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- /* Filter out arguments that are intended only for the
- * initrd */
- unprefixed = startswith(word, "rd.");
- if (unprefixed && !in_initrd())
- continue;
-
- value = strchr(word, '=');
- if (value)
- *(value++) = 0;
-
- r = parse_item(strip_prefix && unprefixed ? unprefixed : word, value, data);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-int get_proc_cmdline_key(const char *key, char **value) {
- _cleanup_free_ char *line = NULL, *ret = NULL;
- bool found = false;
- const char *p;
- int r;
-
- assert(key);
-
- r = proc_cmdline(&line);
- if (r < 0)
- return r;
-
- p = line;
- for (;;) {
- _cleanup_free_ char *word = NULL;
- const char *e;
-
- r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- /* Filter out arguments that are intended only for the
- * initrd */
- if (!in_initrd() && startswith(word, "rd."))
- continue;
-
- if (value) {
- e = startswith(word, key);
- if (!e)
- continue;
-
- r = free_and_strdup(&ret, e);
- if (r < 0)
- return r;
-
- found = true;
- } else {
- if (streq(word, key))
- found = true;
- }
- }
-
- if (value) {
- *value = ret;
- ret = NULL;
- }
-
- return found;
-
-}
-
-int shall_restore_state(void) {
- _cleanup_free_ char *value = NULL;
- int r;
-
- r = get_proc_cmdline_key("systemd.restore_state=", &value);
- if (r < 0)
- return r;
- if (r == 0)
- return true;
-
- return parse_boolean(value);
-}
-
-static const char * const rlmap[] = {
- "emergency", SPECIAL_EMERGENCY_TARGET,
- "-b", SPECIAL_EMERGENCY_TARGET,
- "rescue", SPECIAL_RESCUE_TARGET,
- "single", SPECIAL_RESCUE_TARGET,
- "-s", SPECIAL_RESCUE_TARGET,
- "s", SPECIAL_RESCUE_TARGET,
- "S", SPECIAL_RESCUE_TARGET,
- "1", SPECIAL_RESCUE_TARGET,
- "2", SPECIAL_MULTI_USER_TARGET,
- "3", SPECIAL_MULTI_USER_TARGET,
- "4", SPECIAL_MULTI_USER_TARGET,
- "5", SPECIAL_GRAPHICAL_TARGET,
- NULL
-};
-
-static const char * const rlmap_initrd[] = {
- "emergency", SPECIAL_EMERGENCY_TARGET,
- "rescue", SPECIAL_RESCUE_TARGET,
- NULL
-};
-
-const char* runlevel_to_target(const char *word) {
- size_t i;
- const char * const *rlmap_ptr = in_initrd() ? rlmap_initrd
- : rlmap;
-
- if (!word)
- return NULL;
-
- if (in_initrd() && (word = startswith(word, "rd.")) == NULL)
- return NULL;
-
- for (i = 0; rlmap_ptr[i] != NULL; i += 2)
- if (streq(word, rlmap_ptr[i]))
- return rlmap_ptr[i+1];
-
- return NULL;
-}
diff --git a/src/basic/proc-cmdline.h b/src/basic/proc-cmdline.h
deleted file mode 100644
index 6d6ee95c11..0000000000
--- a/src/basic/proc-cmdline.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#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/>.
-***/
-
-int proc_cmdline(char **ret);
-int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value, void *data),
- void *data,
- bool strip_prefix);
-int get_proc_cmdline_key(const char *parameter, char **value);
-
-int shall_restore_state(void);
-const char* runlevel_to_target(const char *rl);
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
deleted file mode 100644
index 54b644ad56..0000000000
--- a/src/basic/process-util.c
+++ /dev/null
@@ -1,860 +0,0 @@
-/***
- 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 <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <linux/oom.h>
-#include <sched.h>
-#include <signal.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/personality.h>
-#include <sys/prctl.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <syslog.h>
-#include <unistd.h>
-#ifdef HAVE_VALGRIND_VALGRIND_H
-#include <valgrind/valgrind.h>
-#endif
-
-#include "alloc-util.h"
-#include "architecture.h"
-#include "escape.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "fs-util.h"
-#include "ioprio.h"
-#include "log.h"
-#include "macro.h"
-#include "missing.h"
-#include "process-util.h"
-#include "raw-clone.h"
-#include "signal-util.h"
-#include "stat-util.h"
-#include "string-table.h"
-#include "string-util.h"
-#include "user-util.h"
-#include "util.h"
-
-int get_process_state(pid_t pid) {
- const char *p;
- char state;
- int r;
- _cleanup_free_ char *line = NULL;
-
- assert(pid >= 0);
-
- p = procfs_file_alloca(pid, "stat");
-
- r = read_one_line_file(p, &line);
- if (r == -ENOENT)
- return -ESRCH;
- if (r < 0)
- return r;
-
- p = strrchr(line, ')');
- if (!p)
- return -EIO;
-
- p++;
-
- if (sscanf(p, " %c", &state) != 1)
- return -EIO;
-
- return (unsigned char) state;
-}
-
-int get_process_comm(pid_t pid, char **name) {
- const char *p;
- int r;
-
- assert(name);
- assert(pid >= 0);
-
- p = procfs_file_alloca(pid, "comm");
-
- r = read_one_line_file(p, name);
- if (r == -ENOENT)
- return -ESRCH;
-
- return r;
-}
-
-int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
- _cleanup_fclose_ FILE *f = NULL;
- bool space = false;
- char *r = NULL, *k;
- const char *p;
- int c;
-
- assert(line);
- assert(pid >= 0);
-
- /* Retrieves a process' command line. Replaces unprintable characters while doing so by whitespace (coalescing
- * multiple sequential ones into one). If max_length is != 0 will return a string of the specified size at most
- * (the trailing NUL byte does count towards the length here!), abbreviated with a "..." ellipsis. If
- * comm_fallback is true and the process has no command line set (the case for kernel threads), or has a
- * command line that resolves to the empty string will return the "comm" name of the process instead.
- *
- * Returns -ESRCH if the process doesn't exist, and -ENOENT if the process has no command line (and
- * comm_fallback is false). */
-
- p = procfs_file_alloca(pid, "cmdline");
-
- f = fopen(p, "re");
- if (!f) {
- if (errno == ENOENT)
- return -ESRCH;
- return -errno;
- }
-
- if (max_length == 1) {
-
- /* If there's only room for one byte, return the empty string */
- r = new0(char, 1);
- if (!r)
- return -ENOMEM;
-
- *line = r;
- return 0;
-
- } else if (max_length == 0) {
- size_t len = 0, allocated = 0;
-
- while ((c = getc(f)) != EOF) {
-
- if (!GREEDY_REALLOC(r, allocated, len+3)) {
- free(r);
- return -ENOMEM;
- }
-
- if (isprint(c)) {
- if (space) {
- r[len++] = ' ';
- space = false;
- }
-
- r[len++] = c;
- } else if (len > 0)
- space = true;
- }
-
- if (len > 0)
- r[len] = 0;
- else
- r = mfree(r);
-
- } else {
- bool dotdotdot = false;
- size_t left;
-
- r = new(char, max_length);
- if (!r)
- return -ENOMEM;
-
- k = r;
- left = max_length;
- while ((c = getc(f)) != EOF) {
-
- if (isprint(c)) {
-
- if (space) {
- if (left <= 2) {
- dotdotdot = true;
- break;
- }
-
- *(k++) = ' ';
- left--;
- space = false;
- }
-
- if (left <= 1) {
- dotdotdot = true;
- break;
- }
-
- *(k++) = (char) c;
- left--;
- } else if (k > r)
- space = true;
- }
-
- if (dotdotdot) {
- if (max_length <= 4) {
- k = r;
- left = max_length;
- } else {
- k = r + max_length - 4;
- left = 4;
-
- /* Eat up final spaces */
- while (k > r && isspace(k[-1])) {
- k--;
- left++;
- }
- }
-
- strncpy(k, "...", left-1);
- k[left-1] = 0;
- } else
- *k = 0;
- }
-
- /* Kernel threads have no argv[] */
- if (isempty(r)) {
- _cleanup_free_ char *t = NULL;
- int h;
-
- free(r);
-
- if (!comm_fallback)
- return -ENOENT;
-
- h = get_process_comm(pid, &t);
- if (h < 0)
- return h;
-
- if (max_length == 0)
- r = strjoin("[", t, "]", NULL);
- else {
- size_t l;
-
- l = strlen(t);
-
- if (l + 3 <= max_length)
- r = strjoin("[", t, "]", NULL);
- else if (max_length <= 6) {
-
- r = new(char, max_length);
- if (!r)
- return -ENOMEM;
-
- memcpy(r, "[...]", max_length-1);
- r[max_length-1] = 0;
- } else {
- char *e;
-
- t[max_length - 6] = 0;
-
- /* Chop off final spaces */
- e = strchr(t, 0);
- while (e > t && isspace(e[-1]))
- e--;
- *e = 0;
-
- r = strjoin("[", t, "...]", NULL);
- }
- }
- if (!r)
- return -ENOMEM;
- }
-
- *line = r;
- return 0;
-}
-
-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 */
-
- (void) 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;
-
- memzero(saved_argv[i], strlen(saved_argv[i]));
- }
- }
-}
-
-int is_kernel_thread(pid_t pid) {
- const char *p;
- size_t count;
- char c;
- bool eof;
- FILE *f;
-
- if (pid == 0 || pid == 1) /* pid 1, and we ourselves certainly aren't a kernel thread */
- return 0;
-
- assert(pid > 1);
-
- p = procfs_file_alloca(pid, "cmdline");
- f = fopen(p, "re");
- if (!f) {
- if (errno == ENOENT)
- return -ESRCH;
- 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_capeff(pid_t pid, char **capeff) {
- const char *p;
- int r;
-
- assert(capeff);
- assert(pid >= 0);
-
- p = procfs_file_alloca(pid, "status");
-
- r = get_proc_field(p, "CapEff", WHITESPACE, capeff);
- if (r == -ENOENT)
- return -ESRCH;
-
- return r;
-}
-
-static int get_process_link_contents(const char *proc_file, char **name) {
- int r;
-
- assert(proc_file);
- assert(name);
-
- r = readlink_malloc(proc_file, name);
- if (r == -ENOENT)
- return -ESRCH;
- if (r < 0)
- return r;
-
- return 0;
-}
-
-int get_process_exe(pid_t pid, char **name) {
- const char *p;
- char *d;
- int r;
-
- assert(pid >= 0);
-
- p = procfs_file_alloca(pid, "exe");
- r = get_process_link_contents(p, name);
- if (r < 0)
- return r;
-
- d = endswith(*name, " (deleted)");
- if (d)
- *d = '\0';
-
- return 0;
-}
-
-static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
- _cleanup_fclose_ FILE *f = NULL;
- char line[LINE_MAX];
- const char *p;
-
- assert(field);
- assert(uid);
-
- p = procfs_file_alloca(pid, "status");
- f = fopen(p, "re");
- if (!f) {
- if (errno == ENOENT)
- return -ESRCH;
- return -errno;
- }
-
- FOREACH_LINE(line, f, return -errno) {
- char *l;
-
- l = strstrip(line);
-
- if (startswith(l, field)) {
- l += strlen(field);
- l += strspn(l, WHITESPACE);
-
- l[strcspn(l, WHITESPACE)] = 0;
-
- return parse_uid(l, uid);
- }
- }
-
- return -EIO;
-}
-
-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) {
- assert_cc(sizeof(uid_t) == sizeof(gid_t));
- return get_process_id(pid, "Gid:", gid);
-}
-
-int get_process_cwd(pid_t pid, char **cwd) {
- const char *p;
-
- assert(pid >= 0);
-
- p = procfs_file_alloca(pid, "cwd");
-
- return get_process_link_contents(p, cwd);
-}
-
-int get_process_root(pid_t pid, char **root) {
- const char *p;
-
- assert(pid >= 0);
-
- p = procfs_file_alloca(pid, "root");
-
- return get_process_link_contents(p, root);
-}
-
-int get_process_environ(pid_t pid, char **env) {
- _cleanup_fclose_ FILE *f = NULL;
- _cleanup_free_ char *outcome = NULL;
- int c;
- const char *p;
- size_t allocated = 0, sz = 0;
-
- assert(pid >= 0);
- assert(env);
-
- p = procfs_file_alloca(pid, "environ");
-
- f = fopen(p, "re");
- if (!f) {
- if (errno == ENOENT)
- return -ESRCH;
- return -errno;
- }
-
- while ((c = fgetc(f)) != EOF) {
- if (!GREEDY_REALLOC(outcome, allocated, sz + 5))
- return -ENOMEM;
-
- if (c == '\0')
- outcome[sz++] = '\n';
- else
- sz += cescape_char(c, outcome + sz);
- }
-
- if (!outcome) {
- outcome = strdup("");
- if (!outcome)
- return -ENOMEM;
- } else
- outcome[sz] = '\0';
-
- *env = outcome;
- outcome = NULL;
-
- return 0;
-}
-
-int get_process_ppid(pid_t pid, pid_t *_ppid) {
- int r;
- _cleanup_free_ char *line = NULL;
- long unsigned ppid;
- const char *p;
-
- assert(pid >= 0);
- assert(_ppid);
-
- if (pid == 0) {
- *_ppid = getppid();
- return 0;
- }
-
- p = procfs_file_alloca(pid, "stat");
- r = read_one_line_file(p, &line);
- if (r == -ENOENT)
- return -ESRCH;
- if (r < 0)
- 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 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 negative_errno();
- }
-
- return 0;
- }
-}
-
-/*
- * Return values:
- * < 0 : wait_for_terminate() failed to get the state of the
- * process, the process was terminated by a signal, or
- * failed for an unknown reason.
- * >=0 : The process terminated normally, and its exit code is
- * returned.
- *
- * That is, success is indicated by a return value of zero, and an
- * error is indicated by a non-zero value.
- *
- * A warning is emitted if the process terminates abnormally,
- * and also if it returns non-zero unless check_exit_code is true.
- */
-int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code) {
- int r;
- siginfo_t status;
-
- assert(name);
- assert(pid > 1);
-
- r = wait_for_terminate(pid, &status);
- if (r < 0)
- return log_warning_errno(r, "Failed to wait for %s: %m", name);
-
- if (status.si_code == CLD_EXITED) {
- if (status.si_status != 0)
- log_full(check_exit_code ? LOG_WARNING : LOG_DEBUG,
- "%s failed with error code %i.", name, status.si_status);
- else
- log_debug("%s succeeded.", name);
-
- return status.si_status;
- } 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;
-}
-
-void sigkill_wait(pid_t pid) {
- assert(pid > 1);
-
- if (kill(pid, SIGKILL) > 0)
- (void) wait_for_terminate(pid, NULL);
-}
-
-void sigkill_waitp(pid_t *pid) {
- if (!pid)
- return;
- if (*pid <= 1)
- return;
-
- sigkill_wait(*pid);
-}
-
-int kill_and_sigcont(pid_t pid, int sig) {
- int r;
-
- r = kill(pid, sig) < 0 ? -errno : 0;
-
- /* If this worked, also send SIGCONT, unless we already just sent a SIGCONT, or SIGKILL was sent which isn't
- * affected by a process being suspended anyway. */
- if (r >= 0 && !IN_SET(SIGCONT, SIGKILL))
- (void) kill(pid, SIGCONT);
-
- return r;
-}
-
-int getenv_for_pid(pid_t pid, const char *field, char **_value) {
- _cleanup_fclose_ FILE *f = NULL;
- char *value = NULL;
- int r;
- bool done = false;
- size_t l;
- const char *path;
-
- assert(pid >= 0);
- assert(field);
- assert(_value);
-
- path = procfs_file_alloca(pid, "environ");
-
- f = fopen(path, "re");
- if (!f) {
- if (errno == ENOENT)
- return -ESRCH;
- 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)
- return -ENOMEM;
-
- r = 1;
- break;
- }
-
- } while (!done);
-
- *_value = value;
- return r;
-}
-
-bool pid_is_unwaited(pid_t pid) {
- /* Checks whether a PID is still valid at all, including a zombie */
-
- if (pid < 0)
- return false;
-
- if (pid <= 1) /* If we or PID 1 would be dead and have been waited for, this code would not be running */
- return true;
-
- if (kill(pid, 0) >= 0)
- return true;
-
- return errno != ESRCH;
-}
-
-bool pid_is_alive(pid_t pid) {
- int r;
-
- /* Checks whether a PID is still valid and not a zombie */
-
- if (pid < 0)
- return false;
-
- if (pid <= 1) /* If we or PID 1 would be a zombie, this code would not be running */
- return true;
-
- r = get_process_state(pid);
- if (r == -ESRCH || r == 'Z')
- return false;
-
- return true;
-}
-
-int pid_from_same_root_fs(pid_t pid) {
- const char *root;
-
- if (pid < 0)
- return 0;
-
- root = procfs_file_alloca(pid, "root");
-
- return files_same(root, "/proc/1/root");
-}
-
-bool is_main_thread(void) {
- static thread_local int cached = 0;
-
- if (_unlikely_(cached == 0))
- cached = getpid() == gettid() ? 1 : -1;
-
- return cached > 0;
-}
-
-noreturn void freeze(void) {
-
- log_close();
-
- /* Make sure nobody waits for us on a socket anymore */
- close_all_fds(NULL, 0);
-
- sync();
-
- for (;;)
- pause();
-}
-
-bool oom_score_adjust_is_valid(int oa) {
- return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
-}
-
-unsigned long personality_from_string(const char *p) {
- int architecture;
-
- if (!p)
- return PERSONALITY_INVALID;
-
- /* Parse a personality specifier. We use our own identifiers that indicate specific ABIs, rather than just
- * hints regarding the register size, since we want to keep things open for multiple locally supported ABIs for
- * the same register size. */
-
- architecture = architecture_from_string(p);
- if (architecture < 0)
- return PERSONALITY_INVALID;
-
- if (architecture == native_architecture())
- return PER_LINUX;
-#ifdef SECONDARY_ARCHITECTURE
- if (architecture == SECONDARY_ARCHITECTURE)
- return PER_LINUX32;
-#endif
-
- return PERSONALITY_INVALID;
-}
-
-const char* personality_to_string(unsigned long p) {
- int architecture = _ARCHITECTURE_INVALID;
-
- if (p == PER_LINUX)
- architecture = native_architecture();
-#ifdef SECONDARY_ARCHITECTURE
- else if (p == PER_LINUX32)
- architecture = SECONDARY_ARCHITECTURE;
-#endif
-
- if (architecture < 0)
- return NULL;
-
- return architecture_to_string(architecture);
-}
-
-void valgrind_summary_hack(void) {
-#ifdef HAVE_VALGRIND_VALGRIND_H
- if (getpid() == 1 && RUNNING_ON_VALGRIND) {
- pid_t pid;
- pid = raw_clone(SIGCHLD);
- if (pid < 0)
- log_emergency_errno(errno, "Failed to fork off valgrind helper: %m");
- else if (pid == 0)
- exit(EXIT_SUCCESS);
- else {
- log_info("Spawned valgrind helper as PID "PID_FMT".", pid);
- (void) wait_for_terminate(pid, NULL);
- }
- }
-#endif
-}
-
-int pid_compare_func(const void *a, const void *b) {
- const pid_t *p = a, *q = b;
-
- /* Suitable for usage in qsort() */
-
- if (*p < *q)
- return -1;
- if (*p > *q)
- return 1;
- return 0;
-}
-
-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 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);
diff --git a/src/basic/process-util.h b/src/basic/process-util.h
deleted file mode 100644
index 2568e3834f..0000000000
--- a/src/basic/process-util.h
+++ /dev/null
@@ -1,110 +0,0 @@
-#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 <alloca.h>
-#include <signal.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/resource.h>
-
-#include "formats-util.h"
-#include "macro.h"
-
-#define procfs_file_alloca(pid, field) \
- ({ \
- pid_t _pid_ = (pid); \
- const char *_r_; \
- if (_pid_ == 0) { \
- _r_ = ("/proc/self/" field); \
- } else { \
- _r_ = alloca(strlen("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
- sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \
- } \
- _r_; \
- })
-
-int get_process_state(pid_t pid);
-int get_process_comm(pid_t pid, char **name);
-int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line);
-int get_process_exe(pid_t pid, char **name);
-int get_process_uid(pid_t pid, uid_t *uid);
-int get_process_gid(pid_t pid, gid_t *gid);
-int get_process_capeff(pid_t pid, char **capeff);
-int get_process_cwd(pid_t pid, char **cwd);
-int get_process_root(pid_t pid, char **root);
-int get_process_environ(pid_t pid, char **environ);
-int get_process_ppid(pid_t pid, pid_t *ppid);
-
-int wait_for_terminate(pid_t pid, siginfo_t *status);
-int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code);
-
-void sigkill_wait(pid_t pid);
-void sigkill_waitp(pid_t *pid);
-
-int kill_and_sigcont(pid_t pid, int sig);
-
-void rename_process(const char name[8]);
-int is_kernel_thread(pid_t pid);
-
-int getenv_for_pid(pid_t pid, const char *field, char **_value);
-
-bool pid_is_alive(pid_t pid);
-bool pid_is_unwaited(pid_t pid);
-int pid_from_same_root_fs(pid_t pid);
-
-bool is_main_thread(void);
-
-noreturn void freeze(void);
-
-bool oom_score_adjust_is_valid(int oa);
-
-#ifndef PERSONALITY_INVALID
-/* personality(7) documents that 0xffffffffUL is used for querying the
- * current personality, hence let's use that here as error
- * indicator. */
-#define PERSONALITY_INVALID 0xffffffffLU
-#endif
-
-unsigned long personality_from_string(const char *p);
-const char *personality_to_string(unsigned long);
-
-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) _const_;
-int sigchld_code_from_string(const char *s) _pure_;
-
-int sched_policy_to_string_alloc(int i, char **s);
-int sched_policy_from_string(const char *s);
-
-#define PTR_TO_PID(p) ((pid_t) ((uintptr_t) p))
-#define PID_TO_PTR(p) ((void*) ((uintptr_t) p))
-
-void valgrind_summary_hack(void);
-
-int pid_compare_func(const void *a, const void *b);
-
-static inline bool nice_is_valid(int n) {
- return n >= PRIO_MIN && n < PRIO_MAX;
-}
diff --git a/src/basic/random-util.c b/src/basic/random-util.c
deleted file mode 100644
index ad7b3eedf2..0000000000
--- a/src/basic/random-util.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/***
- 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 <elf.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include <linux/random.h>
-#include <stdint.h>
-
-#ifdef HAVE_SYS_AUXV_H
-#include <sys/auxv.h>
-#endif
-
-#include "fd-util.h"
-#include "io-util.h"
-#include "missing.h"
-#include "random-util.h"
-#include "time-util.h"
-
-int dev_urandom(void *p, size_t n) {
- static int have_syscall = -1;
-
- _cleanup_close_ int fd = -1;
- int r;
-
- /* Gathers some randomness from the kernel. This call will
- * never block, and will always return some data from the
- * kernel, regardless if the random pool is fully initialized
- * or not. It thus makes no guarantee for the quality of the
- * returned entropy, but is good enough for our usual usecases
- * of seeding the hash functions for hashtable */
-
- /* Use the getrandom() syscall unless we know we don't have
- * it, or when the requested size is too large for it. */
- if (have_syscall != 0 || (size_t) (int) n != n) {
- r = getrandom(p, n, GRND_NONBLOCK);
- if (r == (int) n) {
- have_syscall = true;
- return 0;
- }
-
- if (r < 0) {
- if (errno == ENOSYS)
- /* we lack the syscall, continue with
- * reading from /dev/urandom */
- have_syscall = false;
- else if (errno == EAGAIN)
- /* not enough entropy for now. Let's
- * remember to use the syscall the
- * next time, again, but also read
- * from /dev/urandom for now, which
- * doesn't care about the current
- * amount of entropy. */
- have_syscall = true;
- else
- return -errno;
- } else
- /* too short read? */
- return -ENODATA;
- }
-
- fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0)
- return errno == ENOENT ? -ENOSYS : -errno;
-
- return loop_read_exact(fd, p, n, true);
-}
-
-void initialize_srand(void) {
- static bool srand_called = false;
- unsigned x;
-#ifdef HAVE_SYS_AUXV_H
- void *auxv;
-#endif
-
- if (srand_called)
- return;
-
-#ifdef HAVE_SYS_AUXV_H
- /* The kernel provides us with 16 bytes of entropy in auxv, so let's try to make use of that to seed the
- * pseudo-random generator. It's better than nothing... */
-
- auxv = (void*) getauxval(AT_RANDOM);
- if (auxv) {
- assert_cc(sizeof(x) < 16);
- memcpy(&x, auxv, sizeof(x));
- } else
-#endif
- x = 0;
-
-
- x ^= (unsigned) now(CLOCK_REALTIME);
- x ^= (unsigned) gettid();
-
- srand(x);
- srand_called = true;
-}
-
-void random_bytes(void *p, size_t n) {
- uint8_t *q;
- int r;
-
- r = dev_urandom(p, n);
- if (r >= 0)
- return;
-
- /* If some idiot made /dev/urandom unavailable to us, he'll
- * get a PRNG instead. */
-
- initialize_srand();
-
- for (q = p; q < (uint8_t*) p + n; q ++)
- *q = rand();
-}
diff --git a/src/basic/random-util.h b/src/basic/random-util.h
deleted file mode 100644
index 3cee4c5014..0000000000
--- a/src/basic/random-util.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#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 <stddef.h>
-#include <stdint.h>
-
-int dev_urandom(void *p, size_t n);
-void random_bytes(void *p, size_t n);
-void initialize_srand(void);
-
-static inline uint64_t random_u64(void) {
- uint64_t u;
- random_bytes(&u, sizeof(u));
- return u;
-}
-
-static inline uint32_t random_u32(void) {
- uint32_t u;
- random_bytes(&u, sizeof(u));
- return u;
-}
diff --git a/src/basic/ratelimit.c b/src/basic/ratelimit.c
deleted file mode 100644
index 3ca5625e4d..0000000000
--- a/src/basic/ratelimit.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/***
- 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/time.h>
-
-#include "macro.h"
-#include "ratelimit.h"
-
-/* Modelled after Linux' lib/ratelimit.c by Dave Young
- * <hidave.darkstar@gmail.com>, which is licensed GPLv2. */
-
-bool ratelimit_test(RateLimit *r) {
- usec_t ts;
-
- assert(r);
-
- if (r->interval <= 0 || r->burst <= 0)
- return true;
-
- ts = now(CLOCK_MONOTONIC);
-
- if (r->begin <= 0 ||
- r->begin + r->interval < ts) {
- r->begin = ts;
-
- /* Reset counter */
- r->num = 0;
- goto good;
- }
-
- if (r->num < r->burst)
- goto good;
-
- return false;
-
-good:
- r->num++;
- return true;
-}
diff --git a/src/basic/ratelimit.h b/src/basic/ratelimit.h
deleted file mode 100644
index 9c8dddf5ad..0000000000
--- a/src/basic/ratelimit.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#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 "time-util.h"
-#include "util.h"
-
-typedef struct RateLimit {
- usec_t interval;
- usec_t begin;
- unsigned burst;
- unsigned num;
-} RateLimit;
-
-#define RATELIMIT_DEFINE(_name, _interval, _burst) \
- RateLimit _name = { \
- .interval = (_interval), \
- .burst = (_burst), \
- .num = 0, \
- .begin = 0 \
- }
-
-#define RATELIMIT_INIT(v, _interval, _burst) \
- do { \
- RateLimit *_r = &(v); \
- _r->interval = (_interval); \
- _r->burst = (_burst); \
- _r->num = 0; \
- _r->begin = 0; \
- } while (false)
-
-#define RATELIMIT_RESET(v) \
- do { \
- RateLimit *_r = &(v); \
- _r->num = 0; \
- _r->begin = 0; \
- } while (false)
-
-bool ratelimit_test(RateLimit *r);
diff --git a/src/basic/raw-clone.h b/src/basic/raw-clone.h
deleted file mode 100644
index d473828999..0000000000
--- a/src/basic/raw-clone.h
+++ /dev/null
@@ -1,81 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2016 Michael Karcher
- 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 <sched.h>
-#include <sys/syscall.h>
-
-#include "log.h"
-#include "macro.h"
-
-/**
- * raw_clone() - uses clone to create a new process with clone flags
- * @flags: Flags to pass to the clone system call
- *
- * Uses the clone system call to create a new process with the cloning
- * flags and termination signal passed in the flags parameter. Opposed
- * to glibc's clone funtion, using this function does not set up a
- * separate stack for the child, but relies on copy-on-write semantics
- * on the one stack at a common virtual address, just as fork does.
- *
- * To obtain copy-on-write semantics, flags must not contain CLONE_VM,
- * and thus CLONE_THREAD and CLONE_SIGHAND (which require CLONE_VM) are
- * not usabale.
- * Additionally, as this function does not pass the ptid, newtls and ctid
- * parameters to the kernel, flags must not contain CLONE_PARENT_SETTID,
- * CLONE_CHILD_SETTID, CLONE_CHILD_CLEARTID or CLONE_SETTLS.
- *
- * Returns: 0 in the child process and the child process id in the parent.
- */
-static inline int raw_clone(unsigned long flags) {
- assert((flags & (CLONE_VM|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID|
- CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0);
-#if defined(__s390__) || defined(__CRIS__)
- /* On s390 and cris the order of the first and second arguments
- * of the raw clone() system call is reversed. */
- return (int) syscall(__NR_clone, NULL, flags);
-#elif defined(__sparc__) && defined(__arch64__)
- {
- /**
- * sparc64 always returns the other process id in %o0, and
- * a boolean flag whether this is the child or the parent in
- * %o1. Inline assembly is needed to get the flag returned
- * in %o1.
- */
- int in_child;
- int child_pid;
- asm volatile("mov %2, %%g1\n\t"
- "mov %3, %%o0\n\t"
- "mov 0 , %%o1\n\t"
- "t 0x6d\n\t"
- "mov %%o1, %0\n\t"
- "mov %%o0, %1" :
- "=r"(in_child), "=r"(child_pid) :
- "i"(__NR_clone), "r"(flags) :
- "%o1", "%o0", "%g1" );
- if (in_child)
- return 0;
- else
- return child_pid;
- }
-#else
- return (int) syscall(__NR_clone, flags, NULL);
-#endif
-}
diff --git a/src/basic/refcnt.h b/src/basic/refcnt.h
deleted file mode 100644
index 1d77a6445a..0000000000
--- a/src/basic/refcnt.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 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/>.
-***/
-
-/* A type-safe atomic refcounter.
- *
- * DO NOT USE THIS UNLESS YOU ACTUALLY CARE ABOUT THREAD SAFETY! */
-
-typedef struct {
- volatile unsigned _value;
-} RefCount;
-
-#define REFCNT_GET(r) ((r)._value)
-#define REFCNT_INC(r) (__sync_add_and_fetch(&(r)._value, 1))
-#define REFCNT_DEC(r) (__sync_sub_and_fetch(&(r)._value, 1))
-
-#define REFCNT_INIT ((RefCount) { ._value = 1 })
diff --git a/src/basic/replace-var.c b/src/basic/replace-var.c
deleted file mode 100644
index 0d21423a9c..0000000000
--- a/src/basic/replace-var.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 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 <errno.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "alloc-util.h"
-#include "macro.h"
-#include "replace-var.h"
-#include "string-util.h"
-
-/*
- * Generic infrastructure for replacing @FOO@ style variables in
- * strings. Will call a callback for each replacement.
- */
-
-static int get_variable(const char *b, char **r) {
- size_t k;
- char *t;
-
- assert(b);
- assert(r);
-
- if (*b != '@')
- return 0;
-
- k = strspn(b + 1, UPPERCASE_LETTERS "_");
- if (k <= 0 || b[k+1] != '@')
- return 0;
-
- t = strndup(b + 1, k);
- if (!t)
- return -ENOMEM;
-
- *r = t;
- return 1;
-}
-
-char *replace_var(const char *text, char *(*lookup)(const char *variable, void*userdata), void *userdata) {
- char *r, *t;
- const char *f;
- size_t l;
-
- assert(text);
- assert(lookup);
-
- l = strlen(text);
- r = new(char, l+1);
- if (!r)
- return NULL;
-
- f = text;
- t = r;
- while (*f) {
- _cleanup_free_ char *v = NULL, *n = NULL;
- char *a;
- int k;
- size_t skip, d, nl;
-
- k = get_variable(f, &v);
- if (k < 0)
- goto oom;
- if (k == 0) {
- *(t++) = *(f++);
- continue;
- }
-
- n = lookup(v, userdata);
- if (!n)
- goto oom;
-
- skip = strlen(v) + 2;
-
- d = t - r;
- nl = l - skip + strlen(n);
- a = realloc(r, nl + 1);
- if (!a)
- goto oom;
-
- l = nl;
- r = a;
- t = r + d;
-
- t = stpcpy(t, n);
- f += skip;
- }
-
- *t = 0;
- return r;
-
-oom:
- return mfree(r);
-}
diff --git a/src/basic/replace-var.h b/src/basic/replace-var.h
deleted file mode 100644
index 78412910b2..0000000000
--- a/src/basic/replace-var.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 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/>.
-***/
-
-char *replace_var(const char *text, char *(*lookup)(const char *variable, void*userdata), void *userdata);
diff --git a/src/basic/rlimit-util.c b/src/basic/rlimit-util.c
deleted file mode 100644
index ee063720ed..0000000000
--- a/src/basic/rlimit-util.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/***
- 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 <sys/resource.h>
-
-#include "alloc-util.h"
-#include "extract-word.h"
-#include "formats-util.h"
-#include "macro.h"
-#include "missing.h"
-#include "rlimit-util.h"
-#include "string-table.h"
-#include "time-util.h"
-
-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;
-}
-
-static int rlimit_parse_u64(const char *val, rlim_t *ret) {
- uint64_t u;
- int r;
-
- assert(val);
- assert(ret);
-
- if (streq(val, "infinity")) {
- *ret = RLIM_INFINITY;
- return 0;
- }
-
- /* setrlimit(2) suggests rlim_t is always 64bit on Linux. */
- assert_cc(sizeof(rlim_t) == sizeof(uint64_t));
-
- r = safe_atou64(val, &u);
- if (r < 0)
- return r;
- if (u >= (uint64_t) RLIM_INFINITY)
- return -ERANGE;
-
- *ret = (rlim_t) u;
- return 0;
-}
-
-static int rlimit_parse_size(const char *val, rlim_t *ret) {
- uint64_t u;
- int r;
-
- assert(val);
- assert(ret);
-
- if (streq(val, "infinity")) {
- *ret = RLIM_INFINITY;
- return 0;
- }
-
- r = parse_size(val, 1024, &u);
- if (r < 0)
- return r;
- if (u >= (uint64_t) RLIM_INFINITY)
- return -ERANGE;
-
- *ret = (rlim_t) u;
- return 0;
-}
-
-static int rlimit_parse_sec(const char *val, rlim_t *ret) {
- uint64_t u;
- usec_t t;
- int r;
-
- assert(val);
- assert(ret);
-
- if (streq(val, "infinity")) {
- *ret = RLIM_INFINITY;
- return 0;
- }
-
- r = parse_sec(val, &t);
- if (r < 0)
- return r;
- if (t == USEC_INFINITY) {
- *ret = RLIM_INFINITY;
- return 0;
- }
-
- u = (uint64_t) DIV_ROUND_UP(t, USEC_PER_SEC);
- if (u >= (uint64_t) RLIM_INFINITY)
- return -ERANGE;
-
- *ret = (rlim_t) u;
- return 0;
-}
-
-static int rlimit_parse_usec(const char *val, rlim_t *ret) {
- usec_t t;
- int r;
-
- assert(val);
- assert(ret);
-
- if (streq(val, "infinity")) {
- *ret = RLIM_INFINITY;
- return 0;
- }
-
- r = parse_time(val, &t, 1);
- if (r < 0)
- return r;
- if (t == USEC_INFINITY) {
- *ret = RLIM_INFINITY;
- return 0;
- }
-
- *ret = (rlim_t) t;
- return 0;
-}
-
-static int rlimit_parse_nice(const char *val, rlim_t *ret) {
- uint64_t rl;
- int r;
-
- /* So, Linux is weird. The range for RLIMIT_NICE is 40..1, mapping to the nice levels -20..19. However, the
- * RLIMIT_NICE limit defaults to 0 by the kernel, i.e. a value that maps to nice level 20, which of course is
- * bogus and does not exist. In order to permit parsing the RLIMIT_NICE of 0 here we hence implement a slight
- * asymmetry: when parsing as positive nice level we permit 0..19. When parsing as negative nice level, we
- * permit -20..0. But when parsing as raw resource limit value then we also allow the special value 0.
- *
- * Yeah, Linux is quality engineering sometimes... */
-
- if (val[0] == '+') {
-
- /* Prefixed with "+": Parse as positive user-friendly nice value */
- r = safe_atou64(val + 1, &rl);
- if (r < 0)
- return r;
-
- if (rl >= PRIO_MAX)
- return -ERANGE;
-
- rl = 20 - rl;
-
- } else if (val[0] == '-') {
-
- /* Prefixed with "-": Parse as negative user-friendly nice value */
- r = safe_atou64(val + 1, &rl);
- if (r < 0)
- return r;
-
- if (rl > (uint64_t) (-PRIO_MIN))
- return -ERANGE;
-
- rl = 20 + rl;
- } else {
-
- /* Not prefixed: parse as raw resource limit value */
- r = safe_atou64(val, &rl);
- if (r < 0)
- return r;
-
- if (rl > (uint64_t) (20 - PRIO_MIN))
- return -ERANGE;
- }
-
- *ret = (rlim_t) rl;
- return 0;
-}
-
-static int (*const rlimit_parse_table[_RLIMIT_MAX])(const char *val, rlim_t *ret) = {
- [RLIMIT_CPU] = rlimit_parse_sec,
- [RLIMIT_FSIZE] = rlimit_parse_size,
- [RLIMIT_DATA] = rlimit_parse_size,
- [RLIMIT_STACK] = rlimit_parse_size,
- [RLIMIT_CORE] = rlimit_parse_size,
- [RLIMIT_RSS] = rlimit_parse_size,
- [RLIMIT_NOFILE] = rlimit_parse_u64,
- [RLIMIT_AS] = rlimit_parse_size,
- [RLIMIT_NPROC] = rlimit_parse_u64,
- [RLIMIT_MEMLOCK] = rlimit_parse_size,
- [RLIMIT_LOCKS] = rlimit_parse_u64,
- [RLIMIT_SIGPENDING] = rlimit_parse_u64,
- [RLIMIT_MSGQUEUE] = rlimit_parse_size,
- [RLIMIT_NICE] = rlimit_parse_nice,
- [RLIMIT_RTPRIO] = rlimit_parse_u64,
- [RLIMIT_RTTIME] = rlimit_parse_usec,
-};
-
-int rlimit_parse_one(int resource, const char *val, rlim_t *ret) {
- assert(val);
- assert(ret);
-
- if (resource < 0)
- return -EINVAL;
- if (resource >= _RLIMIT_MAX)
- return -EINVAL;
-
- return rlimit_parse_table[resource](val, ret);
-}
-
-int rlimit_parse(int resource, const char *val, struct rlimit *ret) {
- _cleanup_free_ char *hard = NULL, *soft = NULL;
- rlim_t hl, sl;
- int r;
-
- assert(val);
- assert(ret);
-
- r = extract_first_word(&val, &soft, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
- if (r < 0)
- return r;
- if (r == 0)
- return -EINVAL;
-
- r = rlimit_parse_one(resource, soft, &sl);
- if (r < 0)
- return r;
-
- r = extract_first_word(&val, &hard, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
- if (r < 0)
- return r;
- if (!isempty(val))
- return -EINVAL;
- if (r == 0)
- hl = sl;
- else {
- r = rlimit_parse_one(resource, hard, &hl);
- if (r < 0)
- return r;
- if (sl > hl)
- return -EILSEQ;
- }
-
- *ret = (struct rlimit) {
- .rlim_cur = sl,
- .rlim_max = hl,
- };
-
- return 0;
-}
-
-int rlimit_format(const struct rlimit *rl, char **ret) {
- char *s = NULL;
-
- assert(rl);
- assert(ret);
-
- if (rl->rlim_cur >= RLIM_INFINITY && rl->rlim_max >= RLIM_INFINITY)
- s = strdup("infinity");
- else if (rl->rlim_cur >= RLIM_INFINITY)
- (void) asprintf(&s, "infinity:" RLIM_FMT, rl->rlim_max);
- else if (rl->rlim_max >= RLIM_INFINITY)
- (void) asprintf(&s, RLIM_FMT ":infinity", rl->rlim_cur);
- else if (rl->rlim_cur == rl->rlim_max)
- (void) asprintf(&s, RLIM_FMT, rl->rlim_cur);
- else
- (void) asprintf(&s, RLIM_FMT ":" RLIM_FMT, rl->rlim_cur, rl->rlim_max);
-
- if (!s)
- return -ENOMEM;
-
- *ret = s;
- return 0;
-}
-
-static const char* const rlimit_table[_RLIMIT_MAX] = {
- [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);
diff --git a/src/basic/rlimit-util.h b/src/basic/rlimit-util.h
deleted file mode 100644
index d4594eccd6..0000000000
--- a/src/basic/rlimit-util.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#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/resource.h>
-
-#include "macro.h"
-
-const char *rlimit_to_string(int i) _const_;
-int rlimit_from_string(const char *s) _pure_;
-
-int setrlimit_closest(int resource, const struct rlimit *rlim);
-
-int rlimit_parse_one(int resource, const char *val, rlim_t *ret);
-int rlimit_parse(int resource, const char *val, struct rlimit *ret);
-
-int rlimit_format(const struct rlimit *rl, char **ret);
-
-#define RLIMIT_MAKE_CONST(lim) ((struct rlimit) { lim, lim })
diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c
deleted file mode 100644
index baa70c2c8d..0000000000
--- a/src/basic/rm-rf.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2015 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 <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <unistd.h>
-
-#include "btrfs-util.h"
-#include "cgroup-util.h"
-#include "fd-util.h"
-#include "log.h"
-#include "macro.h"
-#include "mount-util.h"
-#include "path-util.h"
-#include "rm-rf.h"
-#include "stat-util.h"
-#include "string-util.h"
-
-static bool is_physical_fs(const struct statfs *sfs) {
- return !is_temporary_fs(sfs) && !is_cgroup_fs(sfs);
-}
-
-int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
- _cleanup_closedir_ DIR *d = NULL;
- int ret = 0, r;
- struct statfs sfs;
-
- assert(fd >= 0);
-
- /* This returns the first error we run into, but nevertheless
- * tries to go on. This closes the passed fd. */
-
- if (!(flags & REMOVE_PHYSICAL)) {
-
- r = fstatfs(fd, &sfs);
- if (r < 0) {
- safe_close(fd);
- return -errno;
- }
-
- if (is_physical_fs(&sfs)) {
- /* We refuse to clean physical file systems
- * with this call, unless explicitly
- * requested. This is extra paranoia just to
- * be sure we never ever remove non-state
- * data */
-
- log_error("Attempted to remove disk file system, and we can't allow that.");
- safe_close(fd);
- return -EPERM;
- }
- }
-
- d = fdopendir(fd);
- if (!d) {
- safe_close(fd);
- return errno == ENOENT ? 0 : -errno;
- }
-
- for (;;) {
- struct dirent *de;
- bool is_dir;
- struct stat st;
-
- errno = 0;
- de = readdir(d);
- if (!de) {
- if (errno > 0 && ret == 0)
- ret = -errno;
- return ret;
- }
-
- if (streq(de->d_name, ".") || streq(de->d_name, ".."))
- continue;
-
- if (de->d_type == DT_UNKNOWN ||
- (de->d_type == DT_DIR && (root_dev || (flags & REMOVE_SUBVOLUME)))) {
- 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);
- } else
- is_dir = de->d_type == DT_DIR;
-
- if (is_dir) {
- int subdir_fd;
-
- /* if root_dev is set, remove subdirectories only if device is same */
- 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;
- }
-
- /* Stop at mount points */
- r = fd_is_mount_point(fd, de->d_name, 0);
- if (r < 0) {
- if (ret == 0 && r != -ENOENT)
- ret = r;
-
- safe_close(subdir_fd);
- continue;
- }
- if (r) {
- safe_close(subdir_fd);
- continue;
- }
-
- if ((flags & REMOVE_SUBVOLUME) && st.st_ino == 256) {
-
- /* This could be a subvolume, try to remove it */
-
- r = btrfs_subvol_remove_fd(fd, de->d_name, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA);
- if (r < 0) {
- if (r != -ENOTTY && r != -EINVAL) {
- if (ret == 0)
- ret = r;
-
- safe_close(subdir_fd);
- continue;
- }
-
- /* ENOTTY, then it wasn't a
- * btrfs subvolume, continue
- * below. */
- } else {
- /* It was a subvolume, continue. */
- safe_close(subdir_fd);
- continue;
- }
- }
-
- /* We pass REMOVE_PHYSICAL here, to avoid
- * doing the fstatfs() to check the file
- * system type again for each directory */
- r = rm_rf_children(subdir_fd, flags | REMOVE_PHYSICAL, root_dev);
- if (r < 0 && ret == 0)
- ret = r;
-
- if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
- if (ret == 0 && errno != ENOENT)
- ret = -errno;
- }
-
- } else if (!(flags & REMOVE_ONLY_DIRECTORIES)) {
-
- if (unlinkat(fd, de->d_name, 0) < 0) {
- if (ret == 0 && errno != ENOENT)
- ret = -errno;
- }
- }
- }
-}
-
-int rm_rf(const char *path, RemoveFlags flags) {
- 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;
- }
-
- if ((flags & (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) == (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) {
- /* Try to remove as subvolume first */
- r = btrfs_subvol_remove(path, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA);
- if (r >= 0)
- return r;
-
- if (r != -ENOTTY && r != -EINVAL && r != -ENOTDIR)
- return r;
-
- /* Not btrfs or not a subvolume */
- }
-
- fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
- if (fd < 0) {
-
- if (errno != ENOTDIR && errno != ELOOP)
- return -errno;
-
- if (!(flags & REMOVE_PHYSICAL)) {
- if (statfs(path, &s) < 0)
- return -errno;
-
- if (is_physical_fs(&s)) {
- log_error("Attempted to remove disk file system, and we can't allow that.");
- return -EPERM;
- }
- }
-
- if ((flags & REMOVE_ROOT) && !(flags & REMOVE_ONLY_DIRECTORIES))
- if (unlink(path) < 0 && errno != ENOENT)
- return -errno;
-
- return 0;
- }
-
- r = rm_rf_children(fd, flags, NULL);
-
- if (flags & REMOVE_ROOT) {
- if (rmdir(path) < 0) {
- if (r == 0 && errno != ENOENT)
- r = -errno;
- }
- }
-
- return r;
-}
diff --git a/src/basic/rm-rf.h b/src/basic/rm-rf.h
deleted file mode 100644
index f693a5bb7c..0000000000
--- a/src/basic/rm-rf.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2015 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/stat.h>
-
-typedef enum RemoveFlags {
- REMOVE_ONLY_DIRECTORIES = 1,
- REMOVE_ROOT = 2,
- REMOVE_PHYSICAL = 4, /* if not set, only removes files on tmpfs, never physical file systems */
- REMOVE_SUBVOLUME = 8,
-} RemoveFlags;
-
-int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev);
-int rm_rf(const char *path, RemoveFlags flags);
-
-/* Useful for usage with _cleanup_(), destroys a directory and frees the pointer */
-static inline void rm_rf_physical_and_free(char *p) {
- if (!p)
- return;
- (void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
- free(p);
-}
-DEFINE_TRIVIAL_CLEANUP_FUNC(char*, rm_rf_physical_and_free);
diff --git a/src/basic/securebits.h b/src/basic/securebits.h
deleted file mode 100644
index 98fbe0d433..0000000000
--- a/src/basic/securebits.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef _LINUX_SECUREBITS_H
-#define _LINUX_SECUREBITS_H 1
-
-/* This is minimal version of Linux' linux/securebits.h header file,
- * which is licensed GPL2 */
-
-#define SECUREBITS_DEFAULT 0x00000000
-
-/* When set UID 0 has no special privileges. When unset, we support
- inheritance of root-permissions and suid-root executable under
- compatibility mode. We raise the effective and inheritable bitmasks
- *of the executable file* if the effective uid of the new process is
- 0. If the real uid is 0, we raise the effective (legacy) bit of the
- executable file. */
-#define SECURE_NOROOT 0
-#define SECURE_NOROOT_LOCKED 1 /* make bit-0 immutable */
-
-/* When set, setuid to/from uid 0 does not trigger capability-"fixup".
- When unset, to provide compatibility with old programs relying on
- set*uid to gain/lose privilege, transitions to/from uid 0 cause
- capabilities to be gained/lost. */
-#define SECURE_NO_SETUID_FIXUP 2
-#define SECURE_NO_SETUID_FIXUP_LOCKED 3 /* make bit-2 immutable */
-
-/* When set, a process can retain its capabilities even after
- transitioning to a non-root user (the set-uid fixup suppressed by
- bit 2). Bit-4 is cleared when a process calls exec(); setting both
- bit 4 and 5 will create a barrier through exec that no exec()'d
- child can use this feature again. */
-#define SECURE_KEEP_CAPS 4
-#define SECURE_KEEP_CAPS_LOCKED 5 /* make bit-4 immutable */
-
-/* Each securesetting is implemented using two bits. One bit specifies
- whether the setting is on or off. The other bit specify whether the
- setting is locked or not. A setting which is locked cannot be
- changed from user-level. */
-#define issecure_mask(X) (1 << (X))
-#define issecure(X) (issecure_mask(X) & current_cred_xxx(securebits))
-
-#define SECURE_ALL_BITS (issecure_mask(SECURE_NOROOT) | \
- issecure_mask(SECURE_NO_SETUID_FIXUP) | \
- issecure_mask(SECURE_KEEP_CAPS))
-#define SECURE_ALL_LOCKS (SECURE_ALL_BITS << 1)
-
-#endif /* !_LINUX_SECUREBITS_H */
diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c
deleted file mode 100644
index bc07654668..0000000000
--- a/src/basic/selinux-util.c
+++ /dev/null
@@ -1,485 +0,0 @@
-/***
- 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 <malloc.h>
-#include <stddef.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/un.h>
-#include <syslog.h>
-
-#ifdef HAVE_SELINUX
-#include <selinux/context.h>
-#include <selinux/label.h>
-#include <selinux/selinux.h>
-#endif
-
-#include "alloc-util.h"
-#include "log.h"
-#include "macro.h"
-#include "path-util.h"
-#include "selinux-util.h"
-#include "time-util.h"
-#include "util.h"
-
-#ifdef HAVE_SELINUX
-DEFINE_TRIVIAL_CLEANUP_FUNC(char*, freecon);
-DEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free);
-
-#define _cleanup_freecon_ _cleanup_(freeconp)
-#define _cleanup_context_free_ _cleanup_(context_freep)
-
-static int cached_use = -1;
-static struct selabel_handle *label_hnd = NULL;
-
-#define log_enforcing(...) log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, __VA_ARGS__)
-#endif
-
-bool mac_selinux_have(void) {
-#ifdef HAVE_SELINUX
- if (cached_use < 0)
- cached_use = is_selinux_enabled() > 0;
-
- return cached_use;
-#else
- return false;
-#endif
-}
-
-bool mac_selinux_use(void) {
- if (!mac_selinux_have())
- return false;
-
- /* Never try to configure SELinux features if we aren't
- * root */
-
- return getuid() == 0;
-}
-
-void mac_selinux_retest(void) {
-#ifdef HAVE_SELINUX
- cached_use = -1;
-#endif
-}
-
-int mac_selinux_init(void) {
- int r = 0;
-
-#ifdef HAVE_SELINUX
- usec_t before_timestamp, after_timestamp;
- struct mallinfo before_mallinfo, after_mallinfo;
-
- if (label_hnd)
- return 0;
-
- if (!mac_selinux_use())
- return 0;
-
- before_mallinfo = mallinfo();
- before_timestamp = now(CLOCK_MONOTONIC);
-
- label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
- if (!label_hnd) {
- log_enforcing("Failed to initialize SELinux context: %m");
- r = security_getenforce() == 1 ? -errno : 0;
- } else {
- char timespan[FORMAT_TIMESPAN_MAX];
- int l;
-
- after_timestamp = now(CLOCK_MONOTONIC);
- after_mallinfo = mallinfo();
-
- l = after_mallinfo.uordblks > before_mallinfo.uordblks ? after_mallinfo.uordblks - before_mallinfo.uordblks : 0;
-
- log_debug("Successfully loaded SELinux database in %s, size on heap is %iK.",
- format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0),
- (l+1023)/1024);
- }
-#endif
-
- return r;
-}
-
-void mac_selinux_finish(void) {
-
-#ifdef HAVE_SELINUX
- if (!label_hnd)
- return;
-
- selabel_close(label_hnd);
- label_hnd = NULL;
-#endif
-}
-
-int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
-
-#ifdef HAVE_SELINUX
- struct stat st;
- int r;
-
- assert(path);
-
- /* if mac_selinux_init() wasn't called before we are a NOOP */
- if (!label_hnd)
- return 0;
-
- r = lstat(path, &st);
- if (r >= 0) {
- _cleanup_freecon_ char* fcon = NULL;
-
- r = selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode);
-
- /* If there's no label to set, then exit without warning */
- if (r < 0 && errno == ENOENT)
- return 0;
-
- if (r >= 0) {
- r = lsetfilecon_raw(path, fcon);
-
- /* If the FS doesn't support labels, then exit without warning */
- if (r < 0 && errno == EOPNOTSUPP)
- return 0;
- }
- }
-
- if (r < 0) {
- /* Ignore ENOENT in some cases */
- if (ignore_enoent && errno == ENOENT)
- return 0;
-
- if (ignore_erofs && errno == EROFS)
- return 0;
-
- log_enforcing("Unable to fix SELinux security context of %s: %m", path);
- if (security_getenforce() == 1)
- return -errno;
- }
-#endif
-
- return 0;
-}
-
-int mac_selinux_apply(const char *path, const char *label) {
-
-#ifdef HAVE_SELINUX
- if (!mac_selinux_use())
- return 0;
-
- assert(path);
- assert(label);
-
- if (setfilecon(path, label) < 0) {
- log_enforcing("Failed to set SELinux security context %s on path %s: %m", label, path);
- if (security_getenforce() > 0)
- return -errno;
- }
-#endif
- return 0;
-}
-
-int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
- int r = -EOPNOTSUPP;
-
-#ifdef HAVE_SELINUX
- _cleanup_freecon_ char *mycon = NULL, *fcon = NULL;
- security_class_t sclass;
-
- assert(exe);
- assert(label);
-
- if (!mac_selinux_have())
- return -EOPNOTSUPP;
-
- r = getcon_raw(&mycon);
- if (r < 0)
- return -errno;
-
- r = getfilecon_raw(exe, &fcon);
- if (r < 0)
- return -errno;
-
- sclass = string_to_security_class("process");
- r = security_compute_create_raw(mycon, fcon, sclass, label);
- if (r < 0)
- return -errno;
-#endif
-
- return r;
-}
-
-int mac_selinux_get_our_label(char **label) {
- int r = -EOPNOTSUPP;
-
- assert(label);
-
-#ifdef HAVE_SELINUX
- if (!mac_selinux_have())
- return -EOPNOTSUPP;
-
- r = getcon_raw(label);
- if (r < 0)
- return -errno;
-#endif
-
- return r;
-}
-
-int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *exec_label, char **label) {
- int r = -EOPNOTSUPP;
-
-#ifdef HAVE_SELINUX
- _cleanup_freecon_ char *mycon = NULL, *peercon = NULL, *fcon = NULL;
- _cleanup_context_free_ context_t pcon = NULL, bcon = NULL;
- security_class_t sclass;
- const char *range = NULL;
-
- assert(socket_fd >= 0);
- assert(exe);
- assert(label);
-
- if (!mac_selinux_have())
- return -EOPNOTSUPP;
-
- r = getcon_raw(&mycon);
- if (r < 0)
- return -errno;
-
- r = getpeercon_raw(socket_fd, &peercon);
- if (r < 0)
- return -errno;
-
- if (!exec_label) {
- /* If there is no context set for next exec let's use context
- of target executable */
- r = getfilecon_raw(exe, &fcon);
- if (r < 0)
- return -errno;
- }
-
- bcon = context_new(mycon);
- if (!bcon)
- return -ENOMEM;
-
- pcon = context_new(peercon);
- if (!pcon)
- return -ENOMEM;
-
- range = context_range_get(pcon);
- if (!range)
- return -errno;
-
- r = context_range_set(bcon, range);
- if (r)
- return -errno;
-
- freecon(mycon);
- mycon = strdup(context_str(bcon));
- if (!mycon)
- return -ENOMEM;
-
- sclass = string_to_security_class("process");
- r = security_compute_create_raw(mycon, fcon, sclass, label);
- if (r < 0)
- return -errno;
-#endif
-
- return r;
-}
-
-char* mac_selinux_free(char *label) {
-
-#ifdef HAVE_SELINUX
- if (!label)
- return NULL;
-
- if (!mac_selinux_have())
- return NULL;
-
-
- freecon(label);
-#endif
-
- return NULL;
-}
-
-int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
-
-#ifdef HAVE_SELINUX
- _cleanup_freecon_ char *filecon = NULL;
- int r;
-
- assert(path);
-
- if (!label_hnd)
- return 0;
-
- if (path_is_absolute(path))
- r = selabel_lookup_raw(label_hnd, &filecon, path, mode);
- else {
- _cleanup_free_ char *newpath = NULL;
-
- r = path_make_absolute_cwd(path, &newpath);
- if (r < 0)
- return r;
-
- r = selabel_lookup_raw(label_hnd, &filecon, newpath, mode);
- }
-
- if (r < 0) {
- /* No context specified by the policy? Proceed without setting it. */
- if (errno == ENOENT)
- return 0;
-
- log_enforcing("Failed to determine SELinux security context for %s: %m", path);
- } else {
- if (setfscreatecon_raw(filecon) >= 0)
- return 0; /* Success! */
-
- log_enforcing("Failed to set SELinux security context %s for %s: %m", filecon, path);
- }
-
- if (security_getenforce() > 0)
- return -errno;
-
-#endif
- return 0;
-}
-
-void mac_selinux_create_file_clear(void) {
-
-#ifdef HAVE_SELINUX
- PROTECT_ERRNO;
-
- if (!mac_selinux_use())
- return;
-
- setfscreatecon_raw(NULL);
-#endif
-}
-
-int mac_selinux_create_socket_prepare(const char *label) {
-
-#ifdef HAVE_SELINUX
- if (!mac_selinux_use())
- return 0;
-
- assert(label);
-
- if (setsockcreatecon(label) < 0) {
- log_enforcing("Failed to set SELinux security context %s for sockets: %m", label);
-
- if (security_getenforce() == 1)
- return -errno;
- }
-#endif
-
- return 0;
-}
-
-void mac_selinux_create_socket_clear(void) {
-
-#ifdef HAVE_SELINUX
- PROTECT_ERRNO;
-
- if (!mac_selinux_use())
- return;
-
- setsockcreatecon_raw(NULL);
-#endif
-}
-
-int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
-
- /* Binds a socket and label its file system object according to the SELinux policy */
-
-#ifdef HAVE_SELINUX
- _cleanup_freecon_ char *fcon = NULL;
- const struct sockaddr_un *un;
- bool context_changed = false;
- char *path;
- int r;
-
- assert(fd >= 0);
- assert(addr);
- assert(addrlen >= sizeof(sa_family_t));
-
- if (!label_hnd)
- goto skipped;
-
- /* Filter out non-local sockets */
- if (addr->sa_family != AF_UNIX)
- goto skipped;
-
- /* Filter out anonymous sockets */
- if (addrlen < offsetof(struct sockaddr_un, sun_path) + 1)
- goto skipped;
-
- /* Filter out abstract namespace sockets */
- un = (const struct sockaddr_un*) addr;
- if (un->sun_path[0] == 0)
- goto skipped;
-
- path = strndupa(un->sun_path, addrlen - offsetof(struct sockaddr_un, sun_path));
-
- if (path_is_absolute(path))
- r = selabel_lookup_raw(label_hnd, &fcon, path, S_IFSOCK);
- else {
- _cleanup_free_ char *newpath = NULL;
-
- r = path_make_absolute_cwd(path, &newpath);
- if (r < 0)
- return r;
-
- r = selabel_lookup_raw(label_hnd, &fcon, newpath, S_IFSOCK);
- }
-
- if (r < 0) {
- /* No context specified by the policy? Proceed without setting it */
- if (errno == ENOENT)
- goto skipped;
-
- log_enforcing("Failed to determine SELinux security context for %s: %m", path);
- if (security_getenforce() > 0)
- return -errno;
-
- } else {
- if (setfscreatecon_raw(fcon) < 0) {
- log_enforcing("Failed to set SELinux security context %s for %s: %m", fcon, path);
- if (security_getenforce() > 0)
- return -errno;
- } else
- context_changed = true;
- }
-
- r = bind(fd, addr, addrlen) < 0 ? -errno : 0;
-
- if (context_changed)
- setfscreatecon_raw(NULL);
-
- return r;
-
-skipped:
-#endif
- if (bind(fd, addr, addrlen) < 0)
- return -errno;
-
- return 0;
-}
diff --git a/src/basic/selinux-util.h b/src/basic/selinux-util.h
deleted file mode 100644
index ce6bc8e44c..0000000000
--- a/src/basic/selinux-util.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#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 <sys/socket.h>
-#include <sys/types.h>
-
-#include "macro.h"
-
-bool mac_selinux_use(void);
-bool mac_selinux_have(void);
-void mac_selinux_retest(void);
-
-int mac_selinux_init(void);
-void mac_selinux_finish(void);
-
-int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
-int mac_selinux_apply(const char *path, const char *label);
-
-int mac_selinux_get_create_label_from_exe(const char *exe, char **label);
-int mac_selinux_get_our_label(char **label);
-int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *exec_label, char **label);
-char* mac_selinux_free(char *label);
-
-int mac_selinux_create_file_prepare(const char *path, mode_t mode);
-void mac_selinux_create_file_clear(void);
-
-int mac_selinux_create_socket_prepare(const char *label);
-void mac_selinux_create_socket_clear(void);
-
-int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(char*, mac_selinux_free);
diff --git a/src/basic/set.h b/src/basic/set.h
deleted file mode 100644
index a5f8beb0c4..0000000000
--- a/src/basic/set.h
+++ /dev/null
@@ -1,138 +0,0 @@
-#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 "extract-word.h"
-#include "hashmap.h"
-#include "macro.h"
-
-Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
-#define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS)
-
-static inline Set *set_free(Set *s) {
- internal_hashmap_free(HASHMAP_BASE(s));
- return NULL;
-}
-
-static inline Set *set_free_free(Set *s) {
- internal_hashmap_free_free(HASHMAP_BASE(s));
- return NULL;
-}
-
-/* no set_free_free_free */
-
-static inline Set *set_copy(Set *s) {
- return (Set*) internal_hashmap_copy(HASHMAP_BASE(s));
-}
-
-int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
-#define set_ensure_allocated(h, ops) internal_set_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
-
-int set_put(Set *s, const void *key);
-/* no set_update */
-/* no set_replace */
-static inline void *set_get(Set *s, void *key) {
- return internal_hashmap_get(HASHMAP_BASE(s), key);
-}
-/* no set_get2 */
-
-static inline bool set_contains(Set *s, const void *key) {
- return internal_hashmap_contains(HASHMAP_BASE(s), key);
-}
-
-static inline void *set_remove(Set *s, const void *key) {
- return internal_hashmap_remove(HASHMAP_BASE(s), key);
-}
-
-/* no set_remove2 */
-/* no set_remove_value */
-int set_remove_and_put(Set *s, const void *old_key, const void *new_key);
-/* no set_remove_and_replace */
-int set_merge(Set *s, Set *other);
-
-static inline int set_reserve(Set *h, unsigned entries_add) {
- return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add);
-}
-
-static inline int set_move(Set *s, Set *other) {
- return internal_hashmap_move(HASHMAP_BASE(s), HASHMAP_BASE(other));
-}
-
-static inline int set_move_one(Set *s, Set *other, const void *key) {
- return internal_hashmap_move_one(HASHMAP_BASE(s), HASHMAP_BASE(other), key);
-}
-
-static inline unsigned set_size(Set *s) {
- return internal_hashmap_size(HASHMAP_BASE(s));
-}
-
-static inline bool set_isempty(Set *s) {
- return set_size(s) == 0;
-}
-
-static inline unsigned set_buckets(Set *s) {
- return internal_hashmap_buckets(HASHMAP_BASE(s));
-}
-
-bool set_iterate(Set *s, Iterator *i, void **value);
-
-static inline void set_clear(Set *s) {
- internal_hashmap_clear(HASHMAP_BASE(s));
-}
-
-static inline void set_clear_free(Set *s) {
- internal_hashmap_clear_free(HASHMAP_BASE(s));
-}
-
-/* no set_clear_free_free */
-
-static inline void *set_steal_first(Set *s) {
- return internal_hashmap_steal_first(HASHMAP_BASE(s));
-}
-
-/* no set_steal_first_key */
-/* no set_first_key */
-
-static inline void *set_first(Set *s) {
- return internal_hashmap_first(HASHMAP_BASE(s));
-}
-
-/* no set_next */
-
-static inline char **set_get_strv(Set *s) {
- return internal_hashmap_get_strv(HASHMAP_BASE(s));
-}
-
-int set_consume(Set *s, void *value);
-int set_put_strdup(Set *s, const char *p);
-int set_put_strdupv(Set *s, char **l);
-int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags);
-
-#define SET_FOREACH(e, s, i) \
- for ((i) = ITERATOR_FIRST; set_iterate((s), &(i), (void**)&(e)); )
-
-#define SET_FOREACH_MOVE(e, d, s) \
- for (; ({ e = set_first(s); assert_se(!e || set_move_one(d, s, e) >= 0); e; }); )
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free);
-
-#define _cleanup_set_free_ _cleanup_(set_freep)
-#define _cleanup_set_free_free_ _cleanup_(set_free_freep)
diff --git a/src/basic/sigbus.c b/src/basic/sigbus.c
deleted file mode 100644
index 0ce4f75684..0000000000
--- a/src/basic/sigbus.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 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 <signal.h>
-#include <stddef.h>
-#include <sys/mman.h>
-
-#include "macro.h"
-#include "sigbus.h"
-#include "util.h"
-
-#define SIGBUS_QUEUE_MAX 64
-
-static struct sigaction old_sigaction;
-static unsigned n_installed = 0;
-
-/* We maintain a fixed size list of page addresses that triggered a
- SIGBUS. We access with list with atomic operations, so that we
- don't have to deal with locks between signal handler and main
- programs in possibly multiple threads. */
-
-static void* volatile sigbus_queue[SIGBUS_QUEUE_MAX];
-static volatile sig_atomic_t n_sigbus_queue = 0;
-
-static void sigbus_push(void *addr) {
- unsigned u;
-
- assert(addr);
-
- /* Find a free place, increase the number of entries and leave, if we can */
- for (u = 0; u < SIGBUS_QUEUE_MAX; u++)
- if (__sync_bool_compare_and_swap(&sigbus_queue[u], NULL, addr)) {
- __sync_fetch_and_add(&n_sigbus_queue, 1);
- return;
- }
-
- /* If we can't, make sure the queue size is out of bounds, to
- * mark it as overflow */
- for (;;) {
- unsigned c;
-
- __sync_synchronize();
- c = n_sigbus_queue;
-
- if (c > SIGBUS_QUEUE_MAX) /* already overflow */
- return;
-
- if (__sync_bool_compare_and_swap(&n_sigbus_queue, c, c + SIGBUS_QUEUE_MAX))
- return;
- }
-}
-
-int sigbus_pop(void **ret) {
- assert(ret);
-
- for (;;) {
- unsigned u, c;
-
- __sync_synchronize();
- c = n_sigbus_queue;
-
- if (_likely_(c == 0))
- return 0;
-
- if (_unlikely_(c >= SIGBUS_QUEUE_MAX))
- return -EOVERFLOW;
-
- for (u = 0; u < SIGBUS_QUEUE_MAX; u++) {
- void *addr;
-
- addr = sigbus_queue[u];
- if (!addr)
- continue;
-
- if (__sync_bool_compare_and_swap(&sigbus_queue[u], addr, NULL)) {
- __sync_fetch_and_sub(&n_sigbus_queue, 1);
- *ret = addr;
- return 1;
- }
- }
- }
-}
-
-static void sigbus_handler(int sn, siginfo_t *si, void *data) {
- unsigned long ul;
- void *aligned;
-
- assert(sn == SIGBUS);
- assert(si);
-
- if (si->si_code != BUS_ADRERR || !si->si_addr) {
- assert_se(sigaction(SIGBUS, &old_sigaction, NULL) == 0);
- raise(SIGBUS);
- return;
- }
-
- ul = (unsigned long) si->si_addr;
- ul = ul / page_size();
- ul = ul * page_size();
- aligned = (void*) ul;
-
- /* Let's remember which address failed */
- sigbus_push(aligned);
-
- /* Replace mapping with an anonymous page, so that the
- * execution can continue, however with a zeroed out page */
- assert_se(mmap(aligned, page_size(), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0) == aligned);
-}
-
-void sigbus_install(void) {
- struct sigaction sa = {
- .sa_sigaction = sigbus_handler,
- .sa_flags = SA_SIGINFO,
- };
-
- n_installed++;
-
- if (n_installed == 1)
- assert_se(sigaction(SIGBUS, &sa, &old_sigaction) == 0);
-
- return;
-}
-
-void sigbus_reset(void) {
-
- if (n_installed <= 0)
- return;
-
- n_installed--;
-
- if (n_installed == 0)
- assert_se(sigaction(SIGBUS, &old_sigaction, NULL) == 0);
-
- return;
-}
diff --git a/src/basic/sigbus.h b/src/basic/sigbus.h
deleted file mode 100644
index 980243d9ce..0000000000
--- a/src/basic/sigbus.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 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/>.
-***/
-
-void sigbus_install(void);
-void sigbus_reset(void);
-
-int sigbus_pop(void **ret);
diff --git a/src/basic/signal-util.c b/src/basic/signal-util.c
deleted file mode 100644
index 280b5c3251..0000000000
--- a/src/basic/signal-util.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2015 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 <stdarg.h>
-#include <stdio.h>
-
-#include "macro.h"
-#include "parse-util.h"
-#include "signal-util.h"
-#include "stdio-util.h"
-#include "string-table.h"
-#include "string-util.h"
-
-int reset_all_signal_handlers(void) {
- static const struct sigaction sa = {
- .sa_handler = SIG_DFL,
- .sa_flags = SA_RESTART,
- };
- int sig, r = 0;
-
- for (sig = 1; sig < _NSIG; sig++) {
-
- /* These two cannot be caught... */
- if (sig == SIGKILL || sig == SIGSTOP)
- continue;
-
- /* 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 && r >= 0)
- r = -errno;
- }
-
- return r;
-}
-
-int reset_signal_mask(void) {
- sigset_t ss;
-
- if (sigemptyset(&ss) < 0)
- return -errno;
-
- if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0)
- return -errno;
-
- return 0;
-}
-
-static int sigaction_many_ap(const struct sigaction *sa, int sig, va_list ap) {
- int r = 0;
-
- /* negative signal ends the list. 0 signal is skipped. */
-
- if (sig < 0)
- return 0;
-
- if (sig > 0) {
- if (sigaction(sig, sa, NULL) < 0)
- r = -errno;
- }
-
- while ((sig = va_arg(ap, int)) >= 0) {
-
- if (sig == 0)
- continue;
-
- if (sigaction(sig, sa, NULL) < 0) {
- if (r >= 0)
- r = -errno;
- }
- }
-
- return r;
-}
-
-int sigaction_many(const struct sigaction *sa, ...) {
- va_list ap;
- int r;
-
- va_start(ap, sa);
- r = sigaction_many_ap(sa, 0, ap);
- va_end(ap);
-
- return r;
-}
-
-int ignore_signals(int sig, ...) {
-
- static const struct sigaction sa = {
- .sa_handler = SIG_IGN,
- .sa_flags = SA_RESTART,
- };
-
- va_list ap;
- int r;
-
- va_start(ap, sig);
- r = sigaction_many_ap(&sa, sig, ap);
- va_end(ap);
-
- return r;
-}
-
-int default_signals(int sig, ...) {
-
- static const struct sigaction sa = {
- .sa_handler = SIG_DFL,
- .sa_flags = SA_RESTART,
- };
-
- va_list ap;
- int r;
-
- va_start(ap, sig);
- r = sigaction_many_ap(&sa, sig, ap);
- va_end(ap);
-
- return r;
-}
-
-static int sigset_add_many_ap(sigset_t *ss, va_list ap) {
- int sig, r = 0;
-
- assert(ss);
-
- while ((sig = va_arg(ap, int)) >= 0) {
-
- if (sig == 0)
- continue;
-
- if (sigaddset(ss, sig) < 0) {
- if (r >= 0)
- r = -errno;
- }
- }
-
- return r;
-}
-
-int sigset_add_many(sigset_t *ss, ...) {
- va_list ap;
- int r;
-
- va_start(ap, ss);
- r = sigset_add_many_ap(ss, ap);
- va_end(ap);
-
- return r;
-}
-
-int sigprocmask_many(int how, sigset_t *old, ...) {
- va_list ap;
- sigset_t ss;
- int r;
-
- if (sigemptyset(&ss) < 0)
- return -errno;
-
- va_start(ap, old);
- r = sigset_add_many_ap(&ss, ap);
- va_end(ap);
-
- if (r < 0)
- return r;
-
- if (sigprocmask(how, &ss, old) < 0)
- return -errno;
-
- return 0;
-}
-
-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_local char buf[sizeof("RTMIN+")-1 + DECIMAL_STR_MAX(int) + 1];
- const char *name;
-
- name = __signal_to_string(signo);
- if (name)
- return name;
-
- if (signo >= SIGRTMIN && signo <= SIGRTMAX)
- xsprintf(buf, "RTMIN+%d", signo - SIGRTMIN);
- else
- xsprintf(buf, "%d", signo);
-
- 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 (SIGNAL_VALID(signo))
- return signo;
- }
- return -EINVAL;
-}
-
-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 nop_signal_handler(int sig) {
- /* nothing here */
-}
diff --git a/src/basic/signal-util.h b/src/basic/signal-util.h
deleted file mode 100644
index dfd6eb564d..0000000000
--- a/src/basic/signal-util.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010-2015 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 <signal.h>
-
-#include "macro.h"
-
-int reset_all_signal_handlers(void);
-int reset_signal_mask(void);
-
-int ignore_signals(int sig, ...);
-int default_signals(int sig, ...);
-int sigaction_many(const struct sigaction *sa, ...);
-
-int sigset_add_many(sigset_t *ss, ...);
-int sigprocmask_many(int how, sigset_t *old, ...);
-
-const char *signal_to_string(int i) _const_;
-int signal_from_string(const char *s) _pure_;
-
-int signal_from_string_try_harder(const char *s);
-
-void nop_signal_handler(int sig);
-
-static inline void block_signals_reset(sigset_t *ss) {
- assert_se(sigprocmask(SIG_SETMASK, ss, NULL) >= 0);
-}
-
-#define BLOCK_SIGNALS(...) \
- _cleanup_(block_signals_reset) _unused_ sigset_t _saved_sigset = ({ \
- sigset_t t; \
- assert_se(sigprocmask_many(SIG_BLOCK, &t, __VA_ARGS__, -1) >= 0); \
- t; \
- })
-
-static inline bool SIGNAL_VALID(int signo) {
- return signo > 0 && signo < _NSIG;
-}
diff --git a/src/basic/siphash24.c b/src/basic/siphash24.c
deleted file mode 100644
index 8c1cdc3db6..0000000000
--- a/src/basic/siphash24.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- SipHash reference C implementation
-
- Written in 2012 by
- Jean-Philippe Aumasson <jeanphilippe.aumasson@gmail.com>
- Daniel J. Bernstein <djb@cr.yp.to>
-
- To the extent possible under law, the author(s) have dedicated all copyright
- and related and neighboring rights to this software to the public domain
- worldwide. This software is distributed without any warranty.
-
- You should have received a copy of the CC0 Public Domain Dedication along with
- this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
-
- (Minimal changes made by Lennart Poettering, to make clean for inclusion in systemd)
- (Refactored by Tom Gundersen to split up in several functions and follow systemd
- coding style)
-*/
-
-#include <stdio.h>
-
-#include "macro.h"
-#include "siphash24.h"
-#include "unaligned.h"
-
-static inline uint64_t rotate_left(uint64_t x, uint8_t b) {
- assert(b < 64);
-
- return (x << b) | (x >> (64 - b));
-}
-
-static inline void sipround(struct siphash *state) {
- assert(state);
-
- state->v0 += state->v1;
- state->v1 = rotate_left(state->v1, 13);
- state->v1 ^= state->v0;
- state->v0 = rotate_left(state->v0, 32);
- state->v2 += state->v3;
- state->v3 = rotate_left(state->v3, 16);
- state->v3 ^= state->v2;
- state->v0 += state->v3;
- state->v3 = rotate_left(state->v3, 21);
- state->v3 ^= state->v0;
- state->v2 += state->v1;
- state->v1 = rotate_left(state->v1, 17);
- state->v1 ^= state->v2;
- state->v2 = rotate_left(state->v2, 32);
-}
-
-void siphash24_init(struct siphash *state, const uint8_t k[16]) {
- uint64_t k0, k1;
-
- assert(state);
- assert(k);
-
- k0 = unaligned_read_le64(k);
- k1 = unaligned_read_le64(k + 8);
-
- *state = (struct siphash) {
- /* "somepseudorandomlygeneratedbytes" */
- .v0 = 0x736f6d6570736575ULL ^ k0,
- .v1 = 0x646f72616e646f6dULL ^ k1,
- .v2 = 0x6c7967656e657261ULL ^ k0,
- .v3 = 0x7465646279746573ULL ^ k1,
- .padding = 0,
- .inlen = 0,
- };
-}
-
-void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
-
- const uint8_t *in = _in;
- const uint8_t *end = in + inlen;
- size_t left = state->inlen & 7;
- uint64_t m;
-
- assert(in);
- assert(state);
-
- /* Update total length */
- state->inlen += inlen;
-
- /* If padding exists, fill it out */
- if (left > 0) {
- for ( ; in < end && left < 8; in ++, left ++)
- state->padding |= ((uint64_t) *in) << (left * 8);
-
- if (in == end && left < 8)
- /* We did not have enough input to fill out the padding completely */
- return;
-
-#ifdef DEBUG
- printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
- printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
- printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
- printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
- printf("(%3zu) compress padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t)state->padding);
-#endif
-
- state->v3 ^= state->padding;
- sipround(state);
- sipround(state);
- state->v0 ^= state->padding;
-
- state->padding = 0;
- }
-
- end -= (state->inlen % sizeof(uint64_t));
-
- for ( ; in < end; in += 8) {
- m = unaligned_read_le64(in);
-#ifdef DEBUG
- printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
- printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
- printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
- printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
- printf("(%3zu) compress %08x %08x\n", state->inlen, (uint32_t) (m >> 32), (uint32_t) m);
-#endif
- state->v3 ^= m;
- sipround(state);
- sipround(state);
- state->v0 ^= m;
- }
-
- left = state->inlen & 7;
- switch (left) {
- case 7:
- state->padding |= ((uint64_t) in[6]) << 48;
- case 6:
- state->padding |= ((uint64_t) in[5]) << 40;
- case 5:
- state->padding |= ((uint64_t) in[4]) << 32;
- case 4:
- state->padding |= ((uint64_t) in[3]) << 24;
- case 3:
- state->padding |= ((uint64_t) in[2]) << 16;
- case 2:
- state->padding |= ((uint64_t) in[1]) << 8;
- case 1:
- state->padding |= ((uint64_t) in[0]);
- case 0:
- break;
- }
-}
-
-uint64_t siphash24_finalize(struct siphash *state) {
- uint64_t b;
-
- assert(state);
-
- b = state->padding | (((uint64_t) state->inlen) << 56);
-
-#ifdef DEBUG
- printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
- printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
- printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
- printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
- printf("(%3zu) padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t) state->padding);
-#endif
-
- state->v3 ^= b;
- sipround(state);
- sipround(state);
- state->v0 ^= b;
-
-#ifdef DEBUG
- printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
- printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
- printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
- printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
-#endif
- state->v2 ^= 0xff;
-
- sipround(state);
- sipround(state);
- sipround(state);
- sipround(state);
-
- return state->v0 ^ state->v1 ^ state->v2 ^ state->v3;
-}
-
-uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]) {
- struct siphash state;
-
- assert(in);
- assert(k);
-
- siphash24_init(&state, k);
- siphash24_compress(in, inlen, &state);
-
- return siphash24_finalize(&state);
-}
diff --git a/src/basic/siphash24.h b/src/basic/siphash24.h
deleted file mode 100644
index 54e2420cc6..0000000000
--- a/src/basic/siphash24.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-
-#include <inttypes.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-struct siphash {
- uint64_t v0;
- uint64_t v1;
- uint64_t v2;
- uint64_t v3;
- uint64_t padding;
- size_t inlen;
-};
-
-void siphash24_init(struct siphash *state, const uint8_t k[16]);
-void siphash24_compress(const void *in, size_t inlen, struct siphash *state);
-#define siphash24_compress_byte(byte, state) siphash24_compress((const uint8_t[]) { (byte) }, 1, (state))
-
-uint64_t siphash24_finalize(struct siphash *state);
-
-uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]);
diff --git a/src/basic/smack-util.c b/src/basic/smack-util.c
deleted file mode 100644
index 3a3df987df..0000000000
--- a/src/basic/smack-util.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Intel Corporation
-
- Author: Auke Kok <auke-jan.h.kok@intel.com>
-
- 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 <string.h>
-#include <sys/stat.h>
-#include <sys/xattr.h>
-#include <unistd.h>
-
-#include "alloc-util.h"
-#include "fileio.h"
-#include "log.h"
-#include "macro.h"
-#include "path-util.h"
-#include "process-util.h"
-#include "smack-util.h"
-#include "string-table.h"
-#include "xattr-util.h"
-
-#ifdef HAVE_SMACK
-bool mac_smack_use(void) {
- static int cached_use = -1;
-
- if (cached_use < 0)
- cached_use = access("/sys/fs/smackfs/", F_OK) >= 0;
-
- return cached_use;
-}
-
-static const char* const smack_attr_table[_SMACK_ATTR_MAX] = {
- [SMACK_ATTR_ACCESS] = "security.SMACK64",
- [SMACK_ATTR_EXEC] = "security.SMACK64EXEC",
- [SMACK_ATTR_MMAP] = "security.SMACK64MMAP",
- [SMACK_ATTR_TRANSMUTE] = "security.SMACK64TRANSMUTE",
- [SMACK_ATTR_IPIN] = "security.SMACK64IPIN",
- [SMACK_ATTR_IPOUT] = "security.SMACK64IPOUT",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(smack_attr, SmackAttr);
-
-int mac_smack_read(const char *path, SmackAttr attr, char **label) {
- assert(path);
- assert(attr >= 0 && attr < _SMACK_ATTR_MAX);
- assert(label);
-
- if (!mac_smack_use())
- return 0;
-
- return getxattr_malloc(path, smack_attr_to_string(attr), label, true);
-}
-
-int mac_smack_read_fd(int fd, SmackAttr attr, char **label) {
- assert(fd >= 0);
- assert(attr >= 0 && attr < _SMACK_ATTR_MAX);
- assert(label);
-
- if (!mac_smack_use())
- return 0;
-
- return fgetxattr_malloc(fd, smack_attr_to_string(attr), label);
-}
-
-int mac_smack_apply(const char *path, SmackAttr attr, const char *label) {
- int r;
-
- assert(path);
- assert(attr >= 0 && attr < _SMACK_ATTR_MAX);
-
- if (!mac_smack_use())
- return 0;
-
- if (label)
- r = lsetxattr(path, smack_attr_to_string(attr), label, strlen(label), 0);
- else
- r = lremovexattr(path, smack_attr_to_string(attr));
- if (r < 0)
- return -errno;
-
- return 0;
-}
-
-int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) {
- int r;
-
- assert(fd >= 0);
- assert(attr >= 0 && attr < _SMACK_ATTR_MAX);
-
- if (!mac_smack_use())
- return 0;
-
- if (label)
- r = fsetxattr(fd, smack_attr_to_string(attr), label, strlen(label), 0);
- else
- r = fremovexattr(fd, smack_attr_to_string(attr));
- if (r < 0)
- return -errno;
-
- return 0;
-}
-
-int mac_smack_apply_pid(pid_t pid, const char *label) {
- const char *p;
- int r = 0;
-
- assert(label);
-
- if (!mac_smack_use())
- return 0;
-
- p = procfs_file_alloca(pid, "attr/current");
- r = write_string_file(p, label, 0);
- if (r < 0)
- return r;
-
- return r;
-}
-
-int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
- struct stat st;
- int r = 0;
-
- assert(path);
-
- if (!mac_smack_use())
- return 0;
-
- /*
- * Path must be in /dev and must exist
- */
- if (!path_startswith(path, "/dev"))
- return 0;
-
- r = lstat(path, &st);
- if (r >= 0) {
- const char *label;
-
- /*
- * Label directories and character devices "*".
- * Label symlinks "_".
- * Don't change anything else.
- */
-
- if (S_ISDIR(st.st_mode))
- label = SMACK_STAR_LABEL;
- else if (S_ISLNK(st.st_mode))
- label = SMACK_FLOOR_LABEL;
- else if (S_ISCHR(st.st_mode))
- label = SMACK_STAR_LABEL;
- else
- return 0;
-
- r = lsetxattr(path, "security.SMACK64", label, strlen(label), 0);
-
- /* If the FS doesn't support labels, then exit without warning */
- if (r < 0 && errno == EOPNOTSUPP)
- return 0;
- }
-
- if (r < 0) {
- /* Ignore ENOENT in some cases */
- if (ignore_enoent && errno == ENOENT)
- return 0;
-
- if (ignore_erofs && errno == EROFS)
- return 0;
-
- r = log_debug_errno(errno, "Unable to fix SMACK label of %s: %m", path);
- }
-
- return r;
-}
-
-int mac_smack_copy(const char *dest, const char *src) {
- int r = 0;
- _cleanup_free_ char *label = NULL;
-
- assert(dest);
- assert(src);
-
- r = mac_smack_read(src, SMACK_ATTR_ACCESS, &label);
- if (r < 0)
- return r;
-
- r = mac_smack_apply(dest, SMACK_ATTR_ACCESS, label);
- if (r < 0)
- return r;
-
- return r;
-}
-
-#else
-bool mac_smack_use(void) {
- return false;
-}
-
-int mac_smack_read(const char *path, SmackAttr attr, char **label) {
- return -EOPNOTSUPP;
-}
-
-int mac_smack_read_fd(int fd, SmackAttr attr, char **label) {
- return -EOPNOTSUPP;
-}
-
-int mac_smack_apply(const char *path, SmackAttr attr, const char *label) {
- return 0;
-}
-
-int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) {
- return 0;
-}
-
-int mac_smack_apply_pid(pid_t pid, const char *label) {
- return 0;
-}
-
-int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
- return 0;
-}
-
-int mac_smack_copy(const char *dest, const char *src) {
- return 0;
-}
-#endif
diff --git a/src/basic/smack-util.h b/src/basic/smack-util.h
deleted file mode 100644
index f90ba0a027..0000000000
--- a/src/basic/smack-util.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Intel Corporation
-
- Author: Auke Kok <auke-jan.h.kok@intel.com>
-
- 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 <sys/types.h>
-
-#include "macro.h"
-
-#define SMACK_FLOOR_LABEL "_"
-#define SMACK_STAR_LABEL "*"
-
-typedef enum SmackAttr {
- SMACK_ATTR_ACCESS = 0,
- SMACK_ATTR_EXEC = 1,
- SMACK_ATTR_MMAP = 2,
- SMACK_ATTR_TRANSMUTE = 3,
- SMACK_ATTR_IPIN = 4,
- SMACK_ATTR_IPOUT = 5,
- _SMACK_ATTR_MAX,
- _SMACK_ATTR_INVALID = -1,
-} SmackAttr;
-
-bool mac_smack_use(void);
-
-int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
-
-const char* smack_attr_to_string(SmackAttr i) _const_;
-SmackAttr smack_attr_from_string(const char *s) _pure_;
-int mac_smack_read(const char *path, SmackAttr attr, char **label);
-int mac_smack_read_fd(int fd, SmackAttr attr, char **label);
-int mac_smack_apply(const char *path, SmackAttr attr, const char *label);
-int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label);
-int mac_smack_apply_pid(pid_t pid, const char *label);
-int mac_smack_copy(const char *dest, const char *src);
diff --git a/src/basic/socket-label.c b/src/basic/socket-label.c
deleted file mode 100644
index 6d1dc83874..0000000000
--- a/src/basic/socket-label.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/***
- 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 <netinet/in.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include "alloc-util.h"
-#include "fd-util.h"
-#include "log.h"
-#include "macro.h"
-#include "missing.h"
-#include "mkdir.h"
-#include "selinux-util.h"
-#include "socket-util.h"
-#include "umask-util.h"
-
-int socket_address_listen(
- const SocketAddress *a,
- int flags,
- int backlog,
- SocketAddressBindIPv6Only only,
- const char *bind_to_device,
- bool reuse_port,
- bool free_bind,
- bool transparent,
- mode_t directory_mode,
- mode_t socket_mode,
- const char *label) {
-
- _cleanup_close_ int fd = -1;
- int r, one;
-
- assert(a);
-
- r = socket_address_verify(a);
- if (r < 0)
- return r;
-
- if (socket_address_family(a) == AF_INET6 && !socket_ipv6_is_supported())
- return -EAFNOSUPPORT;
-
- if (label) {
- r = mac_selinux_create_socket_prepare(label);
- if (r < 0)
- return r;
- }
-
- fd = socket(socket_address_family(a), a->type | flags, a->protocol);
- r = fd < 0 ? -errno : 0;
-
- if (label)
- mac_selinux_create_socket_clear();
-
- if (r < 0)
- return r;
-
- if (socket_address_family(a) == AF_INET6 && only != SOCKET_ADDRESS_DEFAULT) {
- int flag = only == SOCKET_ADDRESS_IPV6_ONLY;
-
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag)) < 0)
- return -errno;
- }
-
- if (socket_address_family(a) == AF_INET || socket_address_family(a) == AF_INET6) {
- if (bind_to_device)
- if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, bind_to_device, strlen(bind_to_device)+1) < 0)
- return -errno;
-
- if (reuse_port) {
- one = 1;
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) < 0)
- log_warning_errno(errno, "SO_REUSEPORT failed: %m");
- }
-
- if (free_bind) {
- one = 1;
- if (setsockopt(fd, IPPROTO_IP, IP_FREEBIND, &one, sizeof(one)) < 0)
- log_warning_errno(errno, "IP_FREEBIND failed: %m");
- }
-
- if (transparent) {
- one = 1;
- if (setsockopt(fd, IPPROTO_IP, IP_TRANSPARENT, &one, sizeof(one)) < 0)
- log_warning_errno(errno, "IP_TRANSPARENT failed: %m");
- }
- }
-
- one = 1;
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
- return -errno;
-
- if (socket_address_family(a) == AF_UNIX && a->sockaddr.un.sun_path[0] != 0) {
- /* Create parents */
- (void) mkdir_parents_label(a->sockaddr.un.sun_path, directory_mode);
-
- /* Enforce the right access mode for the socket */
- RUN_WITH_UMASK(~socket_mode) {
- r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size);
- if (r == -EADDRINUSE) {
- /* Unlink and try again */
- unlink(a->sockaddr.un.sun_path);
- if (bind(fd, &a->sockaddr.sa, a->size) < 0)
- return -errno;
- } else if (r < 0)
- return r;
- }
- } else {
- if (bind(fd, &a->sockaddr.sa, a->size) < 0)
- return -errno;
- }
-
- if (socket_address_can_accept(a))
- if (listen(fd, backlog) < 0)
- return -errno;
-
- r = fd;
- fd = -1;
-
- return r;
-}
-
-int make_socket_fd(int log_level, const char* address, int type, int flags) {
- SocketAddress a;
- int fd, r;
-
- r = socket_address_parse(&a, address);
- if (r < 0)
- return log_error_errno(r, "Failed to parse socket address \"%s\": %m", address);
-
- a.type = type;
-
- fd = socket_address_listen(&a, type | flags, SOMAXCONN, SOCKET_ADDRESS_DEFAULT,
- NULL, false, false, false, 0755, 0644, NULL);
- if (fd < 0 || log_get_max_level() >= log_level) {
- _cleanup_free_ char *p = NULL;
-
- r = socket_address_print(&a, &p);
- if (r < 0)
- return log_error_errno(r, "socket_address_print(): %m");
-
- if (fd < 0)
- log_error_errno(fd, "Failed to listen on %s: %m", p);
- else
- log_full(log_level, "Listening on %s", p);
- }
-
- return fd;
-}
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
deleted file mode 100644
index 1662c04705..0000000000
--- a/src/basic/socket-util.c
+++ /dev/null
@@ -1,1079 +0,0 @@
-/***
- 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 <arpa/inet.h>
-#include <errno.h>
-#include <limits.h>
-#include <net/if.h>
-#include <netdb.h>
-#include <netinet/ip.h>
-#include <poll.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "alloc-util.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "formats-util.h"
-#include "log.h"
-#include "macro.h"
-#include "missing.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "socket-util.h"
-#include "string-table.h"
-#include "string-util.h"
-#include "strv.h"
-#include "user-util.h"
-#include "utf8.h"
-#include "util.h"
-
-int socket_address_parse(SocketAddress *a, const char *s) {
- char *e, *n;
- unsigned u;
- int r;
-
- assert(a);
- assert(s);
-
- zero(*a);
- a->type = SOCK_STREAM;
-
- if (*s == '[') {
- /* IPv6 in [x:.....:z]:p notation */
-
- e = strchr(s+1, ']');
- if (!e)
- return -EINVAL;
-
- n = strndupa(s+1, e-s-1);
-
- errno = 0;
- if (inet_pton(AF_INET6, n, &a->sockaddr.in6.sin6_addr) <= 0)
- return errno > 0 ? -errno : -EINVAL;
-
- e++;
- if (*e != ':')
- return -EINVAL;
-
- e++;
- r = safe_atou(e, &u);
- if (r < 0)
- return r;
-
- if (u <= 0 || u > 0xFFFF)
- return -EINVAL;
-
- a->sockaddr.in6.sin6_family = AF_INET6;
- a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
- a->size = sizeof(struct sockaddr_in6);
-
- } else if (*s == '/') {
- /* AF_UNIX socket */
-
- size_t l;
-
- l = strlen(s);
- if (l >= sizeof(a->sockaddr.un.sun_path))
- return -EINVAL;
-
- a->sockaddr.un.sun_family = AF_UNIX;
- memcpy(a->sockaddr.un.sun_path, s, l);
- a->size = offsetof(struct sockaddr_un, sun_path) + l + 1;
-
- } else if (*s == '@') {
- /* Abstract AF_UNIX socket */
- size_t l;
-
- l = strlen(s+1);
- if (l >= sizeof(a->sockaddr.un.sun_path) - 1)
- return -EINVAL;
-
- a->sockaddr.un.sun_family = AF_UNIX;
- memcpy(a->sockaddr.un.sun_path+1, s+1, l);
- a->size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
-
- } else {
- e = strchr(s, ':');
- if (e) {
- r = safe_atou(e+1, &u);
- if (r < 0)
- return r;
-
- if (u <= 0 || u > 0xFFFF)
- return -EINVAL;
-
- n = strndupa(s, e-s);
-
- /* IPv4 in w.x.y.z:p notation? */
- r = inet_pton(AF_INET, n, &a->sockaddr.in.sin_addr);
- if (r < 0)
- return -errno;
-
- if (r > 0) {
- /* Gotcha, it's a traditional IPv4 address */
- a->sockaddr.in.sin_family = AF_INET;
- a->sockaddr.in.sin_port = htobe16((uint16_t)u);
- a->size = sizeof(struct sockaddr_in);
- } else {
- unsigned idx;
-
- if (strlen(n) > IF_NAMESIZE-1)
- return -EINVAL;
-
- /* Uh, our last resort, an interface name */
- idx = if_nametoindex(n);
- if (idx == 0)
- return -EINVAL;
-
- a->sockaddr.in6.sin6_family = AF_INET6;
- a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
- a->sockaddr.in6.sin6_scope_id = idx;
- a->sockaddr.in6.sin6_addr = in6addr_any;
- a->size = sizeof(struct sockaddr_in6);
- }
- } else {
-
- /* Just a port */
- r = safe_atou(s, &u);
- if (r < 0)
- return r;
-
- if (u <= 0 || u > 0xFFFF)
- return -EINVAL;
-
- if (socket_ipv6_is_supported()) {
- a->sockaddr.in6.sin6_family = AF_INET6;
- a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
- a->sockaddr.in6.sin6_addr = in6addr_any;
- a->size = sizeof(struct sockaddr_in6);
- } else {
- a->sockaddr.in.sin_family = AF_INET;
- a->sockaddr.in.sin_port = htobe16((uint16_t)u);
- a->sockaddr.in.sin_addr.s_addr = INADDR_ANY;
- a->size = sizeof(struct sockaddr_in);
- }
- }
- }
-
- return 0;
-}
-
-int socket_address_parse_and_warn(SocketAddress *a, const char *s) {
- SocketAddress b;
- int r;
-
- /* Similar to socket_address_parse() but warns for IPv6 sockets when we don't support them. */
-
- r = socket_address_parse(&b, s);
- if (r < 0)
- return r;
-
- if (!socket_ipv6_is_supported() && b.sockaddr.sa.sa_family == AF_INET6) {
- log_warning("Binding to IPv6 address not available since kernel does not support IPv6.");
- return -EAFNOSUPPORT;
- }
-
- *a = b;
- return 0;
-}
-
-int socket_address_parse_netlink(SocketAddress *a, const char *s) {
- int family;
- unsigned group = 0;
- _cleanup_free_ char *sfamily = NULL;
- assert(a);
- assert(s);
-
- zero(*a);
- a->type = SOCK_RAW;
-
- errno = 0;
- if (sscanf(s, "%ms %u", &sfamily, &group) < 1)
- return errno > 0 ? -errno : -EINVAL;
-
- family = netlink_family_from_string(sfamily);
- if (family < 0)
- return -EINVAL;
-
- a->sockaddr.nl.nl_family = AF_NETLINK;
- a->sockaddr.nl.nl_groups = group;
-
- a->type = SOCK_RAW;
- a->size = sizeof(struct sockaddr_nl);
- a->protocol = family;
-
- return 0;
-}
-
-int socket_address_verify(const SocketAddress *a) {
- assert(a);
-
- switch (socket_address_family(a)) {
-
- case AF_INET:
- if (a->size != sizeof(struct sockaddr_in))
- return -EINVAL;
-
- if (a->sockaddr.in.sin_port == 0)
- return -EINVAL;
-
- if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
- return -EINVAL;
-
- return 0;
-
- case AF_INET6:
- if (a->size != sizeof(struct sockaddr_in6))
- return -EINVAL;
-
- if (a->sockaddr.in6.sin6_port == 0)
- return -EINVAL;
-
- if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
- return -EINVAL;
-
- return 0;
-
- case AF_UNIX:
- if (a->size < offsetof(struct sockaddr_un, sun_path))
- return -EINVAL;
-
- if (a->size > offsetof(struct sockaddr_un, sun_path)) {
-
- if (a->sockaddr.un.sun_path[0] != 0) {
- char *e;
-
- /* path */
- e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path));
- if (!e)
- return -EINVAL;
-
- if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1)
- return -EINVAL;
- }
- }
-
- if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM && a->type != SOCK_SEQPACKET)
- return -EINVAL;
-
- return 0;
-
- case AF_NETLINK:
-
- if (a->size != sizeof(struct sockaddr_nl))
- return -EINVAL;
-
- if (a->type != SOCK_RAW && a->type != SOCK_DGRAM)
- return -EINVAL;
-
- return 0;
-
- default:
- return -EAFNOSUPPORT;
- }
-}
-
-int socket_address_print(const SocketAddress *a, char **ret) {
- int r;
-
- assert(a);
- assert(ret);
-
- r = socket_address_verify(a);
- if (r < 0)
- return r;
-
- if (socket_address_family(a) == AF_NETLINK) {
- _cleanup_free_ char *sfamily = NULL;
-
- r = netlink_family_to_string_alloc(a->protocol, &sfamily);
- if (r < 0)
- return r;
-
- r = asprintf(ret, "%s %u", sfamily, a->sockaddr.nl.nl_groups);
- if (r < 0)
- return -ENOMEM;
-
- return 0;
- }
-
- return sockaddr_pretty(&a->sockaddr.sa, a->size, false, true, ret);
-}
-
-bool socket_address_can_accept(const SocketAddress *a) {
- assert(a);
-
- return
- a->type == SOCK_STREAM ||
- a->type == SOCK_SEQPACKET;
-}
-
-bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
- assert(a);
- assert(b);
-
- /* Invalid addresses are unequal to all */
- if (socket_address_verify(a) < 0 ||
- socket_address_verify(b) < 0)
- return false;
-
- if (a->type != b->type)
- return false;
-
- if (socket_address_family(a) != socket_address_family(b))
- return false;
-
- switch (socket_address_family(a)) {
-
- case AF_INET:
- if (a->sockaddr.in.sin_addr.s_addr != b->sockaddr.in.sin_addr.s_addr)
- return false;
-
- if (a->sockaddr.in.sin_port != b->sockaddr.in.sin_port)
- return false;
-
- break;
-
- case AF_INET6:
- if (memcmp(&a->sockaddr.in6.sin6_addr, &b->sockaddr.in6.sin6_addr, sizeof(a->sockaddr.in6.sin6_addr)) != 0)
- return false;
-
- if (a->sockaddr.in6.sin6_port != b->sockaddr.in6.sin6_port)
- return false;
-
- break;
-
- case AF_UNIX:
- if (a->size <= offsetof(struct sockaddr_un, sun_path) ||
- b->size <= offsetof(struct sockaddr_un, sun_path))
- return false;
-
- if ((a->sockaddr.un.sun_path[0] == 0) != (b->sockaddr.un.sun_path[0] == 0))
- return false;
-
- if (a->sockaddr.un.sun_path[0]) {
- if (!path_equal_or_files_same(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path))
- return false;
- } else {
- if (a->size != b->size)
- return false;
-
- if (memcmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, a->size) != 0)
- return false;
- }
-
- break;
-
- case AF_NETLINK:
- if (a->protocol != b->protocol)
- return false;
-
- if (a->sockaddr.nl.nl_groups != b->sockaddr.nl.nl_groups)
- return false;
-
- break;
-
- default:
- /* Cannot compare, so we assume the addresses are different */
- return false;
- }
-
- return true;
-}
-
-bool socket_address_is(const SocketAddress *a, const char *s, int type) {
- struct SocketAddress b;
-
- assert(a);
- assert(s);
-
- if (socket_address_parse(&b, s) < 0)
- return false;
-
- b.type = type;
-
- return socket_address_equal(a, &b);
-}
-
-bool socket_address_is_netlink(const SocketAddress *a, const char *s) {
- struct SocketAddress b;
-
- assert(a);
- assert(s);
-
- if (socket_address_parse_netlink(&b, s) < 0)
- return false;
-
- return socket_address_equal(a, &b);
-}
-
-const char* socket_address_get_path(const SocketAddress *a) {
- assert(a);
-
- if (socket_address_family(a) != AF_UNIX)
- return NULL;
-
- if (a->sockaddr.un.sun_path[0] == 0)
- return NULL;
-
- return a->sockaddr.un.sun_path;
-}
-
-bool socket_ipv6_is_supported(void) {
- if (access("/proc/net/if_inet6", F_OK) != 0)
- return false;
-
- return true;
-}
-
-bool socket_address_matches_fd(const SocketAddress *a, int fd) {
- SocketAddress b;
- socklen_t solen;
-
- assert(a);
- assert(fd >= 0);
-
- b.size = sizeof(b.sockaddr);
- if (getsockname(fd, &b.sockaddr.sa, &b.size) < 0)
- return false;
-
- if (b.sockaddr.sa.sa_family != a->sockaddr.sa.sa_family)
- return false;
-
- solen = sizeof(b.type);
- if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &b.type, &solen) < 0)
- return false;
-
- if (b.type != a->type)
- return false;
-
- if (a->protocol != 0) {
- solen = sizeof(b.protocol);
- if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &b.protocol, &solen) < 0)
- return false;
-
- if (b.protocol != a->protocol)
- return false;
- }
-
- return socket_address_equal(a, &b);
-}
-
-int sockaddr_port(const struct sockaddr *_sa) {
- union sockaddr_union *sa = (union sockaddr_union*) _sa;
-
- assert(sa);
-
- if (!IN_SET(sa->sa.sa_family, AF_INET, AF_INET6))
- return -EAFNOSUPPORT;
-
- return be16toh(sa->sa.sa_family == AF_INET6 ? sa->in6.sin6_port : sa->in.sin_port);
-}
-
-int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret) {
- union sockaddr_union *sa = (union sockaddr_union*) _sa;
- char *p;
- int r;
-
- assert(sa);
- assert(salen >= sizeof(sa->sa.sa_family));
-
- switch (sa->sa.sa_family) {
-
- case AF_INET: {
- uint32_t a;
-
- a = be32toh(sa->in.sin_addr.s_addr);
-
- if (include_port)
- r = asprintf(&p,
- "%u.%u.%u.%u:%u",
- a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
- be16toh(sa->in.sin_port));
- else
- r = asprintf(&p,
- "%u.%u.%u.%u",
- a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF);
- if (r < 0)
- return -ENOMEM;
- break;
- }
-
- case AF_INET6: {
- static const unsigned char ipv4_prefix[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
- };
-
- if (translate_ipv6 &&
- memcmp(&sa->in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) {
- const uint8_t *a = sa->in6.sin6_addr.s6_addr+12;
- if (include_port)
- r = asprintf(&p,
- "%u.%u.%u.%u:%u",
- a[0], a[1], a[2], a[3],
- be16toh(sa->in6.sin6_port));
- else
- r = asprintf(&p,
- "%u.%u.%u.%u",
- a[0], a[1], a[2], a[3]);
- if (r < 0)
- return -ENOMEM;
- } else {
- char a[INET6_ADDRSTRLEN];
-
- inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a));
-
- if (include_port) {
- r = asprintf(&p,
- "[%s]:%u",
- a,
- be16toh(sa->in6.sin6_port));
- if (r < 0)
- return -ENOMEM;
- } else {
- p = strdup(a);
- if (!p)
- return -ENOMEM;
- }
- }
-
- break;
- }
-
- case AF_UNIX:
- if (salen <= offsetof(struct sockaddr_un, sun_path)) {
- p = strdup("<unnamed>");
- if (!p)
- return -ENOMEM;
-
- } else if (sa->un.sun_path[0] == 0) {
- /* abstract */
-
- /* FIXME: We assume we can print the
- * socket path here and that it hasn't
- * more than one NUL byte. That is
- * actually an invalid assumption */
-
- p = new(char, sizeof(sa->un.sun_path)+1);
- if (!p)
- return -ENOMEM;
-
- p[0] = '@';
- memcpy(p+1, sa->un.sun_path+1, sizeof(sa->un.sun_path)-1);
- p[sizeof(sa->un.sun_path)] = 0;
-
- } else {
- p = strndup(sa->un.sun_path, sizeof(sa->un.sun_path));
- if (!p)
- return -ENOMEM;
- }
-
- break;
-
- default:
- return -EOPNOTSUPP;
- }
-
-
- *ret = p;
- return 0;
-}
-
-int getpeername_pretty(int fd, bool include_port, char **ret) {
- union sockaddr_union sa;
- socklen_t salen = sizeof(sa);
- int r;
-
- assert(fd >= 0);
- assert(ret);
-
- if (getpeername(fd, &sa.sa, &salen) < 0)
- return -errno;
-
- if (sa.sa.sa_family == AF_UNIX) {
- struct ucred ucred = {};
-
- /* UNIX connection sockets are anonymous, so let's use
- * PID/UID as pretty credentials instead */
-
- r = getpeercred(fd, &ucred);
- if (r < 0)
- return r;
-
- if (asprintf(ret, "PID "PID_FMT"/UID "UID_FMT, ucred.pid, ucred.uid) < 0)
- return -ENOMEM;
-
- return 0;
- }
-
- /* For remote sockets we translate IPv6 addresses back to IPv4
- * if applicable, since that's nicer. */
-
- return sockaddr_pretty(&sa.sa, salen, true, include_port, ret);
-}
-
-int getsockname_pretty(int fd, char **ret) {
- union sockaddr_union sa;
- socklen_t salen = sizeof(sa);
-
- assert(fd >= 0);
- assert(ret);
-
- if (getsockname(fd, &sa.sa, &salen) < 0)
- return -errno;
-
- /* For local sockets we do not translate IPv6 addresses back
- * to IPv6 if applicable, since this is usually used for
- * listening sockets where the difference between IPv4 and
- * IPv6 matters. */
-
- return sockaddr_pretty(&sa.sa, salen, false, true, ret);
-}
-
-int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret) {
- int r;
- char host[NI_MAXHOST], *ret;
-
- assert(_ret);
-
- r = getnameinfo(&sa->sa, salen, host, sizeof(host), NULL, 0,
- NI_IDN|NI_IDN_USE_STD3_ASCII_RULES);
- if (r != 0) {
- int saved_errno = errno;
-
- r = sockaddr_pretty(&sa->sa, salen, true, true, &ret);
- if (r < 0)
- return r;
-
- log_debug_errno(saved_errno, "getnameinfo(%s) failed: %m", ret);
- } else {
- ret = strdup(host);
- if (!ret)
- return -ENOMEM;
- }
-
- *_ret = ret;
- return 0;
-}
-
-int getnameinfo_pretty(int fd, char **ret) {
- union sockaddr_union sa;
- socklen_t salen = sizeof(sa);
-
- assert(fd >= 0);
- assert(ret);
-
- if (getsockname(fd, &sa.sa, &salen) < 0)
- return -errno;
-
- return socknameinfo_pretty(&sa, salen, ret);
-}
-
-int socket_address_unlink(SocketAddress *a) {
- assert(a);
-
- if (socket_address_family(a) != AF_UNIX)
- return 0;
-
- if (a->sockaddr.un.sun_path[0] == 0)
- return 0;
-
- if (unlink(a->sockaddr.un.sun_path) < 0)
- return -errno;
-
- return 1;
-}
-
-static const char* const netlink_family_table[] = {
- [NETLINK_ROUTE] = "route",
- [NETLINK_FIREWALL] = "firewall",
- [NETLINK_INET_DIAG] = "inet-diag",
- [NETLINK_NFLOG] = "nflog",
- [NETLINK_XFRM] = "xfrm",
- [NETLINK_SELINUX] = "selinux",
- [NETLINK_ISCSI] = "iscsi",
- [NETLINK_AUDIT] = "audit",
- [NETLINK_FIB_LOOKUP] = "fib-lookup",
- [NETLINK_CONNECTOR] = "connector",
- [NETLINK_NETFILTER] = "netfilter",
- [NETLINK_IP6_FW] = "ip6-fw",
- [NETLINK_DNRTMSG] = "dnrtmsg",
- [NETLINK_KOBJECT_UEVENT] = "kobject-uevent",
- [NETLINK_GENERIC] = "generic",
- [NETLINK_SCSITRANSPORT] = "scsitransport",
- [NETLINK_ECRYPTFS] = "ecryptfs"
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX);
-
-static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = {
- [SOCKET_ADDRESS_DEFAULT] = "default",
- [SOCKET_ADDRESS_BOTH] = "both",
- [SOCKET_ADDRESS_IPV6_ONLY] = "ipv6-only"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
-
-bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) {
- assert(a);
- assert(b);
-
- if (a->sa.sa_family != b->sa.sa_family)
- return false;
-
- if (a->sa.sa_family == AF_INET)
- return a->in.sin_addr.s_addr == b->in.sin_addr.s_addr;
-
- if (a->sa.sa_family == AF_INET6)
- return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)) == 0;
-
- return false;
-}
-
-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;
-
- /* If we have the privileges we will ignore the kernel limit. */
-
- value = (int) n;
- if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
- if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 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;
-
- /* If we have the privileges we will ignore the kernel limit. */
-
- value = (int) n;
- if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
- if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
- return -errno;
- return 1;
-}
-
-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);
-
-bool ifname_valid(const char *p) {
- bool numeric = true;
-
- /* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources
- * but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We
- * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */
-
- if (isempty(p))
- return false;
-
- if (strlen(p) >= IFNAMSIZ)
- return false;
-
- if (STR_IN_SET(p, ".", ".."))
- return false;
-
- while (*p) {
- if ((unsigned char) *p >= 127U)
- return false;
-
- if ((unsigned char) *p <= 32U)
- return false;
-
- if (*p == ':' || *p == '/')
- return false;
-
- numeric = numeric && (*p >= '0' && *p <= '9');
- p++;
- }
-
- if (numeric)
- return false;
-
- return true;
-}
-
-int getpeercred(int fd, struct ucred *ucred) {
- socklen_t n = sizeof(struct ucred);
- struct ucred u;
- int r;
-
- assert(fd >= 0);
- assert(ucred);
-
- r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n);
- if (r < 0)
- return -errno;
-
- if (n != sizeof(struct ucred))
- return -EIO;
-
- /* Check if the data is actually useful and not suppressed due
- * to namespacing issues */
- if (u.pid <= 0)
- return -ENODATA;
- if (u.uid == UID_INVALID)
- return -ENODATA;
- if (u.gid == GID_INVALID)
- return -ENODATA;
-
- *ucred = u;
- return 0;
-}
-
-int getpeersec(int fd, char **ret) {
- socklen_t n = 64;
- char *s;
- int r;
-
- assert(fd >= 0);
- assert(ret);
-
- s = new0(char, n);
- if (!s)
- return -ENOMEM;
-
- r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
- if (r < 0) {
- free(s);
-
- if (errno != ERANGE)
- return -errno;
-
- s = new0(char, n);
- if (!s)
- return -ENOMEM;
-
- r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
- if (r < 0) {
- free(s);
- return -errno;
- }
- }
-
- if (isempty(s)) {
- free(s);
- return -EOPNOTSUPP;
- }
-
- *ret = s;
- return 0;
-}
-
-int send_one_fd_sa(
- int transport_fd,
- int fd,
- const struct sockaddr *sa, socklen_t len,
- int flags) {
-
- union {
- struct cmsghdr cmsghdr;
- uint8_t buf[CMSG_SPACE(sizeof(int))];
- } control = {};
- struct msghdr mh = {
- .msg_name = (struct sockaddr*) sa,
- .msg_namelen = len,
- .msg_control = &control,
- .msg_controllen = sizeof(control),
- };
- struct cmsghdr *cmsg;
-
- assert(transport_fd >= 0);
- assert(fd >= 0);
-
- cmsg = CMSG_FIRSTHDR(&mh);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = CMSG_LEN(sizeof(int));
- memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
-
- mh.msg_controllen = CMSG_SPACE(sizeof(int));
- if (sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags) < 0)
- return -errno;
-
- return 0;
-}
-
-int receive_one_fd(int transport_fd, int flags) {
- union {
- struct cmsghdr cmsghdr;
- uint8_t buf[CMSG_SPACE(sizeof(int))];
- } control = {};
- struct msghdr mh = {
- .msg_control = &control,
- .msg_controllen = sizeof(control),
- };
- struct cmsghdr *cmsg, *found = NULL;
-
- assert(transport_fd >= 0);
-
- /*
- * Receive a single FD via @transport_fd. We don't care for
- * the transport-type. We retrieve a single FD at most, so for
- * packet-based transports, the caller must ensure to send
- * only a single FD per packet. This is best used in
- * combination with send_one_fd().
- */
-
- if (recvmsg(transport_fd, &mh, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC | flags) < 0)
- return -errno;
-
- CMSG_FOREACH(cmsg, &mh) {
- if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_RIGHTS &&
- cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
- assert(!found);
- found = cmsg;
- break;
- }
- }
-
- if (!found) {
- cmsg_close_all(&mh);
- return -EIO;
- }
-
- return *(int*) CMSG_DATA(found);
-}
-
-ssize_t next_datagram_size_fd(int fd) {
- ssize_t l;
- int k;
-
- /* This is a bit like FIONREAD/SIOCINQ, however a bit more powerful. The difference being: recv(MSG_PEEK) will
- * actually cause the next datagram in the queue to be validated regarding checksums, which FIONREAD doesn't
- * do. This difference is actually of major importance as we need to be sure that the size returned here
- * actually matches what we will read with recvmsg() next, as otherwise we might end up allocating a buffer of
- * the wrong size. */
-
- l = recv(fd, NULL, 0, MSG_PEEK|MSG_TRUNC);
- if (l < 0) {
- if (errno == EOPNOTSUPP || errno == EFAULT)
- goto fallback;
-
- return -errno;
- }
- if (l == 0)
- goto fallback;
-
- return l;
-
-fallback:
- k = 0;
-
- /* Some sockets (AF_PACKET) do not support null-sized recv() with MSG_TRUNC set, let's fall back to FIONREAD
- * for them. Checksums don't matter for raw sockets anyway, hence this should be fine. */
-
- if (ioctl(fd, FIONREAD, &k) < 0)
- return -errno;
-
- return (ssize_t) k;
-}
-
-int flush_accept(int fd) {
-
- struct pollfd pollfd = {
- .fd = fd,
- .events = POLLIN,
- };
- int r;
-
-
- /* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
-
- for (;;) {
- int cfd;
-
- r = poll(&pollfd, 1, 0);
- if (r < 0) {
- if (errno == EINTR)
- continue;
-
- return -errno;
-
- } else if (r == 0)
- return 0;
-
- cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
- if (cfd < 0) {
- if (errno == EINTR)
- continue;
-
- if (errno == EAGAIN)
- return 0;
-
- return -errno;
- }
-
- close(cfd);
- }
-}
-
-struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length) {
- struct cmsghdr *cmsg;
-
- assert(mh);
-
- CMSG_FOREACH(cmsg, mh)
- if (cmsg->cmsg_level == level &&
- cmsg->cmsg_type == type &&
- (length == (socklen_t) -1 || length == cmsg->cmsg_len))
- return cmsg;
-
- return NULL;
-}
-
-int socket_ioctl_fd(void) {
- int fd;
-
- /* Create a socket to invoke the various network interface ioctl()s on. Traditionally only AF_INET was good for
- * that. Since kernel 4.6 AF_NETLINK works for this too. We first try to use AF_INET hence, but if that's not
- * available (for example, because it is made unavailable via SECCOMP or such), we'll fall back to the more
- * generic AF_NETLINK. */
-
- fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0);
- if (fd < 0)
- fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_GENERIC);
- if (fd < 0)
- return -errno;
-
- return fd;
-}
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
deleted file mode 100644
index 2ef572badb..0000000000
--- a/src/basic/socket-util.h
+++ /dev/null
@@ -1,158 +0,0 @@
-#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 <netinet/ether.h>
-#include <netinet/in.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <linux/netlink.h>
-#include <linux/if_packet.h>
-
-#include "macro.h"
-#include "util.h"
-
-union sockaddr_union {
- struct sockaddr sa;
- struct sockaddr_in in;
- struct sockaddr_in6 in6;
- struct sockaddr_un un;
- struct sockaddr_nl nl;
- struct sockaddr_storage storage;
- struct sockaddr_ll ll;
-};
-
-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_and_warn(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) _pure_;
-int socket_address_unlink(SocketAddress *a);
-
-bool socket_address_can_accept(const SocketAddress *a) _pure_;
-
-int socket_address_listen(
- const SocketAddress *a,
- int flags,
- int backlog,
- SocketAddressBindIPv6Only only,
- const char *bind_to_device,
- bool reuse_port,
- bool free_bind,
- bool transparent,
- mode_t directory_mode,
- mode_t socket_mode,
- const char *label);
-int make_socket_fd(int log_level, const char* address, int type, int flags);
-
-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_matches_fd(const SocketAddress *a, int fd);
-
-bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) _pure_;
-
-const char* socket_address_get_path(const SocketAddress *a);
-
-bool socket_ipv6_is_supported(void);
-
-int sockaddr_port(const struct sockaddr *_sa) _pure_;
-
-int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret);
-int getpeername_pretty(int fd, bool include_port, char **ret);
-int getsockname_pretty(int fd, char **ret);
-
-int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret);
-int getnameinfo_pretty(int fd, char **ret);
-
-const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b) _const_;
-SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s) _pure_;
-
-int netlink_family_to_string_alloc(int b, char **s);
-int netlink_family_from_string(const char *s) _pure_;
-
-bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b);
-
-int fd_inc_sndbuf(int fd, size_t n);
-int fd_inc_rcvbuf(int fd, size_t n);
-
-int ip_tos_to_string_alloc(int i, char **s);
-int ip_tos_from_string(const char *s);
-
-bool ifname_valid(const char *p);
-
-int getpeercred(int fd, struct ucred *ucred);
-int getpeersec(int fd, char **ret);
-
-int send_one_fd_sa(int transport_fd,
- int fd,
- const struct sockaddr *sa, socklen_t len,
- int flags);
-#define send_one_fd(transport_fd, fd, flags) send_one_fd_sa(transport_fd, fd, NULL, 0, flags)
-int receive_one_fd(int transport_fd, int flags);
-
-ssize_t next_datagram_size_fd(int fd);
-
-int flush_accept(int fd);
-
-#define CMSG_FOREACH(cmsg, mh) \
- for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg)))
-
-struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length);
-
-/* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */
-#define SOCKADDR_UN_LEN(sa) \
- ({ \
- const struct sockaddr_un *_sa = &(sa); \
- assert(_sa->sun_family == AF_UNIX); \
- offsetof(struct sockaddr_un, sun_path) + \
- (_sa->sun_path[0] == 0 ? \
- 1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : \
- strnlen(_sa->sun_path, sizeof(_sa->sun_path))); \
- })
-
-int socket_ioctl_fd(void);
diff --git a/src/basic/sparse-endian.h b/src/basic/sparse-endian.h
deleted file mode 100644
index a3573b84a9..0000000000
--- a/src/basic/sparse-endian.h
+++ /dev/null
@@ -1,91 +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 <byteswap.h>
-#include <endian.h>
-#include <stdint.h>
-
-#ifdef __CHECKER__
-#define __sd_bitwise __attribute__((bitwise))
-#define __sd_force __attribute__((force))
-#else
-#define __sd_bitwise
-#define __sd_force
-#endif
-
-typedef uint16_t __sd_bitwise le16_t;
-typedef uint16_t __sd_bitwise be16_t;
-typedef uint32_t __sd_bitwise le32_t;
-typedef uint32_t __sd_bitwise be32_t;
-typedef uint64_t __sd_bitwise le64_t;
-typedef uint64_t __sd_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 __sd_force) bswap_16_on_be(value); }
-static inline le32_t htole32(uint32_t value) { return (le32_t __sd_force) bswap_32_on_be(value); }
-static inline le64_t htole64(uint64_t value) { return (le64_t __sd_force) bswap_64_on_be(value); }
-
-static inline be16_t htobe16(uint16_t value) { return (be16_t __sd_force) bswap_16_on_le(value); }
-static inline be32_t htobe32(uint32_t value) { return (be32_t __sd_force) bswap_32_on_le(value); }
-static inline be64_t htobe64(uint64_t value) { return (be64_t __sd_force) bswap_64_on_le(value); }
-
-static inline uint16_t le16toh(le16_t value) { return bswap_16_on_be((uint16_t __sd_force)value); }
-static inline uint32_t le32toh(le32_t value) { return bswap_32_on_be((uint32_t __sd_force)value); }
-static inline uint64_t le64toh(le64_t value) { return bswap_64_on_be((uint64_t __sd_force)value); }
-
-static inline uint16_t be16toh(be16_t value) { return bswap_16_on_le((uint16_t __sd_force)value); }
-static inline uint32_t be32toh(be32_t value) { return bswap_32_on_le((uint32_t __sd_force)value); }
-static inline uint64_t be64toh(be64_t value) { return bswap_64_on_le((uint64_t __sd_force)value); }
-
-#undef __sd_bitwise
-#undef __sd_force
-
-#endif /* SPARSE_ENDIAN_H */
diff --git a/src/basic/special.h b/src/basic/special.h
deleted file mode 100644
index 5276bcf598..0000000000
--- a/src/basic/special.h
+++ /dev/null
@@ -1,122 +0,0 @@
-#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/>.
-***/
-
-#define SPECIAL_DEFAULT_TARGET "default.target"
-
-/* Shutdown targets */
-#define SPECIAL_UMOUNT_TARGET "umount.target"
-/* This is not really intended to be started by directly. This is
- * mostly so that other targets (reboot/halt/poweroff) can depend on
- * it to bring all services down that want to be brought down on
- * system shutdown. */
-#define SPECIAL_SHUTDOWN_TARGET "shutdown.target"
-#define SPECIAL_HALT_TARGET "halt.target"
-#define SPECIAL_POWEROFF_TARGET "poweroff.target"
-#define SPECIAL_REBOOT_TARGET "reboot.target"
-#define SPECIAL_KEXEC_TARGET "kexec.target"
-#define SPECIAL_EXIT_TARGET "exit.target"
-#define SPECIAL_SUSPEND_TARGET "suspend.target"
-#define SPECIAL_HIBERNATE_TARGET "hibernate.target"
-#define SPECIAL_HYBRID_SLEEP_TARGET "hybrid-sleep.target"
-
-/* Special boot targets */
-#define SPECIAL_RESCUE_TARGET "rescue.target"
-#define SPECIAL_EMERGENCY_TARGET "emergency.target"
-#define SPECIAL_MULTI_USER_TARGET "multi-user.target"
-#define SPECIAL_GRAPHICAL_TARGET "graphical.target"
-
-/* Early boot targets */
-#define SPECIAL_SYSINIT_TARGET "sysinit.target"
-#define SPECIAL_SOCKETS_TARGET "sockets.target"
-#define SPECIAL_BUSNAMES_TARGET "busnames.target"
-#define SPECIAL_TIMERS_TARGET "timers.target"
-#define SPECIAL_PATHS_TARGET "paths.target"
-#define SPECIAL_LOCAL_FS_TARGET "local-fs.target"
-#define SPECIAL_LOCAL_FS_PRE_TARGET "local-fs-pre.target"
-#define SPECIAL_INITRD_FS_TARGET "initrd-fs.target"
-#define SPECIAL_INITRD_ROOT_DEVICE_TARGET "initrd-root-device.target"
-#define SPECIAL_INITRD_ROOT_FS_TARGET "initrd-root-fs.target"
-#define SPECIAL_REMOTE_FS_TARGET "remote-fs.target" /* LSB's $remote_fs */
-#define SPECIAL_REMOTE_FS_PRE_TARGET "remote-fs-pre.target"
-#define SPECIAL_SWAP_TARGET "swap.target"
-#define SPECIAL_NETWORK_ONLINE_TARGET "network-online.target"
-#define SPECIAL_TIME_SYNC_TARGET "time-sync.target" /* LSB's $time */
-#define SPECIAL_BASIC_TARGET "basic.target"
-
-/* LSB compatibility */
-#define SPECIAL_NETWORK_TARGET "network.target" /* LSB's $network */
-#define SPECIAL_NSS_LOOKUP_TARGET "nss-lookup.target" /* LSB's $named */
-#define SPECIAL_RPCBIND_TARGET "rpcbind.target" /* LSB's $portmap */
-
-/*
- * Rules regarding adding further high level targets like the above:
- *
- * - Be conservative, only add more of these when we really need
- * them. We need strong usecases for further additions.
- *
- * - When there can be multiple implementations running side-by-side,
- * it needs to be a .target unit which can pull in all
- * implementations.
- *
- * - If something can be implemented with socket activation, and
- * without, it needs to be a .target unit, so that it can pull in
- * the appropriate unit.
- *
- * - Otherwise, it should be a .service unit.
- *
- * - In some cases it is OK to have both a .service and a .target
- * unit, i.e. if there can be multiple parallel implementations, but
- * only one is the "system" one. Example: syslog.
- *
- * Or to put this in other words: .service symlinks can be used to
- * arbitrate between multiple implementations if there can be only one
- * of a kind. .target units can be used to support multiple
- * implementations that can run side-by-side.
- */
-
-/* Magic early boot services */
-#define SPECIAL_FSCK_SERVICE "systemd-fsck@.service"
-#define SPECIAL_QUOTACHECK_SERVICE "systemd-quotacheck.service"
-#define SPECIAL_QUOTAON_SERVICE "quotaon.service"
-#define SPECIAL_REMOUNT_FS_SERVICE "systemd-remount-fs.service"
-
-/* Services systemd relies on */
-#define SPECIAL_DBUS_SERVICE "dbus.service"
-#define SPECIAL_DBUS_SOCKET "dbus.socket"
-#define SPECIAL_JOURNALD_SOCKET "systemd-journald.socket"
-#define SPECIAL_JOURNALD_SERVICE "systemd-journald.service"
-
-/* Magic init signals */
-#define SPECIAL_KBREQUEST_TARGET "kbrequest.target"
-#define SPECIAL_SIGPWR_TARGET "sigpwr.target"
-#define SPECIAL_CTRL_ALT_DEL_TARGET "ctrl-alt-del.target"
-
-/* Where we add all our system units, users and machines by default */
-#define SPECIAL_SYSTEM_SLICE "system.slice"
-#define SPECIAL_USER_SLICE "user.slice"
-#define SPECIAL_MACHINE_SLICE "machine.slice"
-#define SPECIAL_ROOT_SLICE "-.slice"
-
-/* The scope unit systemd itself lives in. */
-#define SPECIAL_INIT_SCOPE "init.scope"
-
-/* The root directory. */
-#define SPECIAL_ROOT_MOUNT "-.mount"
diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c
deleted file mode 100644
index 309e84b93d..0000000000
--- a/src/basic/stat-util.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/***
- 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 <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <linux/magic.h>
-#include <sys/statvfs.h>
-#include <unistd.h>
-
-#include "dirent-util.h"
-#include "fd-util.h"
-#include "macro.h"
-#include "missing.h"
-#include "stat-util.h"
-#include "string-util.h"
-
-int is_symlink(const char *path) {
- struct stat info;
-
- assert(path);
-
- if (lstat(path, &info) < 0)
- return -errno;
-
- return !!S_ISLNK(info.st_mode);
-}
-
-int is_dir(const char* path, bool follow) {
- struct stat st;
- int r;
-
- assert(path);
-
- if (follow)
- r = stat(path, &st);
- else
- r = lstat(path, &st);
- if (r < 0)
- return -errno;
-
- return !!S_ISDIR(st.st_mode);
-}
-
-int is_device_node(const char *path) {
- struct stat info;
-
- assert(path);
-
- if (lstat(path, &info) < 0)
- return -errno;
-
- return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode));
-}
-
-int dir_is_empty(const char *path) {
- _cleanup_closedir_ DIR *d;
- struct dirent *de;
-
- d = opendir(path);
- if (!d)
- return -errno;
-
- FOREACH_DIRENT(de, d, return -errno)
- return 0;
-
- return 1;
-}
-
-bool null_or_empty(struct stat *st) {
- assert(st);
-
- if (S_ISREG(st->st_mode) && st->st_size <= 0)
- return true;
-
- /* We don't want to hardcode the major/minor of /dev/null,
- * hence we do a simpler "is this a device node?" check. */
-
- 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);
-}
-
-int null_or_empty_fd(int fd) {
- struct stat st;
-
- assert(fd >= 0);
-
- if (fstat(fd, &st) < 0)
- return -errno;
-
- return null_or_empty(&st);
-}
-
-int path_is_read_only_fs(const char *path) {
- struct statvfs st;
-
- assert(path);
-
- if (statvfs(path, &st) < 0)
- return -errno;
-
- if (st.f_flag & ST_RDONLY)
- return true;
-
- /* On NFS, statvfs() might not reflect whether we can actually
- * write to the remote share. Let's try again with
- * access(W_OK) which is more reliable, at least sometimes. */
- if (access(path, W_OK) < 0 && errno == EROFS)
- return true;
-
- return false;
-}
-
-int path_is_os_tree(const char *path) {
- char *p;
- int r;
-
- assert(path);
-
- /* We use /usr/lib/os-release as flag file if something is an OS */
- p = strjoina(path, "/usr/lib/os-release");
- r = access(p, F_OK);
- if (r >= 0)
- return 1;
-
- /* Also check for the old location in /etc, just in case. */
- p = strjoina(path, "/etc/os-release");
- r = access(p, F_OK);
-
- return r >= 0;
-}
-
-int files_same(const char *filea, const char *fileb) {
- struct stat a, b;
-
- assert(filea);
- assert(fileb);
-
- if (stat(filea, &a) < 0)
- return -errno;
-
- if (stat(fileb, &b) < 0)
- return -errno;
-
- return a.st_dev == b.st_dev &&
- a.st_ino == b.st_ino;
-}
-
-bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
- assert(s);
- assert_cc(sizeof(statfs_f_type_t) >= sizeof(s->f_type));
-
- return F_TYPE_EQUAL(s->f_type, magic_value);
-}
-
-int fd_check_fstype(int fd, statfs_f_type_t magic_value) {
- struct statfs s;
-
- if (fstatfs(fd, &s) < 0)
- return -errno;
-
- return is_fs_type(&s, magic_value);
-}
-
-int path_check_fstype(const char *path, statfs_f_type_t magic_value) {
- _cleanup_close_ int fd = -1;
-
- fd = open(path, O_RDONLY);
- if (fd < 0)
- return -errno;
-
- return fd_check_fstype(fd, magic_value);
-}
-
-bool is_temporary_fs(const struct statfs *s) {
- return is_fs_type(s, TMPFS_MAGIC) ||
- is_fs_type(s, RAMFS_MAGIC);
-}
-
-int fd_is_temporary_fs(int fd) {
- struct statfs s;
-
- if (fstatfs(fd, &s) < 0)
- return -errno;
-
- return is_temporary_fs(&s);
-}
diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h
deleted file mode 100644
index 56d28f791e..0000000000
--- a/src/basic/stat-util.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#pragma once
-
-/***
- 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>
-#include <stddef.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <sys/types.h>
-#include <sys/vfs.h>
-
-#include "macro.h"
-
-int is_symlink(const char *path);
-int is_dir(const char *path, bool follow);
-int is_device_node(const char *path);
-
-int dir_is_empty(const char *path);
-
-static inline int dir_is_populated(const char *path) {
- int r;
- r = dir_is_empty(path);
- if (r < 0)
- return r;
- return !r;
-}
-
-bool null_or_empty(struct stat *st) _pure_;
-int null_or_empty_path(const char *fn);
-int null_or_empty_fd(int fd);
-
-int path_is_read_only_fs(const char *path);
-int path_is_os_tree(const char *path);
-
-int files_same(const char *filea, const char *fileb);
-
-/* The .f_type field of struct statfs is really weird defined on
- * different archs. Let's give its type a name. */
-typedef typeof(((struct statfs*)NULL)->f_type) statfs_f_type_t;
-
-bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) _pure_;
-int fd_check_fstype(int fd, statfs_f_type_t magic_value);
-int path_check_fstype(const char *path, statfs_f_type_t magic_value);
-
-bool is_temporary_fs(const struct statfs *s) _pure_;
-int fd_is_temporary_fs(int fd);
-
-/* Because statfs.t_type can be int on some architectures, we have to cast
- * the const magic to the type, otherwise the compiler warns about
- * signed/unsigned comparison, because the magic can be 32 bit unsigned.
- */
-#define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b)
diff --git a/src/basic/stdio-util.h b/src/basic/stdio-util.h
deleted file mode 100644
index bd1144b4c9..0000000000
--- a/src/basic/stdio-util.h
+++ /dev/null
@@ -1,76 +0,0 @@
-#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 <printf.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/types.h>
-
-#include "macro.h"
-
-#define xsprintf(buf, fmt, ...) \
- assert_message_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf), "xsprintf: " #buf "[] must be big enough")
-
-
-#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)
diff --git a/src/basic/strbuf.c b/src/basic/strbuf.c
deleted file mode 100644
index 00aaf9e621..0000000000
--- a/src/basic/strbuf.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/***
- 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 <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "alloc-util.h"
-#include "strbuf.h"
-
-/*
- * Strbuf stores given strings in a single continuous 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);
- return mfree(str);
-}
-
-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 struct strbuf_child_entry *n1,
- const struct strbuf_child_entry *n2) {
- return n1->c - n2->c;
-}
-
-static void bubbleinsert(struct strbuf_node *node,
- uint8_t c,
- struct strbuf_node *node_child) {
-
- struct strbuf_child_entry new = {
- .c = c,
- .child = node_child,
- };
- int left = 0, right = node->children_count;
-
- while (right > left) {
- int middle = (right + left) / 2 ;
- if (strbuf_children_cmp(&node->children[middle], &new) <= 0)
- left = middle + 1;
- else
- right = middle;
- }
-
- memmove(node->children + left + 1, node->children + left,
- sizeof(struct strbuf_child_entry) * (node->children_count - left));
- node->children[left] = new;
-
- node->children_count++;
-}
-
-/* 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;
- }
-
- c = s[len - 1 - depth];
-
- /* bsearch is not allowed on a NULL sequence */
- if (node->children_count == 0)
- break;
-
- /* lookup child node */
- search.c = c;
- child = bsearch(&search, node->children, node->children_count,
- sizeof(struct strbuf_child_entry),
- (__compar_fn_t) 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;
- 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) {
- free(node_child);
- return -ENOMEM;
- }
-
- str->nodes_count++;
-
- node->children = child;
- bubbleinsert(node, c, node_child);
-
- return off;
-}
diff --git a/src/basic/strbuf.h b/src/basic/strbuf.h
deleted file mode 100644
index a1632da0e8..0000000000
--- a/src/basic/strbuf.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#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 <stddef.h>
-#include <stdint.h>
-#include <sys/types.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/basic/string-table.c b/src/basic/string-table.c
deleted file mode 100644
index a1499ab126..0000000000
--- a/src/basic/string-table.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/***
- 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 "string-table.h"
-#include "string-util.h"
-
-ssize_t string_table_lookup(const char * const *table, size_t len, const char *key) {
- size_t i;
-
- if (!key)
- return -1;
-
- for (i = 0; i < len; ++i)
- if (streq_ptr(table[i], key))
- return (ssize_t) i;
-
- return -1;
-}
diff --git a/src/basic/string-table.h b/src/basic/string-table.h
deleted file mode 100644
index 369610efc8..0000000000
--- a/src/basic/string-table.h
+++ /dev/null
@@ -1,119 +0,0 @@
-
-#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 <errno.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include "macro.h"
-#include "parse-util.h"
-#include "string-util.h"
-
-ssize_t string_table_lookup(const char * const *table, size_t len, const char *key);
-
-/* For basic lookup tables with strictly enumerated entries */
-#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(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]; \
- }
-
-#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \
- scope type name##_from_string(const char *s) { \
- return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
- }
-
-#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
- scope type name##_from_string(const char *s) { \
- int b; \
- if (!s) \
- return -1; \
- b = parse_boolean(s); \
- if (b == 0) \
- return (type) 0; \
- else if (b > 0) \
- return yes; \
- return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
- }
-
-#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,scope) \
- scope int name##_to_string_alloc(type i, char **str) { \
- char *s; \
- if (i < 0 || i > max) \
- return -ERANGE; \
- if (i < (type) ELEMENTSOF(name##_table)) { \
- s = strdup(name##_table[i]); \
- if (!s) \
- return -ENOMEM; \
- } else { \
- if (asprintf(&s, "%i", i) < 0) \
- return -ENOMEM; \
- } \
- *str = s; \
- return 0; \
- }
-
-#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,scope) \
- type name##_from_string(const char *s) { \
- type i; \
- unsigned u = 0; \
- if (!s) \
- return (type) -1; \
- for (i = 0; i < (type) ELEMENTSOF(name##_table); i++) \
- if (streq_ptr(name##_table[i], s)) \
- return i; \
- if (safe_atou(s, &u) >= 0 && u <= max) \
- return (type) u; \
- return (type) -1; \
- } \
-
-
-#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \
- _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
- _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \
- struct __useless_struct_to_allow_trailing_semicolon__
-
-#define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope) \
- _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
- _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
- 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)
-#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static)
-#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static)
-
-#define DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,)
-
-/* For string conversions where numbers are also acceptable */
-#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \
- _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,) \
- _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,) \
- struct __useless_struct_to_allow_trailing_semicolon__
-
-#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max) \
- _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,static)
-#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max) \
- _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,static)
diff --git a/src/basic/string-util.c b/src/basic/string-util.c
deleted file mode 100644
index 6b06e643c9..0000000000
--- a/src/basic/string-util.c
+++ /dev/null
@@ -1,868 +0,0 @@
-/***
- 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 <stdarg.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "alloc-util.h"
-#include "gunicode.h"
-#include "macro.h"
-#include "string-util.h"
-#include "utf8.h"
-#include "util.h"
-
-int strcmp_ptr(const char *a, const char *b) {
-
- /* Like strcmp(), but tries to make sense of NULL pointers */
- if (a && b)
- return strcmp(a, b);
-
- if (!a && b)
- return -1;
-
- if (a && !b)
- return 1;
-
- return 0;
-}
-
-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* endswith_no_case(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 (strcasecmp(s + sl - pl, postfix) != 0)
- return NULL;
-
- return (char*) s + sl - pl;
-}
-
-char* first_word(const char *s, const char *word) {
- size_t sl, wl;
- const char *p;
-
- assert(s);
- assert(word);
-
- /* Checks if the string starts with the specified word, either
- * followed by NUL or by whitespace. Returns a pointer to the
- * NUL or the first character after the whitespace. */
-
- sl = strlen(s);
- wl = strlen(word);
-
- if (sl < wl)
- return NULL;
-
- if (wl == 0)
- return (char*) s;
-
- if (memcmp(s, word, wl) != 0)
- return NULL;
-
- p = s + wl;
- if (*p == 0)
- return (char*) p;
-
- if (!strchr(WHITESPACE, *p))
- return NULL;
-
- p += strspn(p, WHITESPACE);
- return (char*) p;
-}
-
-static size_t strcspn_escaped(const char *s, const char *reject) {
- bool escaped = false;
- int n;
-
- for (n=0; s[n]; n++) {
- if (escaped)
- escaped = false;
- else if (s[n] == '\\')
- escaped = true;
- else if (strchr(reject, s[n]))
- break;
- }
-
- /* if s ends in \, return index of previous char */
- return n - escaped;
-}
-
-/* Split a string into words. */
-const char* split(const char **state, size_t *l, const char *separator, bool quoted) {
- const char *current;
-
- current = *state;
-
- if (!*current) {
- assert(**state == '\0');
- return NULL;
- }
-
- current += strspn(current, separator);
- if (!*current) {
- *state = current;
- return NULL;
- }
-
- if (quoted && strchr("\'\"", *current)) {
- char quotechars[2] = {*current, '\0'};
-
- *l = strcspn_escaped(current + 1, quotechars);
- if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] ||
- (current[*l + 2] && !strchr(separator, current[*l + 2]))) {
- /* right quote missing or garbage at the end */
- *state = current;
- return NULL;
- }
- *state = current++ + *l + 2;
- } else if (quoted) {
- *l = strcspn_escaped(current, separator);
- if (current[*l] && !strchr(separator, current[*l])) {
- /* unfinished escape */
- *state = current;
- return NULL;
- }
- *state = current + *l;
- } else {
- *l = strcspn(current, separator);
- *state = current + *l;
- }
-
- return current;
-}
-
-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);
-}
-
-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;
-}
-
-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;
-}
-
-char *truncate_nl(char *s) {
- assert(s);
-
- s[strcspn(s, NEWLINE)] = 0;
- return s;
-}
-
-char ascii_tolower(char x) {
-
- if (x >= 'A' && x <= 'Z')
- return x - 'A' + 'a';
-
- return x;
-}
-
-char ascii_toupper(char x) {
-
- if (x >= 'a' && x <= 'z')
- return x - 'a' + 'A';
-
- return x;
-}
-
-char *ascii_strlower(char *t) {
- char *p;
-
- assert(t);
-
- for (p = t; *p; p++)
- *p = ascii_tolower(*p);
-
- return t;
-}
-
-char *ascii_strupper(char *t) {
- char *p;
-
- assert(t);
-
- for (p = t; *p; p++)
- *p = ascii_toupper(*p);
-
- return t;
-}
-
-char *ascii_strlower_n(char *t, size_t n) {
- size_t i;
-
- if (n <= 0)
- return t;
-
- for (i = 0; i < n; i++)
- t[i] = ascii_tolower(t[i]);
-
- return t;
-}
-
-int ascii_strcasecmp_n(const char *a, const char *b, size_t n) {
-
- for (; n > 0; a++, b++, n--) {
- int x, y;
-
- x = (int) (uint8_t) ascii_tolower(*a);
- y = (int) (uint8_t) ascii_tolower(*b);
-
- if (x != y)
- return x - y;
- }
-
- return 0;
-}
-
-int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m) {
- int r;
-
- r = ascii_strcasecmp_n(a, b, MIN(n, m));
- if (r != 0)
- return r;
-
- if (n < m)
- return -1;
- else if (n > m)
- return 1;
- else
- return 0;
-}
-
-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;
-}
-
-bool string_has_cc(const char *p, const char *ok) {
- const char *t;
-
- assert(p);
-
- /*
- * Check if a string contains control characters. If 'ok' is
- * non-NULL it may be a string containing additional CCs to be
- * considered OK.
- */
-
- for (t = p; *t; t++) {
- if (ok && strchr(ok, *t))
- continue;
-
- if (*t > 0 && *t < ' ')
- return true;
-
- if (*t == 127)
- return true;
- }
-
- return false;
-}
-
-static char *ascii_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+3);
- if (!r)
- return NULL;
-
- x = (new_length * percent) / 100;
-
- if (x > new_length - 3)
- x = new_length - 3;
-
- memcpy(r, s, x);
- r[x] = 0xe2; /* tri-dot ellipsis: … */
- r[x+1] = 0x80;
- r[x+2] = 0xa6;
- memcpy(r + x + 3,
- s + old_length - (new_length - x - 1),
- new_length - x - 1);
-
- return r;
-}
-
-char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
- size_t x;
- char *e;
- const char *i, *j;
- unsigned k, len, len2;
- int r;
-
- assert(s);
- assert(percent <= 100);
- assert(new_length >= 3);
-
- /* if no multibyte characters use ascii_ellipsize_mem for speed */
- if (ascii_is_valid(s))
- return ascii_ellipsize_mem(s, old_length, new_length, percent);
-
- if (old_length <= 3 || old_length <= new_length)
- return strndup(s, old_length);
-
- x = (new_length * percent) / 100;
-
- if (x > new_length - 3)
- x = new_length - 3;
-
- k = 0;
- for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) {
- char32_t c;
-
- r = utf8_encoded_to_unichar(i, &c);
- if (r < 0)
- return NULL;
- k += unichar_iswide(c) ? 2 : 1;
- }
-
- if (k > x) /* last character was wide and went over quota */
- x++;
-
- for (j = s + old_length; k < new_length && j > i; ) {
- char32_t c;
-
- j = utf8_prev_char(j);
- r = utf8_encoded_to_unichar(j, &c);
- if (r < 0)
- return NULL;
- k += unichar_iswide(c) ? 2 : 1;
- }
- assert(i <= j);
-
- /* we don't actually need to ellipsize */
- if (i == j)
- return memdup(s, old_length + 1);
-
- /* make space for ellipsis */
- j = utf8_next_char(j);
-
- len = i - s;
- len2 = s + old_length - j;
- e = new(char, len + 3 + len2 + 1);
- if (!e)
- return NULL;
-
- /*
- printf("old_length=%zu new_length=%zu x=%zu len=%u len2=%u k=%u\n",
- old_length, new_length, x, len, len2, k);
- */
-
- memcpy(e, s, len);
- e[len] = 0xe2; /* tri-dot ellipsis: … */
- e[len + 1] = 0x80;
- e[len + 2] = 0xa6;
-
- memcpy(e + len + 3, j, len2 + 1);
-
- return e;
-}
-
-char *ellipsize(const char *s, size_t length, unsigned percent) {
- return ellipsize_mem(s, strlen(s), length, percent);
-}
-
-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;
-}
-
-char* strshorten(char *s, size_t l) {
- assert(s);
-
- if (l < strlen(s))
- s[l] = 0;
-
- return s;
-}
-
-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:
- return mfree(r);
-}
-
-char *strip_tab_ansi(char **ibuf, size_t *_isz) {
- const char *i, *begin = NULL;
- enum {
- STATE_OTHER,
- STATE_ESCAPE,
- STATE_BRACKET
- } state = STATE_OTHER;
- char *obuf = NULL;
- size_t osz = 0, isz;
- FILE *f;
-
- assert(ibuf);
- assert(*ibuf);
-
- /* Strips ANSI color and replaces TABs by 8 spaces */
-
- isz = _isz ? *_isz : strlen(*ibuf);
-
- f = open_memstream(&obuf, &osz);
- if (!f)
- return NULL;
-
- for (i = *ibuf; i < *ibuf + isz + 1; i++) {
-
- switch (state) {
-
- case STATE_OTHER:
- if (i >= *ibuf + isz) /* EOT */
- break;
- else if (*i == '\x1B')
- state = STATE_ESCAPE;
- else if (*i == '\t')
- fputs(" ", f);
- else
- fputc(*i, f);
- break;
-
- case STATE_ESCAPE:
- if (i >= *ibuf + isz) { /* EOT */
- fputc('\x1B', f);
- break;
- } else if (*i == '[') {
- state = STATE_BRACKET;
- begin = i + 1;
- } else {
- fputc('\x1B', f);
- fputc(*i, f);
- state = STATE_OTHER;
- }
-
- break;
-
- case STATE_BRACKET:
-
- if (i >= *ibuf + isz || /* EOT */
- (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) {
- fputc('\x1B', f);
- fputc('[', f);
- state = STATE_OTHER;
- i = begin-1;
- } else if (*i == 'm')
- state = STATE_OTHER;
- break;
- }
- }
-
- if (ferror(f)) {
- fclose(f);
- return mfree(obuf);
- }
-
- fclose(f);
-
- free(*ibuf);
- *ibuf = obuf;
-
- if (_isz)
- *_isz = osz;
-
- return obuf;
-}
-
-char *strextend(char **x, ...) {
- va_list ap;
- size_t f, l;
- char *r, *p;
-
- assert(x);
-
- l = f = *x ? strlen(*x) : 0;
-
- va_start(ap, 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;
- }
- va_end(ap);
-
- r = realloc(*x, l+1);
- if (!r)
- return NULL;
-
- p = r + f;
-
- va_start(ap, x);
- for (;;) {
- const char *t;
-
- t = va_arg(ap, const char *);
- if (!t)
- break;
-
- p = stpcpy(p, t);
- }
- va_end(ap);
-
- *p = 0;
- *x = r;
-
- return r + l;
-}
-
-char *strrep(const char *s, unsigned n) {
- size_t l;
- char *r, *p;
- unsigned i;
-
- assert(s);
-
- l = strlen(s);
- p = r = malloc(l * n + 1);
- if (!r)
- return NULL;
-
- for (i = 0; i < n; i++)
- p = stpcpy(p, s);
-
- *p = 0;
- return r;
-}
-
-int split_pair(const char *s, const char *sep, char **l, char **r) {
- char *x, *a, *b;
-
- assert(s);
- assert(sep);
- assert(l);
- assert(r);
-
- if (isempty(sep))
- return -EINVAL;
-
- x = strstr(s, sep);
- if (!x)
- return -EINVAL;
-
- a = strndup(s, x - s);
- if (!a)
- return -ENOMEM;
-
- b = strdup(x + strlen(sep));
- if (!b) {
- free(a);
- return -ENOMEM;
- }
-
- *l = a;
- *r = b;
-
- return 0;
-}
-
-int free_and_strdup(char **p, const char *s) {
- char *t;
-
- assert(p);
-
- /* Replaces a string pointer with an strdup()ed new string,
- * possibly freeing the old one. */
-
- if (streq_ptr(*p, s))
- return 0;
-
- if (s) {
- t = strdup(s);
- if (!t)
- return -ENOMEM;
- } else
- t = NULL;
-
- free(*p);
- *p = t;
-
- return 1;
-}
-
-/*
- * Pointer to memset is volatile so that compiler must de-reference
- * the pointer and can't assume that it points to any function in
- * particular (such as memset, which it then might further "optimize")
- * This approach is inspired by openssl's crypto/mem_clr.c.
- */
-typedef void *(*memset_t)(void *,int,size_t);
-
-static volatile memset_t memset_func = memset;
-
-void* memory_erase(void *p, size_t l) {
- return memset_func(p, 'x', l);
-}
-
-char* string_erase(char *x) {
-
- if (!x)
- return NULL;
-
- /* A delicious drop of snake-oil! To be called on memory where
- * we stored passphrases or so, after we used them. */
-
- return memory_erase(x, strlen(x));
-}
-
-char *string_free_erase(char *s) {
- return mfree(string_erase(s));
-}
-
-bool string_is_safe(const char *p) {
- const char *t;
-
- if (!p)
- return false;
-
- for (t = p; *t; t++) {
- if (*t > 0 && *t < ' ') /* no control characters */
- return false;
-
- if (strchr(QUOTES "\\\x7f", *t))
- return false;
- }
-
- return true;
-}
diff --git a/src/basic/string-util.h b/src/basic/string-util.h
deleted file mode 100644
index d029d538bd..0000000000
--- a/src/basic/string-util.h
+++ /dev/null
@@ -1,201 +0,0 @@
-#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 <alloca.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <string.h>
-
-#include "macro.h"
-
-/* What is interpreted as whitespace? */
-#define WHITESPACE " \t\n\r"
-#define NEWLINE "\n\r"
-#define QUOTES "\"\'"
-#define COMMENTS "#;"
-#define GLOB_CHARS "*?["
-#define DIGITS "0123456789"
-#define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz"
-#define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-#define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS
-#define ALPHANUMERICAL LETTERS DIGITS
-#define HEXDIGITS DIGITS "abcdefABCDEF"
-
-#define streq(a,b) (strcmp((a),(b)) == 0)
-#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
-#define strcaseeq(a,b) (strcasecmp((a),(b)) == 0)
-#define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0)
-
-int strcmp_ptr(const char *a, const char *b) _pure_;
-
-static inline bool streq_ptr(const char *a, const char *b) {
- return strcmp_ptr(a, b) == 0;
-}
-
-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];
-}
-
-static inline const char *empty_to_null(const char *p) {
- return isempty(p) ? NULL : p;
-}
-
-static inline const char *strdash_if_empty(const char *str) {
- return isempty(str) ? "-" : str;
-}
-
-static inline char *startswith(const char *s, const char *prefix) {
- size_t l;
-
- l = strlen(prefix);
- if (strncmp(s, prefix, l) == 0)
- return (char*) s + l;
-
- return NULL;
-}
-
-static inline char *startswith_no_case(const char *s, const char *prefix) {
- size_t l;
-
- l = strlen(prefix);
- if (strncasecmp(s, prefix, l) == 0)
- return (char*) s + l;
-
- return NULL;
-}
-
-char *endswith(const char *s, const char *postfix) _pure_;
-char *endswith_no_case(const char *s, const char *postfix) _pure_;
-
-char *first_word(const char *s, const char *word) _pure_;
-
-const char* split(const char **state, size_t *l, const char *separator, bool quoted);
-
-#define FOREACH_WORD(word, length, s, state) \
- _FOREACH_WORD(word, length, s, WHITESPACE, false, state)
-
-#define FOREACH_WORD_SEPARATOR(word, length, s, separator, state) \
- _FOREACH_WORD(word, length, s, separator, false, state)
-
-#define FOREACH_WORD_QUOTED(word, length, s, state) \
- _FOREACH_WORD(word, length, s, WHITESPACE, true, state)
-
-#define _FOREACH_WORD(word, length, s, separator, quoted, state) \
- for ((state) = (s), (word) = split(&(state), &(length), (separator), (quoted)); (word); (word) = split(&(state), &(length), (separator), (quoted)))
-
-char *strappend(const char *s, const char *suffix);
-char *strnappend(const char *s, const char *suffix, size_t length);
-
-char *strjoin(const char *x, ...) _sentinel_;
-
-#define strjoina(a, ...) \
- ({ \
- const char *_appendees_[] = { a, __VA_ARGS__ }; \
- char *_d_, *_p_; \
- int _len_ = 0; \
- unsigned _i_; \
- for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \
- _len_ += strlen(_appendees_[_i_]); \
- _p_ = _d_ = alloca(_len_ + 1); \
- for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \
- _p_ = stpcpy(_p_, _appendees_[_i_]); \
- *_p_ = 0; \
- _d_; \
- })
-
-char *strstrip(char *s);
-char *delete_chars(char *s, const char *bad);
-char *truncate_nl(char *s);
-
-char ascii_tolower(char x);
-char *ascii_strlower(char *s);
-char *ascii_strlower_n(char *s, size_t n);
-
-char ascii_toupper(char x);
-char *ascii_strupper(char *s);
-
-int ascii_strcasecmp_n(const char *a, const char *b, size_t n);
-int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m);
-
-bool chars_intersect(const char *a, const char *b) _pure_;
-
-static inline bool _pure_ in_charset(const char *s, const char* charset) {
- assert(s);
- assert(charset);
- return s[strspn(s, charset)] == '\0';
-}
-
-bool string_has_cc(const char *p, const char *ok) _pure_;
-
-char *ellipsize_mem(const char *s, size_t old_length_bytes, size_t new_length_columns, unsigned percent);
-char *ellipsize(const char *s, size_t length, unsigned percent);
-
-bool nulstr_contains(const char*nulstr, const char *needle);
-
-char* strshorten(char *s, size_t l);
-
-char *strreplace(const char *text, const char *old_string, const char *new_string);
-
-char *strip_tab_ansi(char **p, size_t *l);
-
-char *strextend(char **x, ...) _sentinel_;
-
-char *strrep(const char *s, unsigned n);
-
-int split_pair(const char *s, const char *sep, char **l, char **r);
-
-int free_and_strdup(char **p, const char *s);
-
-/* Normal memmem() requires haystack to be nonnull, which is annoying for zero-length buffers */
-static inline void *memmem_safe(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) {
-
- if (needlelen <= 0)
- return (void*) haystack;
-
- if (haystacklen < needlelen)
- return NULL;
-
- assert(haystack);
- assert(needle);
-
- return memmem(haystack, haystacklen, needle, needlelen);
-}
-
-void* memory_erase(void *p, size_t l);
-char *string_erase(char *x);
-
-char *string_free_erase(char *s);
-DEFINE_TRIVIAL_CLEANUP_FUNC(char *, string_free_erase);
-#define _cleanup_string_free_erase_ _cleanup_(string_free_erasep)
-
-bool string_is_safe(const char *p) _pure_;
diff --git a/src/basic/strv.c b/src/basic/strv.c
deleted file mode 100644
index 0eec868eed..0000000000
--- a/src/basic/strv.c
+++ /dev/null
@@ -1,940 +0,0 @@
-/***
- 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 <fnmatch.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "alloc-util.h"
-#include "escape.h"
-#include "extract-word.h"
-#include "fileio.h"
-#include "string-util.h"
-#include "strv.h"
-#include "util.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;
-}
-
-char *strv_find_startswith(char **l, const char *name) {
- char **i, *e;
-
- assert(name);
-
- /* Like strv_find_prefix, but actually returns only the
- * suffix, not the whole item */
-
- STRV_FOREACH(i, l) {
- e = startswith(*i, name);
- if (e)
- return e;
- }
-
- return NULL;
-}
-
-void strv_clear(char **l) {
- char **k;
-
- if (!l)
- return;
-
- for (k = l; *k; k++)
- free(*k);
-
- *l = NULL;
-}
-
-char **strv_free(char **l) {
- strv_clear(l);
- return mfree(l);
-}
-
-char **strv_free_erase(char **l) {
- char **i;
-
- STRV_FOREACH(i, l)
- string_erase(*i);
-
- return strv_free(l);
-}
-
-char **strv_copy(char * const *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 * const *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
- * STRV_IGNORE. This is supposed to be used with the
- * STRV_IFNOTNULL() macro to include possibly NULL strings in
- * the string list. */
-
- if (x) {
- n = x == STRV_IGNORE ? 0 : 1;
-
- va_copy(aq, ap);
- while ((s = va_arg(aq, const char*))) {
- if (s == STRV_IGNORE)
- continue;
-
- n++;
- }
-
- va_end(aq);
- }
-
- a = new(char*, n+1);
- if (!a)
- return NULL;
-
- if (x) {
- if (x != STRV_IGNORE) {
- a[i] = strdup(x);
- if (!a[i])
- goto fail;
- i++;
- }
-
- while ((s = va_arg(ap, const char*))) {
-
- if (s == STRV_IGNORE)
- 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;
-}
-
-int strv_extend_strv(char ***a, char **b, bool filter_duplicates) {
- char **s, **t;
- size_t p, q, i = 0, j;
-
- assert(a);
-
- if (strv_isempty(b))
- return 0;
-
- p = strv_length(*a);
- q = strv_length(b);
-
- t = realloc(*a, sizeof(char*) * (p + q + 1));
- if (!t)
- return -ENOMEM;
-
- t[p] = NULL;
- *a = t;
-
- STRV_FOREACH(s, b) {
-
- if (filter_duplicates && strv_contains(t, *s))
- continue;
-
- t[p+i] = strdup(*s);
- if (!t[p+i])
- goto rollback;
-
- i++;
- t[p+i] = NULL;
- }
-
- assert(i <= q);
-
- return (int) i;
-
-rollback:
- for (j = 0; j < i; j++)
- free(t[p + j]);
-
- t[p] = NULL;
- return -ENOMEM;
-}
-
-int strv_extend_strv_concat(char ***a, char **b, const char *suffix) {
- int r;
- char **s;
-
- STRV_FOREACH(s, b) {
- char *v;
-
- v = strappend(*s, suffix);
- if (!v)
- return -ENOMEM;
-
- r = strv_push(a, v);
- if (r < 0) {
- free(v);
- return r;
- }
- }
-
- return 0;
-}
-
-char **strv_split(const char *s, const char *separator) {
- const char *word, *state;
- size_t l;
- unsigned n, i;
- char **r;
-
- assert(s);
-
- n = 0;
- FOREACH_WORD_SEPARATOR(word, l, s, separator, state)
- n++;
-
- r = new(char*, n+1);
- if (!r)
- return NULL;
-
- i = 0;
- FOREACH_WORD_SEPARATOR(word, l, s, separator, state) {
- r[i] = strndup(word, l);
- if (!r[i]) {
- strv_free(r);
- return NULL;
- }
-
- i++;
- }
-
- r[i] = NULL;
- return r;
-}
-
-char **strv_split_newlines(const char *s) {
- char **l;
- unsigned n;
-
- assert(s);
-
- /* Special version of strv_split() that splits on newlines and
- * suppresses an empty string at the end */
-
- l = strv_split(s, NEWLINE);
- if (!l)
- return NULL;
-
- n = strv_length(l);
- if (n <= 0)
- return l;
-
- if (isempty(l[n - 1]))
- l[n - 1] = mfree(l[n - 1]);
-
- return l;
-}
-
-int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) {
- _cleanup_strv_free_ char **l = NULL;
- size_t n = 0, allocated = 0;
- int r;
-
- assert(t);
- assert(s);
-
- for (;;) {
- _cleanup_free_ char *word = NULL;
-
- r = extract_first_word(&s, &word, separators, flags);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- if (!GREEDY_REALLOC(l, allocated, n + 2))
- return -ENOMEM;
-
- l[n++] = word;
- word = NULL;
-
- l[n] = NULL;
- }
-
- if (!l) {
- l = new0(char*, 1);
- if (!l)
- return -ENOMEM;
- }
-
- *t = l;
- l = NULL;
-
- return (int) n;
-}
-
-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 (s != l)
- n += k;
- n += strlen(*s);
- }
-
- r = new(char, n+1);
- if (!r)
- return NULL;
-
- e = r;
- STRV_FOREACH(s, l) {
- if (s != l)
- e = stpcpy(e, separator);
-
- e = stpcpy(e, *s);
- }
-
- *e = 0;
-
- return r;
-}
-
-char *strv_join_quoted(char **l) {
- char *buf = NULL;
- char **s;
- size_t allocated = 0, len = 0;
-
- STRV_FOREACH(s, l) {
- /* assuming here that escaped string cannot be more
- * than twice as long, and reserving space for the
- * separator and quotes.
- */
- _cleanup_free_ char *esc = NULL;
- size_t needed;
-
- if (!GREEDY_REALLOC(buf, allocated,
- len + strlen(*s) * 2 + 3))
- goto oom;
-
- esc = cescape(*s);
- if (!esc)
- goto oom;
-
- needed = snprintf(buf + len, allocated - len, "%s\"%s\"",
- len > 0 ? " " : "", esc);
- assert(needed < allocated - len);
- len += needed;
- }
-
- if (!buf)
- buf = malloc0(1);
-
- return buf;
-
- oom:
- return mfree(buf);
-}
-
-int strv_push(char ***l, char *value) {
- char **c;
- unsigned n, m;
-
- if (!value)
- return 0;
-
- n = strv_length(*l);
-
- /* Increase and check for overflow */
- m = n + 2;
- if (m < n)
- return -ENOMEM;
-
- c = realloc_multiply(*l, sizeof(char*), m);
- if (!c)
- return -ENOMEM;
-
- c[n] = value;
- c[n+1] = NULL;
-
- *l = c;
- return 0;
-}
-
-int strv_push_pair(char ***l, char *a, char *b) {
- char **c;
- unsigned n, m;
-
- if (!a && !b)
- return 0;
-
- n = strv_length(*l);
-
- /* increase and check for overflow */
- m = n + !!a + !!b + 1;
- if (m < n)
- return -ENOMEM;
-
- c = realloc_multiply(*l, sizeof(char*), m);
- if (!c)
- return -ENOMEM;
-
- if (a)
- c[n++] = a;
- if (b)
- c[n++] = b;
- c[n] = NULL;
-
- *l = c;
- return 0;
-}
-
-int strv_push_prepend(char ***l, char *value) {
- char **c;
- unsigned n, m, i;
-
- if (!value)
- return 0;
-
- n = strv_length(*l);
-
- /* increase and check for overflow */
- m = n + 2;
- if (m < n)
- return -ENOMEM;
-
- c = new(char*, m);
- if (!c)
- return -ENOMEM;
-
- for (i = 0; i < n; i++)
- c[i+1] = (*l)[i];
-
- c[0] = value;
- c[n+1] = NULL;
-
- free(*l);
- *l = c;
-
- return 0;
-}
-
-int strv_consume(char ***l, char *value) {
- int r;
-
- r = strv_push(l, value);
- if (r < 0)
- free(value);
-
- return r;
-}
-
-int strv_consume_pair(char ***l, char *a, char *b) {
- int r;
-
- r = strv_push_pair(l, a, b);
- if (r < 0) {
- free(a);
- free(b);
- }
-
- return r;
-}
-
-int strv_consume_prepend(char ***l, char *value) {
- int r;
-
- r = strv_push_prepend(l, value);
- if (r < 0)
- free(value);
-
- return r;
-}
-
-int strv_extend(char ***l, const char *value) {
- char *v;
-
- if (!value)
- return 0;
-
- v = strdup(value);
- if (!v)
- return -ENOMEM;
-
- return strv_consume(l, v);
-}
-
-int strv_extend_front(char ***l, const char *value) {
- size_t n, m;
- char *v, **c;
-
- assert(l);
-
- /* Like strv_extend(), but prepends rather than appends the new entry */
-
- if (!value)
- return 0;
-
- n = strv_length(*l);
-
- /* Increase and overflow check. */
- m = n + 2;
- if (m < n)
- return -ENOMEM;
-
- v = strdup(value);
- if (!v)
- return -ENOMEM;
-
- c = realloc_multiply(*l, sizeof(char*), m);
- if (!c) {
- free(v);
- return -ENOMEM;
- }
-
- memmove(c+1, c, n * sizeof(char*));
- c[0] = v;
- c[n+1] = NULL;
-
- *l = c;
- return 0;
-}
-
-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;
-}
-
-bool strv_is_uniq(char **l) {
- char **i;
-
- STRV_FOREACH(i, l)
- if (strv_find(i+1, *i))
- return false;
-
- return true;
-}
-
-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);
- else
- *(t++) = *f;
-
- *t = NULL;
- return l;
-}
-
-char **strv_parse_nulstr(const char *s, size_t l) {
- /* l is the length of the input data, which will be split at NULs into
- * elements of the resulting strv. Hence, the number of items in the resulting strv
- * will be equal to one plus the number of NUL bytes in the l bytes starting at s,
- * unless s[l-1] is NUL, in which case the final empty string is not stored in
- * the resulting strv, and length is equal to the number of NUL bytes.
- *
- * Note that contrary to a normal nulstr which cannot contain empty strings, because
- * the input data is terminated by any two consequent NUL bytes, this parser accepts
- * empty strings in s.
- */
-
- const char *p;
- unsigned c = 0, i = 0;
- char **v;
-
- assert(s || l <= 0);
-
- if (l <= 0)
- return new0(char*, 1);
-
- 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;
-}
-
-char **strv_split_nulstr(const char *s) {
- const char *i;
- char **r = NULL;
-
- NULSTR_FOREACH(i, s)
- if (strv_extend(&r, i) < 0) {
- strv_free(r);
- return NULL;
- }
-
- if (!r)
- return strv_new(NULL, NULL);
-
- return r;
-}
-
-int strv_make_nulstr(char **l, char **p, size_t *q) {
- /* A valid nulstr with two NULs at the end will be created, but
- * q will be the length without the two trailing NULs. Thus the output
- * string is a valid nulstr and can be iterated over using NULSTR_FOREACH,
- * and can also be parsed by strv_parse_nulstr as long as the length
- * is provided separately.
- */
-
- size_t n_allocated = 0, n = 0;
- _cleanup_free_ char *m = NULL;
- char **i;
-
- assert(p);
- assert(q);
-
- STRV_FOREACH(i, l) {
- size_t z;
-
- z = strlen(*i);
-
- if (!GREEDY_REALLOC(m, n_allocated, n + z + 2))
- return -ENOMEM;
-
- memcpy(m + n, *i, z + 1);
- n += z + 1;
- }
-
- if (!m) {
- m = new0(char, 1);
- if (!m)
- return -ENOMEM;
- n = 1;
- } else
- /* make sure there is a second extra NUL at the end of resulting nulstr */
- m[n] = '\0';
-
- assert(n > 0);
- *p = m;
- *q = n - 1;
-
- m = NULL;
-
- return 0;
-}
-
-bool strv_overlap(char **a, char **b) {
- char **i;
-
- STRV_FOREACH(i, a)
- if (strv_contains(b, *i))
- 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;
-}
-
-bool strv_equal(char **a, char **b) {
-
- if (strv_isempty(a))
- return strv_isempty(b);
-
- if (strv_isempty(b))
- return false;
-
- for ( ; *a || *b; ++a, ++b)
- if (!streq_ptr(*a, *b))
- return false;
-
- return true;
-}
-
-void strv_print(char **l) {
- char **s;
-
- STRV_FOREACH(s, l)
- puts(*s);
-}
-
-int strv_extendf(char ***l, const char *format, ...) {
- va_list ap;
- char *x;
- int r;
-
- va_start(ap, format);
- r = vasprintf(&x, format, ap);
- va_end(ap);
-
- if (r < 0)
- return -ENOMEM;
-
- return strv_consume(l, x);
-}
-
-char **strv_reverse(char **l) {
- unsigned n, i;
-
- n = strv_length(l);
- if (n <= 1)
- return l;
-
- for (i = 0; i < n / 2; i++)
- SWAP_TWO(l[i], l[n-1-i]);
-
- return l;
-}
-
-char **strv_shell_escape(char **l, const char *bad) {
- char **s;
-
- /* Escapes every character in every string in l that is in bad,
- * edits in-place, does not roll-back on error. */
-
- STRV_FOREACH(s, l) {
- char *v;
-
- v = shell_escape(*s, bad);
- if (!v)
- return NULL;
-
- free(*s);
- *s = v;
- }
-
- return l;
-}
-
-bool strv_fnmatch(char* const* patterns, const char *s, int flags) {
- char* const* p;
-
- STRV_FOREACH(p, patterns)
- if (fnmatch(*p, s, flags) == 0)
- return true;
-
- return false;
-}
-
-char ***strv_free_free(char ***l) {
- char ***i;
-
- if (!l)
- return NULL;
-
- for (i = l; *i; i++)
- strv_free(*i);
-
- return mfree(l);
-}
-
-char **strv_skip(char **l, size_t n) {
-
- while (n > 0) {
- if (strv_isempty(l))
- return l;
-
- l++, n--;
- }
-
- return l;
-}
-
-int strv_extend_n(char ***l, const char *value, size_t n) {
- size_t i, j, k;
- char **nl;
-
- assert(l);
-
- if (!value)
- return 0;
- if (n == 0)
- return 0;
-
- /* Adds the value n times to l */
-
- k = strv_length(*l);
-
- nl = realloc(*l, sizeof(char*) * (k + n + 1));
- if (!nl)
- return -ENOMEM;
-
- *l = nl;
-
- for (i = k; i < k + n; i++) {
- nl[i] = strdup(value);
- if (!nl[i])
- goto rollback;
- }
-
- nl[i] = NULL;
- return 0;
-
-rollback:
- for (j = k; j < i; j++)
- free(nl[j]);
-
- nl[k] = NULL;
- return -ENOMEM;
-}
-
-int fputstrv(FILE *f, char **l, const char *separator, bool *space) {
- bool b = false;
- char **s;
- int r;
-
- /* Like fputs(), but for strv, and with a less stupid argument order */
-
- if (!space)
- space = &b;
-
- STRV_FOREACH(s, l) {
- r = fputs_with_space(f, *s, separator, space);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
diff --git a/src/basic/strv.h b/src/basic/strv.h
deleted file mode 100644
index 385ad17779..0000000000
--- a/src/basic/strv.h
+++ /dev/null
@@ -1,182 +0,0 @@
-#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 <fnmatch.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stddef.h>
-
-#include "alloc-util.h"
-#include "extract-word.h"
-#include "macro.h"
-#include "util.h"
-
-char *strv_find(char **l, const char *name) _pure_;
-char *strv_find_prefix(char **l, const char *name) _pure_;
-char *strv_find_startswith(char **l, const char *name) _pure_;
-
-char **strv_free(char **l);
-DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free);
-#define _cleanup_strv_free_ _cleanup_(strv_freep)
-
-char **strv_free_erase(char **l);
-DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free_erase);
-#define _cleanup_strv_free_erase_ _cleanup_(strv_free_erasep)
-
-void strv_clear(char **l);
-
-char **strv_copy(char * const *l);
-unsigned strv_length(char * const *l) _pure_;
-
-int strv_extend_strv(char ***a, char **b, bool filter_duplicates);
-int strv_extend_strv_concat(char ***a, char **b, const char *suffix);
-int strv_extend(char ***l, const char *value);
-int strv_extendf(char ***l, const char *format, ...) _printf_(2,0);
-int strv_extend_front(char ***l, const char *value);
-int strv_push(char ***l, char *value);
-int strv_push_pair(char ***l, char *a, char *b);
-int strv_push_prepend(char ***l, char *value);
-int strv_consume(char ***l, char *value);
-int strv_consume_pair(char ***l, char *a, char *b);
-int strv_consume_prepend(char ***l, char *value);
-
-char **strv_remove(char **l, const char *s);
-char **strv_uniq(char **l);
-bool strv_is_uniq(char **l);
-
-bool strv_equal(char **a, char **b);
-
-#define strv_contains(l, s) (!!strv_find((l), (s)))
-
-char **strv_new(const char *x, ...) _sentinel_;
-char **strv_new_ap(const char *x, va_list ap);
-
-#define STRV_IGNORE ((const char *) -1)
-
-static inline const char* STRV_IFNOTNULL(const char *x) {
- return x ? x : STRV_IGNORE;
-}
-
-static inline bool strv_isempty(char * const *l) {
- return !l || !*l;
-}
-
-char **strv_split(const char *s, const char *separator);
-char **strv_split_newlines(const char *s);
-
-int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags);
-
-char *strv_join(char **l, const char *separator);
-char *strv_join_quoted(char **l);
-
-char **strv_parse_nulstr(const char *s, size_t l);
-char **strv_split_nulstr(const char *s);
-int strv_make_nulstr(char **l, char **p, size_t *n);
-
-bool strv_overlap(char **a, char **b) _pure_;
-
-#define STRV_FOREACH(s, l) \
- for ((s) = (l); (s) && *(s); (s)++)
-
-#define STRV_FOREACH_BACKWARDS(s, l) \
- for (s = ({ \
- char **_l = l; \
- _l ? _l + strv_length(_l) - 1U : NULL; \
- }); \
- (l) && ((s) >= (l)); \
- (s)--)
-
-#define STRV_FOREACH_PAIR(x, y, l) \
- for ((x) = (l), (y) = (x+1); (x) && *(x) && *(y); (x) += 2, (y) = (x + 1))
-
-char **strv_sort(char **l);
-void strv_print(char **l);
-
-#define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL }))
-
-#define STRV_MAKE_EMPTY ((char*[1]) { NULL })
-
-#define strv_from_stdarg_alloca(first) \
- ({ \
- char **_l; \
- \
- if (!first) \
- _l = (char**) &first; \
- else { \
- unsigned _n; \
- va_list _ap; \
- \
- _n = 1; \
- va_start(_ap, first); \
- while (va_arg(_ap, char*)) \
- _n++; \
- va_end(_ap); \
- \
- _l = newa(char*, _n+1); \
- _l[_n = 0] = (char*) first; \
- va_start(_ap, first); \
- for (;;) { \
- _l[++_n] = va_arg(_ap, char*); \
- if (!_l[_n]) \
- break; \
- } \
- va_end(_ap); \
- } \
- _l; \
- })
-
-#define STR_IN_SET(x, ...) strv_contains(STRV_MAKE(__VA_ARGS__), x)
-#define STRPTR_IN_SET(x, ...) \
- ({ \
- const char* _x = (x); \
- _x && strv_contains(STRV_MAKE(__VA_ARGS__), _x); \
- })
-
-#define FOREACH_STRING(x, ...) \
- for (char **_l = ({ \
- char **_ll = STRV_MAKE(__VA_ARGS__); \
- x = _ll ? _ll[0] : NULL; \
- _ll; \
- }); \
- _l && *_l; \
- x = ({ \
- _l ++; \
- _l[0]; \
- }))
-
-char **strv_reverse(char **l);
-char **strv_shell_escape(char **l, const char *bad);
-
-bool strv_fnmatch(char* const* patterns, const char *s, int flags);
-
-static inline bool strv_fnmatch_or_empty(char* const* patterns, const char *s, int flags) {
- assert(s);
- return strv_isempty(patterns) ||
- strv_fnmatch(patterns, s, flags);
-}
-
-char ***strv_free_free(char ***l);
-
-char **strv_skip(char **l, size_t n);
-
-int strv_extend_n(char ***l, const char *value, size_t n);
-
-int fputstrv(FILE *f, char **l, const char *separator, bool *space);
diff --git a/src/basic/strxcpyx.c b/src/basic/strxcpyx.c
deleted file mode 100644
index aaf11d21f6..0000000000
--- a/src/basic/strxcpyx.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 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/>.
-***/
-
-/*
- * Concatenates/copies strings. In any case, terminates in all cases
- * with '\0' * and moves the @dest pointer forward to the added '\0'.
- * Returns the * remaining size, and 0 if the string was truncated.
- */
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "strxcpyx.h"
-
-size_t strpcpy(char **dest, size_t size, const char *src) {
- size_t len;
-
- len = strlen(src);
- if (len >= size) {
- if (size > 1)
- *dest = mempcpy(*dest, src, size-1);
- size = 0;
- } else {
- if (len > 0) {
- *dest = mempcpy(*dest, src, len);
- size -= len;
- }
- }
- *dest[0] = '\0';
- return size;
-}
-
-size_t strpcpyf(char **dest, size_t size, const char *src, ...) {
- va_list va;
- int i;
-
- va_start(va, src);
- i = vsnprintf(*dest, size, src, va);
- if (i < (int)size) {
- *dest += i;
- size -= i;
- } else {
- *dest += size;
- size = 0;
- }
- va_end(va);
- *dest[0] = '\0';
- return size;
-}
-
-size_t strpcpyl(char **dest, size_t size, const char *src, ...) {
- va_list va;
-
- va_start(va, src);
- do {
- size = strpcpy(dest, size, src);
- src = va_arg(va, char *);
- } while (src != NULL);
- va_end(va);
- return size;
-}
-
-size_t strscpy(char *dest, size_t size, const char *src) {
- char *s;
-
- s = dest;
- return strpcpy(&s, size, src);
-}
-
-size_t strscpyl(char *dest, size_t size, const char *src, ...) {
- va_list va;
- char *s;
-
- va_start(va, src);
- s = dest;
- do {
- size = strpcpy(&s, size, src);
- src = va_arg(va, char *);
- } while (src != NULL);
- va_end(va);
-
- return size;
-}
diff --git a/src/basic/strxcpyx.h b/src/basic/strxcpyx.h
deleted file mode 100644
index 80ff58726b..0000000000
--- a/src/basic/strxcpyx.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 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 <stddef.h>
-
-#include "macro.h"
-
-size_t strpcpy(char **dest, size_t size, const char *src);
-size_t strpcpyf(char **dest, size_t size, const char *src, ...) _printf_(3, 4);
-size_t strpcpyl(char **dest, size_t size, const char *src, ...) _sentinel_;
-size_t strscpy(char *dest, size_t size, const char *src);
-size_t strscpyl(char *dest, size_t size, const char *src, ...) _sentinel_;
diff --git a/src/basic/syslog-util.c b/src/basic/syslog-util.c
deleted file mode 100644
index db3405154e..0000000000
--- a/src/basic/syslog-util.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/***
- 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 <string.h>
-#include <syslog.h>
-
-#include "hexdecoct.h"
-#include "macro.h"
-#include "string-table.h"
-#include "syslog-util.h"
-
-int syslog_parse_priority(const char **p, int *priority, bool with_facility) {
- int a = 0, b = 0, c = 0;
- int k;
-
- assert(p);
- assert(*p);
- assert(priority);
-
- if ((*p)[0] != '<')
- return 0;
-
- if (!strchr(*p, '>'))
- return 0;
-
- if ((*p)[2] == '>') {
- c = undecchar((*p)[1]);
- k = 3;
- } else if ((*p)[3] == '>') {
- b = undecchar((*p)[1]);
- c = undecchar((*p)[2]);
- k = 4;
- } else if ((*p)[4] == '>') {
- a = undecchar((*p)[1]);
- b = undecchar((*p)[2]);
- c = undecchar((*p)[3]);
- k = 5;
- } else
- return 0;
-
- if (a < 0 || b < 0 || c < 0 ||
- (!with_facility && (a || b || c > 7)))
- return 0;
-
- if (with_facility)
- *priority = a*100 + b*10 + c;
- else
- *priority = (*priority & LOG_FACMASK) | c;
-
- *p += k;
- return 1;
-}
-
-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));
-
-bool log_facility_unshifted_is_valid(int facility) {
- return facility >= 0 && facility <= 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);
-
-bool log_level_is_valid(int level) {
- return level >= 0 && level <= LOG_DEBUG;
-}
diff --git a/src/basic/syslog-util.h b/src/basic/syslog-util.h
deleted file mode 100644
index 5cb606a1bf..0000000000
--- a/src/basic/syslog-util.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#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>
-
-int log_facility_unshifted_to_string_alloc(int i, char **s);
-int log_facility_unshifted_from_string(const char *s);
-bool log_facility_unshifted_is_valid(int faciliy);
-
-int log_level_to_string_alloc(int i, char **s);
-int log_level_from_string(const char *s);
-bool log_level_is_valid(int level);
-
-int syslog_parse_priority(const char **p, int *priority, bool with_facility);
diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c
deleted file mode 100644
index eafdea9eb3..0000000000
--- a/src/basic/terminal-util.c
+++ /dev/null
@@ -1,1224 +0,0 @@
-/***
- 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 <fcntl.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/inotify.h>
-#include <sys/socket.h>
-#include <sys/sysmacros.h>
-#include <sys/time.h>
-#include <linux/kd.h>
-#include <linux/tiocl.h>
-#include <linux/vt.h>
-#include <poll.h>
-#include <signal.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "alloc-util.h"
-#include "env-util.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "fs-util.h"
-#include "io-util.h"
-#include "log.h"
-#include "macro.h"
-#include "parse-util.h"
-#include "process-util.h"
-#include "socket-util.h"
-#include "stat-util.h"
-#include "string-util.h"
-#include "strv.h"
-#include "terminal-util.h"
-#include "time-util.h"
-#include "util.h"
-
-static volatile unsigned cached_columns = 0;
-static volatile unsigned cached_lines = 0;
-
-int chvt(int vt) {
- _cleanup_close_ int fd;
-
- fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
- 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, 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_INFINITY) {
- 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_INFINITY) {
- if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0)
- return -ETIMEDOUT;
- }
-
- errno = 0;
- if (!fgets(line, sizeof(line), f))
- return errno > 0 ? -errno : -EIO;
-
- truncate_nl(line);
-
- if (strlen(line) != 1)
- return -EBADMSG;
-
- if (need_nl)
- *need_nl = false;
-
- *ret = line[0];
- return 0;
-}
-
-int ask_char(char *ret, const char *replies, const char *text, ...) {
- int r;
-
- assert(ret);
- assert(replies);
- assert(text);
-
- for (;;) {
- va_list ap;
- char c;
- bool need_nl = true;
-
- if (colors_enabled())
- fputs(ANSI_HIGHLIGHT, stdout);
-
- va_start(ap, text);
- vprintf(text, ap);
- va_end(ap);
-
- if (colors_enabled())
- fputs(ANSI_NORMAL, stdout);
-
- fflush(stdout);
-
- r = read_one_char(stdin, &c, USEC_INFINITY, &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 ask_string(char **ret, const char *text, ...) {
- assert(ret);
- assert(text);
-
- for (;;) {
- char line[LINE_MAX];
- va_list ap;
-
- if (colors_enabled())
- fputs(ANSI_HIGHLIGHT, stdout);
-
- va_start(ap, text);
- vprintf(text, ap);
- va_end(ap);
-
- if (colors_enabled())
- fputs(ANSI_NORMAL, stdout);
-
- fflush(stdout);
-
- errno = 0;
- if (!fgets(line, sizeof(line), stdin))
- return errno > 0 ? -errno : -EIO;
-
- if (!endswith(line, "\n"))
- putchar('\n');
- else {
- char *s;
-
- if (isempty(line))
- continue;
-
- truncate_nl(line);
- s = strdup(line);
- if (!s)
- return -ENOMEM;
-
- *ret = s;
- return 0;
- }
- }
-}
-
-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 */
- (void) ioctl(fd, TIOCNXCL);
-
- /* Switch to text mode */
- if (switch_to_text)
- (void) ioctl(fd, KDSETMODE, KD_TEXT);
-
- /* Enable console unicode mode */
- (void) 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 */
- (void) tcflush(fd, TCIOFLUSH);
-
- return r;
-}
-
-int reset_terminal(const char *name) {
- _cleanup_close_ int fd = -1;
-
- /* We open the terminal with O_NONBLOCK here, to ensure we
- * don't block on carrier if this is a terminal with carrier
- * configured. */
-
- fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
- if (fd < 0)
- return fd;
-
- return reset_terminal_fd(fd, true);
-}
-
-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
- */
-
- if (mode & O_CREAT)
- return -EINVAL;
-
- for (;;) {
- fd = open(name, mode, 0);
- if (fd >= 0)
- break;
-
- if (errno != EIO)
- return -errno;
-
- /* Max 1s in total */
- if (c >= 20)
- return -errno;
-
- usleep(50 * USEC_PER_MSEC);
- c++;
- }
-
- r = isatty(fd);
- if (r == 0) {
- safe_close(fd);
- return -ENOTTY;
- }
-
- return fd;
-}
-
-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;
-
- 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_INFINITY)
- ts = now(CLOCK_MONOTONIC);
-
- if (!fail && !force) {
- notify = inotify_init1(IN_CLOEXEC | (timeout != USEC_INFINITY ? 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 (;;) {
- struct sigaction sa_old, sa_new = {
- .sa_handler = SIG_IGN,
- .sa_flags = SA_RESTART,
- };
-
- 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. */
- 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 (;;) {
- union inotify_event_buffer buffer;
- struct inotify_event *e;
- ssize_t l;
-
- if (timeout != USEC_INFINITY) {
- 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, &buffer, sizeof(buffer));
- if (l < 0) {
- if (errno == EINTR || errno == EAGAIN)
- continue;
-
- r = -errno;
- goto fail;
- }
-
- FOREACH_INOTIFY_EVENT(e, buffer, l) {
- if (e->wd != wd || !(e->mask & IN_CLOSE)) {
- r = -EIO;
- goto fail;
- }
- }
-
- 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. */
- fd = safe_close(fd);
- }
-
- safe_close(notify);
-
- return fd;
-
-fail:
- safe_close(fd);
- safe_close(notify);
-
- return r;
-}
-
-int release_terminal(void) {
- static const struct sigaction sa_new = {
- .sa_handler = SIG_IGN,
- .sa_flags = SA_RESTART,
- };
-
- _cleanup_close_ int fd = -1;
- struct sigaction sa_old;
- int r = 0;
-
- fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
- if (fd < 0)
- return -errno;
-
- /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed
- * by our own TIOCNOTTY */
- assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0);
-
- if (ioctl(fd, TIOCNOTTY) < 0)
- r = -errno;
-
- assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0);
-
- return r;
-}
-
-int terminal_vhangup_fd(int fd) {
- assert(fd >= 0);
-
- if (ioctl(fd, TIOCVHANGUP) < 0)
- return -errno;
-
- return 0;
-}
-
-int terminal_vhangup(const char *name) {
- _cleanup_close_ int fd;
-
- fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
- if (fd < 0)
- return fd;
-
- return terminal_vhangup_fd(fd);
-}
-
-int vt_disallocate(const char *name) {
- _cleanup_close_ int fd = -1;
- unsigned u;
- int r;
-
- /* 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);
- 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|O_NONBLOCK);
- if (fd < 0)
- return fd;
-
- r = ioctl(fd, VT_DISALLOCATE, u);
- fd = safe_close(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);
- return 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_INFINITY);
- if (fd < 0)
- return log_error_errno(fd, "Failed to acquire terminal: %m");
-
- r = reset_terminal_fd(fd, true);
- if (r < 0)
- log_warning_errno(r, "Failed to reset terminal, ignoring: %m");
-
- r = make_stdio(fd);
- if (r < 0)
- return log_error_errno(r, "Failed to duplicate terminal fd: %m");
-
- return 0;
-}
-
-bool tty_is_vc(const char *tty) {
- assert(tty);
-
- 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;
-}
-
-char *resolve_dev_console(char **active) {
- char *tty;
-
- /* 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 (path_is_read_only_fs("/sys") > 0)
- return NULL;
-
- if (read_one_line_file("/sys/class/tty/console/active", active) < 0)
- return NULL;
-
- /* If multiple log outputs are configured the last one is what
- * /dev/console points to */
- tty = strrchr(*active, ' ');
- if (tty)
- tty++;
- else
- tty = *active;
-
- if (streq(tty, "tty0")) {
- char *tmp;
-
- /* Get the active VC (e.g. tty1) */
- if (read_one_line_file("/sys/class/tty/tty0/active", &tmp) >= 0) {
- free(*active);
- tty = *active = tmp;
- }
- }
-
- return tty;
-}
-
-int get_kernel_consoles(char ***consoles) {
- _cleanup_strv_free_ char **con = NULL;
- _cleanup_free_ char *line = NULL;
- const char *active;
- int r;
-
- assert(consoles);
-
- r = read_one_line_file("/sys/class/tty/console/active", &line);
- if (r < 0)
- return r;
-
- active = line;
- for (;;) {
- _cleanup_free_ char *tty = NULL;
- char *path;
-
- r = extract_first_word(&active, &tty, NULL, 0);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- if (streq(tty, "tty0")) {
- tty = mfree(tty);
- r = read_one_line_file("/sys/class/tty/tty0/active", &tty);
- if (r < 0)
- return r;
- }
-
- path = strappend("/dev/", tty);
- if (!path)
- return -ENOMEM;
-
- if (access(path, F_OK) < 0) {
- log_debug_errno(errno, "Console device %s is not accessible, skipping: %m", path);
- free(path);
- continue;
- }
-
- r = strv_consume(&con, path);
- if (r < 0)
- return r;
- }
-
- if (strv_isempty(con)) {
- log_debug("No devices found for system console");
-
- r = strv_extend(&con, "/dev/console");
- if (r < 0)
- return r;
- }
-
- *consoles = con;
- con = NULL;
- return 0;
-}
-
-bool tty_is_vc_resolve(const char *tty) {
- _cleanup_free_ char *active = NULL;
-
- assert(tty);
-
- if (startswith(tty, "/dev/"))
- tty += 5;
-
- if (streq(tty, "console")) {
- tty = resolve_dev_console(&active);
- if (!tty)
- return false;
- }
-
- return tty_is_vc(tty);
-}
-
-const char *default_term_for_tty(const char *tty) {
- return tty && tty_is_vc_resolve(tty) ? "linux" : "vt220";
-}
-
-int fd_columns(int fd) {
- struct winsize 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;
- int c;
-
- if (_likely_(cached_columns > 0))
- return cached_columns;
-
- c = 0;
- e = getenv("COLUMNS");
- if (e)
- (void) safe_atoi(e, &c);
-
- if (c <= 0)
- c = fd_columns(STDOUT_FILENO);
-
- if (c <= 0)
- c = 80;
-
- cached_columns = c;
- return cached_columns;
-}
-
-int fd_lines(int fd) {
- struct winsize 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;
- int l;
-
- if (_likely_(cached_lines > 0))
- return cached_lines;
-
- l = 0;
- e = getenv("LINES");
- if (e)
- (void) safe_atoi(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 make_stdio(int fd) {
- int r, s, t;
-
- assert(fd >= 0);
-
- r = dup2(fd, STDIN_FILENO);
- s = dup2(fd, STDOUT_FILENO);
- t = dup2(fd, STDERR_FILENO);
-
- if (fd >= 3)
- safe_close(fd);
-
- if (r < 0 || s < 0 || t < 0)
- return -errno;
-
- /* Explicitly unset O_CLOEXEC, since if fd was < 3, then
- * dup2() was a NOP and the bit hence possibly set. */
- stdio_unset_cloexec();
-
- 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);
-}
-
-int getttyname_malloc(int fd, char **ret) {
- size_t l = 100;
- int r;
-
- assert(fd >= 0);
- assert(ret);
-
- for (;;) {
- char path[l];
-
- r = ttyname_r(fd, path, sizeof(path));
- if (r == 0) {
- const char *p;
- char *c;
-
- p = startswith(path, "/dev/");
- c = strdup(p ?: path);
- if (!c)
- return -ENOMEM;
-
- *ret = c;
- return 0;
- }
-
- if (r != ERANGE)
- return -r;
-
- l *= 2;
- }
-
- return 0;
-}
-
-int getttyname_harder(int fd, char **r) {
- int k;
- char *s = NULL;
-
- 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 r;
- _cleanup_free_ char *line = NULL;
- const char *p;
- unsigned long ttynr;
-
- assert(pid >= 0);
-
- p = procfs_file_alloca(pid, "stat");
- r = read_one_line_file(p, &line);
- if (r < 0)
- return r;
-
- 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;
-
- if (major(ttynr) == 0 && minor(ttynr) == 0)
- return -ENXIO;
-
- if (d)
- *d = (dev_t) ttynr;
-
- return 0;
-}
-
-int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
- char fn[sizeof("/dev/char/")-1 + 2*DECIMAL_STR_MAX(unsigned) + 1 + 1], *b = NULL;
- _cleanup_free_ char *s = NULL;
- const char *p;
- dev_t devnr;
- int k;
-
- assert(r);
-
- k = get_ctty_devnr(pid, &devnr);
- if (k < 0)
- return k;
-
- sprintf(fn, "/dev/char/%u:%u", major(devnr), minor(devnr));
-
- k = readlink_malloc(fn, &s);
- if (k < 0) {
-
- if (k != -ENOENT)
- return k;
-
- /* This is an ugly hack */
- if (major(devnr) == 136) {
- if (asprintf(&b, "pts/%u", minor(devnr)) < 0)
- return -ENOMEM;
- } else {
- /* Probably something like the ptys which have no
- * symlink in /dev/char. Let's return something
- * vaguely useful. */
-
- b = strdup(fn + 5);
- if (!b)
- return -ENOMEM;
- }
- } else {
- if (startswith(s, "/dev/"))
- p = s + 5;
- else if (startswith(s, "../"))
- p = s + 3;
- else
- p = s;
-
- b = strdup(p);
- if (!b)
- return -ENOMEM;
- }
-
- *r = b;
- if (_devnr)
- *_devnr = devnr;
-
- return 0;
-}
-
-int ptsname_malloc(int fd, char **ret) {
- size_t l = 100;
-
- assert(fd >= 0);
- assert(ret);
-
- for (;;) {
- char *c;
-
- c = new(char, l);
- if (!c)
- return -ENOMEM;
-
- if (ptsname_r(fd, c, l) == 0) {
- *ret = c;
- return 0;
- }
- if (errno != ERANGE) {
- free(c);
- return -errno;
- }
-
- free(c);
- l *= 2;
- }
-}
-
-int ptsname_namespace(int pty, char **ret) {
- int no = -1, r;
-
- /* Like ptsname(), but doesn't assume that the path is
- * accessible in the local namespace. */
-
- r = ioctl(pty, TIOCGPTN, &no);
- if (r < 0)
- return -errno;
-
- if (no < 0)
- return -EIO;
-
- if (asprintf(ret, "/dev/pts/%i", no) < 0)
- return -ENOMEM;
-
- return 0;
-}
-
-int openpt_in_namespace(pid_t pid, int flags) {
- _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
- _cleanup_close_pair_ int pair[2] = { -1, -1 };
- siginfo_t si;
- pid_t child;
- int r;
-
- assert(pid > 0);
-
- r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
- if (r < 0)
- return r;
-
- if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
- return -errno;
-
- child = fork();
- if (child < 0)
- return -errno;
-
- if (child == 0) {
- int master;
-
- pair[0] = safe_close(pair[0]);
-
- r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- master = posix_openpt(flags|O_NOCTTY|O_CLOEXEC);
- if (master < 0)
- _exit(EXIT_FAILURE);
-
- if (unlockpt(master) < 0)
- _exit(EXIT_FAILURE);
-
- if (send_one_fd(pair[1], master, 0) < 0)
- _exit(EXIT_FAILURE);
-
- _exit(EXIT_SUCCESS);
- }
-
- pair[1] = safe_close(pair[1]);
-
- r = wait_for_terminate(child, &si);
- if (r < 0)
- return r;
- if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
- return -EIO;
-
- return receive_one_fd(pair[0], 0);
-}
-
-int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
- _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
- _cleanup_close_pair_ int pair[2] = { -1, -1 };
- siginfo_t si;
- pid_t child;
- int r;
-
- r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
- if (r < 0)
- return r;
-
- if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
- return -errno;
-
- child = fork();
- if (child < 0)
- return -errno;
-
- if (child == 0) {
- int master;
-
- pair[0] = safe_close(pair[0]);
-
- r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- master = open_terminal(name, mode|O_NOCTTY|O_CLOEXEC);
- if (master < 0)
- _exit(EXIT_FAILURE);
-
- if (send_one_fd(pair[1], master, 0) < 0)
- _exit(EXIT_FAILURE);
-
- _exit(EXIT_SUCCESS);
- }
-
- pair[1] = safe_close(pair[1]);
-
- r = wait_for_terminate(child, &si);
- if (r < 0)
- return r;
- if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
- return -EIO;
-
- return receive_one_fd(pair[0], 0);
-}
-
-static bool getenv_terminal_is_dumb(void) {
- const char *e;
-
- e = getenv("TERM");
- if (!e)
- return true;
-
- return streq(e, "dumb");
-}
-
-bool terminal_is_dumb(void) {
- if (!on_tty())
- return true;
-
- return getenv_terminal_is_dumb();
-}
-
-bool colors_enabled(void) {
- static int enabled = -1;
-
- if (_unlikely_(enabled < 0)) {
- int val;
-
- val = getenv_bool("SYSTEMD_COLORS");
- if (val >= 0)
- enabled = val;
- else if (getpid() == 1)
- /* PID1 outputs to the console without holding it open all the time */
- enabled = !getenv_terminal_is_dumb();
- else
- enabled = !terminal_is_dumb();
- }
-
- return enabled;
-}
diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h
deleted file mode 100644
index b862bfaf05..0000000000
--- a/src/basic/terminal-util.h
+++ /dev/null
@@ -1,119 +0,0 @@
-#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 <stdio.h>
-#include <sys/types.h>
-
-#include "macro.h"
-#include "time-util.h"
-
-#define ANSI_RED "\x1B[0;31m"
-#define ANSI_GREEN "\x1B[0;32m"
-#define ANSI_UNDERLINE "\x1B[0;4m"
-#define ANSI_HIGHLIGHT "\x1B[0;1;39m"
-#define ANSI_HIGHLIGHT_RED "\x1B[0;1;31m"
-#define ANSI_HIGHLIGHT_GREEN "\x1B[0;1;32m"
-#define ANSI_HIGHLIGHT_YELLOW "\x1B[0;1;33m"
-#define ANSI_HIGHLIGHT_BLUE "\x1B[0;1;34m"
-#define ANSI_HIGHLIGHT_UNDERLINE "\x1B[0;1;4m"
-#define ANSI_HIGHLIGHT_RED_UNDERLINE "\x1B[0;1;4;31m"
-#define ANSI_HIGHLIGHT_GREEN_UNDERLINE "\x1B[0;1;4;32m"
-#define ANSI_HIGHLIGHT_YELLOW_UNDERLINE "\x1B[0;1;4;33m"
-#define ANSI_HIGHLIGHT_BLUE_UNDERLINE "\x1B[0;1;4;34m"
-#define ANSI_NORMAL "\x1B[0m"
-
-#define ANSI_ERASE_TO_END_OF_LINE "\x1B[K"
-
-/* Set cursor to top left corner and clear screen */
-#define ANSI_HOME_CLEAR "\x1B[H\x1B[2J"
-
-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 terminal_vhangup_fd(int fd);
-int terminal_vhangup(const char *name);
-
-int chvt(int vt);
-
-int read_one_char(FILE *f, char *ret, usec_t timeout, bool *need_nl);
-int ask_char(char *ret, const char *replies, const char *text, ...) _printf_(3, 4);
-int ask_string(char **ret, const char *text, ...) _printf_(2, 3);
-
-int vt_disallocate(const char *name);
-
-char *resolve_dev_console(char **active);
-int get_kernel_consoles(char ***consoles);
-bool tty_is_vc(const char *tty);
-bool tty_is_vc_resolve(const char *tty);
-bool tty_is_console(const char *tty) _pure_;
-int vtnr_from_tty(const char *tty);
-const char *default_term_for_tty(const char *tty);
-
-int make_stdio(int fd);
-int make_null_stdio(void);
-int make_console_stdio(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);
-bool terminal_is_dumb(void);
-bool colors_enabled(void);
-
-#define DEFINE_ANSI_FUNC(name, NAME) \
- static inline const char *ansi_##name(void) { \
- return colors_enabled() ? ANSI_##NAME : ""; \
- } \
- struct __useless_struct_to_allow_trailing_semicolon__
-
-DEFINE_ANSI_FUNC(underline, UNDERLINE);
-DEFINE_ANSI_FUNC(highlight, HIGHLIGHT);
-DEFINE_ANSI_FUNC(highlight_underline, HIGHLIGHT_UNDERLINE);
-DEFINE_ANSI_FUNC(highlight_red, HIGHLIGHT_RED);
-DEFINE_ANSI_FUNC(highlight_green, HIGHLIGHT_GREEN);
-DEFINE_ANSI_FUNC(highlight_yellow, HIGHLIGHT_YELLOW);
-DEFINE_ANSI_FUNC(highlight_blue, HIGHLIGHT_BLUE);
-DEFINE_ANSI_FUNC(highlight_red_underline, HIGHLIGHT_RED_UNDERLINE);
-DEFINE_ANSI_FUNC(highlight_green_underline, HIGHLIGHT_GREEN_UNDERLINE);
-DEFINE_ANSI_FUNC(highlight_yellow_underline, HIGHLIGHT_YELLOW_UNDERLINE);
-DEFINE_ANSI_FUNC(highlight_blue_underline, HIGHLIGHT_BLUE_UNDERLINE);
-DEFINE_ANSI_FUNC(normal, NORMAL);
-
-int get_ctty_devnr(pid_t pid, dev_t *d);
-int get_ctty(pid_t, dev_t *_devnr, char **r);
-
-int getttyname_malloc(int fd, char **r);
-int getttyname_harder(int fd, char **r);
-
-int ptsname_malloc(int fd, char **ret);
-int ptsname_namespace(int pty, char **ret);
-
-int openpt_in_namespace(pid_t pid, int flags);
-int open_terminal_in_namespace(pid_t pid, const char *name, int mode);
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
deleted file mode 100644
index fedff1362c..0000000000
--- a/src/basic/time-util.c
+++ /dev/null
@@ -1,1327 +0,0 @@
-/***
- 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 <limits.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/timerfd.h>
-#include <sys/timex.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "alloc-util.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "fs-util.h"
-#include "log.h"
-#include "macro.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "string-util.h"
-#include "strv.h"
-#include "time-util.h"
-
-static clockid_t map_clock_id(clockid_t c) {
-
- /* Some more exotic archs (s390, ppc, …) lack the "ALARM" flavour of the clocks. Thus, clock_gettime() will
- * fail for them. Since they are essentially the same as their non-ALARM pendants (their only difference is
- * when timers are set on them), let's just map them accordingly. This way, we can get the correct time even on
- * those archs. */
-
- switch (c) {
-
- case CLOCK_BOOTTIME_ALARM:
- return CLOCK_BOOTTIME;
-
- case CLOCK_REALTIME_ALARM:
- return CLOCK_REALTIME;
-
- default:
- return c;
- }
-}
-
-usec_t now(clockid_t clock_id) {
- struct timespec ts;
-
- assert_se(clock_gettime(map_clock_id(clock_id), &ts) == 0);
-
- return timespec_load(&ts);
-}
-
-nsec_t now_nsec(clockid_t clock_id) {
- struct timespec ts;
-
- assert_se(clock_gettime(map_clock_id(clock_id), &ts) == 0);
-
- return timespec_load_nsec(&ts);
-}
-
-dual_timestamp* dual_timestamp_get(dual_timestamp *ts) {
- assert(ts);
-
- ts->realtime = now(CLOCK_REALTIME);
- ts->monotonic = now(CLOCK_MONOTONIC);
-
- return ts;
-}
-
-triple_timestamp* triple_timestamp_get(triple_timestamp *ts) {
- assert(ts);
-
- ts->realtime = now(CLOCK_REALTIME);
- ts->monotonic = now(CLOCK_MONOTONIC);
- ts->boottime = clock_boottime_supported() ? now(CLOCK_BOOTTIME) : USEC_INFINITY;
-
- return ts;
-}
-
-dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
- int64_t delta;
- assert(ts);
-
- if (u == USEC_INFINITY || u <= 0) {
- ts->realtime = ts->monotonic = u;
- return ts;
- }
-
- ts->realtime = u;
-
- delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u;
- ts->monotonic = usec_sub(now(CLOCK_MONOTONIC), delta);
-
- return ts;
-}
-
-triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u) {
- int64_t delta;
-
- assert(ts);
-
- if (u == USEC_INFINITY || u <= 0) {
- ts->realtime = ts->monotonic = ts->boottime = u;
- return ts;
- }
-
- ts->realtime = u;
- delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u;
- ts->monotonic = usec_sub(now(CLOCK_MONOTONIC), delta);
- ts->boottime = clock_boottime_supported() ? usec_sub(now(CLOCK_BOOTTIME), delta) : USEC_INFINITY;
-
- return ts;
-}
-
-dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u) {
- int64_t delta;
- assert(ts);
-
- if (u == USEC_INFINITY) {
- ts->realtime = ts->monotonic = USEC_INFINITY;
- return ts;
- }
-
- ts->monotonic = u;
- delta = (int64_t) now(CLOCK_MONOTONIC) - (int64_t) u;
- ts->realtime = usec_sub(now(CLOCK_REALTIME), delta);
-
- return ts;
-}
-
-dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, usec_t u) {
- int64_t delta;
-
- if (u == USEC_INFINITY) {
- ts->realtime = ts->monotonic = USEC_INFINITY;
- return ts;
- }
-
- dual_timestamp_get(ts);
- delta = (int64_t) now(clock_boottime_or_monotonic()) - (int64_t) u;
- ts->realtime = usec_sub(ts->realtime, delta);
- ts->monotonic = usec_sub(ts->monotonic, delta);
-
- return ts;
-}
-
-usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock) {
-
- switch (clock) {
-
- case CLOCK_REALTIME:
- case CLOCK_REALTIME_ALARM:
- return ts->realtime;
-
- case CLOCK_MONOTONIC:
- return ts->monotonic;
-
- case CLOCK_BOOTTIME:
- case CLOCK_BOOTTIME_ALARM:
- return ts->boottime;
-
- default:
- return USEC_INFINITY;
- }
-}
-
-usec_t timespec_load(const struct timespec *ts) {
- assert(ts);
-
- if (ts->tv_sec == (time_t) -1 && ts->tv_nsec == (long) -1)
- return USEC_INFINITY;
-
- if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC)
- return USEC_INFINITY;
-
- return
- (usec_t) ts->tv_sec * USEC_PER_SEC +
- (usec_t) ts->tv_nsec / NSEC_PER_USEC;
-}
-
-nsec_t timespec_load_nsec(const struct timespec *ts) {
- assert(ts);
-
- if (ts->tv_sec == (time_t) -1 && ts->tv_nsec == (long) -1)
- return NSEC_INFINITY;
-
- if ((nsec_t) ts->tv_sec >= (UINT64_MAX - ts->tv_nsec) / NSEC_PER_SEC)
- return NSEC_INFINITY;
-
- return (nsec_t) ts->tv_sec * NSEC_PER_SEC + (nsec_t) ts->tv_nsec;
-}
-
-struct timespec *timespec_store(struct timespec *ts, usec_t u) {
- assert(ts);
-
- if (u == USEC_INFINITY) {
- 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_INFINITY;
-
- if ((usec_t) tv->tv_sec > (UINT64_MAX - tv->tv_usec) / USEC_PER_SEC)
- return USEC_INFINITY;
-
- 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_INFINITY) {
- tv->tv_sec = (time_t) -1;
- tv->tv_usec = (suseconds_t) -1;
- } else {
- tv->tv_sec = (time_t) (u / USEC_PER_SEC);
- tv->tv_usec = (suseconds_t) (u % USEC_PER_SEC);
- }
-
- return tv;
-}
-
-static char *format_timestamp_internal(
- char *buf,
- size_t l,
- usec_t t,
- bool utc,
- bool us) {
-
- /* The weekdays in non-localized (English) form. We use this instead of the localized form, so that our
- * generated timestamps may be parsed with parse_timestamp(), and always read the same. */
- static const char * const weekdays[] = {
- [0] = "Sun",
- [1] = "Mon",
- [2] = "Tue",
- [3] = "Wed",
- [4] = "Thu",
- [5] = "Fri",
- [6] = "Sat",
- };
-
- struct tm tm;
- time_t sec;
- size_t n;
-
- assert(buf);
-
- if (l <
- 3 + /* week day */
- 1 + 10 + /* space and date */
- 1 + 8 + /* space and time */
- (us ? 1 + 6 : 0) + /* "." and microsecond part */
- 1 + 1 + /* space and shortest possible zone */
- 1)
- return NULL; /* Not enough space even for the shortest form. */
- if (t <= 0 || t == USEC_INFINITY)
- return NULL; /* Timestamp is unset */
-
- sec = (time_t) (t / USEC_PER_SEC); /* Round down */
- if ((usec_t) sec != (t / USEC_PER_SEC))
- return NULL; /* overflow? */
-
- if (!localtime_or_gmtime_r(&sec, &tm, utc))
- return NULL;
-
- /* Start with the week day */
- assert((size_t) tm.tm_wday < ELEMENTSOF(weekdays));
- memcpy(buf, weekdays[tm.tm_wday], 4);
-
- /* Add the main components */
- if (strftime(buf + 3, l - 3, " %Y-%m-%d %H:%M:%S", &tm) <= 0)
- return NULL; /* Doesn't fit */
-
- /* Append the microseconds part, if that's requested */
- if (us) {
- n = strlen(buf);
- if (n + 8 > l)
- return NULL; /* Microseconds part doesn't fit. */
-
- sprintf(buf + n, ".%06llu", (unsigned long long) (t % USEC_PER_SEC));
- }
-
- /* Append the timezone */
- n = strlen(buf);
- if (utc) {
- /* If this is UTC then let's explicitly use the "UTC" string here, because gmtime_r() normally uses the
- * obsolete "GMT" instead. */
- if (n + 5 > l)
- return NULL; /* "UTC" doesn't fit. */
-
- strcpy(buf + n, " UTC");
-
- } else if (!isempty(tm.tm_zone)) {
- size_t tn;
-
- /* An explicit timezone is specified, let's use it, if it fits */
- tn = strlen(tm.tm_zone);
- if (n + 1 + tn + 1 > l) {
- /* The full time zone does not fit in. Yuck. */
-
- if (n + 1 + _POSIX_TZNAME_MAX + 1 > l)
- return NULL; /* Not even enough space for the POSIX minimum (of 6)? In that case, complain that it doesn't fit */
-
- /* So the time zone doesn't fit in fully, but the caller passed enough space for the POSIX
- * minimum time zone length. In this case suppress the timezone entirely, in order not to dump
- * an overly long, hard to read string on the user. This should be safe, because the user will
- * assume the local timezone anyway if none is shown. And so does parse_timestamp(). */
- } else {
- buf[n++] = ' ';
- strcpy(buf + n, tm.tm_zone);
- }
- }
-
- return buf;
-}
-
-char *format_timestamp(char *buf, size_t l, usec_t t) {
- return format_timestamp_internal(buf, l, t, false, false);
-}
-
-char *format_timestamp_utc(char *buf, size_t l, usec_t t) {
- return format_timestamp_internal(buf, l, t, true, false);
-}
-
-char *format_timestamp_us(char *buf, size_t l, usec_t t) {
- return format_timestamp_internal(buf, l, t, false, true);
-}
-
-char *format_timestamp_us_utc(char *buf, size_t l, usec_t t) {
- return format_timestamp_internal(buf, l, t, true, true);
-}
-
-char *format_timestamp_relative(char *buf, size_t l, usec_t t) {
- const char *s;
- usec_t n, d;
-
- if (t <= 0 || t == USEC_INFINITY)
- return NULL;
-
- n = now(CLOCK_REALTIME);
- if (n > t) {
- d = n - t;
- s = "ago";
- } else {
- d = t - n;
- s = "left";
- }
-
- if (d >= USEC_PER_YEAR)
- snprintf(buf, l, USEC_FMT " years " USEC_FMT " months %s",
- d / USEC_PER_YEAR,
- (d % USEC_PER_YEAR) / USEC_PER_MONTH, s);
- else if (d >= USEC_PER_MONTH)
- snprintf(buf, l, USEC_FMT " months " USEC_FMT " days %s",
- d / USEC_PER_MONTH,
- (d % USEC_PER_MONTH) / USEC_PER_DAY, s);
- else if (d >= USEC_PER_WEEK)
- snprintf(buf, l, USEC_FMT " weeks " USEC_FMT " days %s",
- d / USEC_PER_WEEK,
- (d % USEC_PER_WEEK) / USEC_PER_DAY, s);
- else if (d >= 2*USEC_PER_DAY)
- snprintf(buf, l, USEC_FMT " days %s", d / USEC_PER_DAY, s);
- else if (d >= 25*USEC_PER_HOUR)
- snprintf(buf, l, "1 day " USEC_FMT "h %s",
- (d - USEC_PER_DAY) / USEC_PER_HOUR, s);
- else if (d >= 6*USEC_PER_HOUR)
- snprintf(buf, l, USEC_FMT "h %s",
- d / USEC_PER_HOUR, s);
- else if (d >= USEC_PER_HOUR)
- snprintf(buf, l, USEC_FMT "h " USEC_FMT "min %s",
- d / USEC_PER_HOUR,
- (d % USEC_PER_HOUR) / USEC_PER_MINUTE, s);
- else if (d >= 5*USEC_PER_MINUTE)
- snprintf(buf, l, USEC_FMT "min %s",
- d / USEC_PER_MINUTE, s);
- else if (d >= USEC_PER_MINUTE)
- snprintf(buf, l, USEC_FMT "min " USEC_FMT "s %s",
- d / USEC_PER_MINUTE,
- (d % USEC_PER_MINUTE) / USEC_PER_SEC, s);
- else if (d >= USEC_PER_SEC)
- snprintf(buf, l, USEC_FMT "s %s",
- d / USEC_PER_SEC, s);
- else if (d >= USEC_PER_MSEC)
- snprintf(buf, l, USEC_FMT "ms %s",
- d / USEC_PER_MSEC, s);
- else if (d > 0)
- snprintf(buf, l, USEC_FMT"us %s",
- d, s);
- else
- snprintf(buf, l, "now");
-
- buf[l-1] = 0;
- return buf;
-}
-
-char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
- static const struct {
- const char *suffix;
- usec_t usec;
- } table[] = {
- { "y", USEC_PER_YEAR },
- { "month", USEC_PER_MONTH },
- { "w", USEC_PER_WEEK },
- { "d", USEC_PER_DAY },
- { "h", USEC_PER_HOUR },
- { "min", USEC_PER_MINUTE },
- { "s", USEC_PER_SEC },
- { "ms", USEC_PER_MSEC },
- { "us", 1 },
- };
-
- unsigned i;
- char *p = buf;
- bool something = false;
-
- assert(buf);
- assert(l > 0);
-
- if (t == USEC_INFINITY) {
- strncpy(p, "infinity", l-1);
- p[l-1] = 0;
- return p;
- }
-
- if (t <= 0) {
- strncpy(p, "0", l-1);
- p[l-1] = 0;
- return p;
- }
-
- /* The result of this function can be parsed with parse_sec */
-
- for (i = 0; i < ELEMENTSOF(table); i++) {
- int k = 0;
- size_t n;
- bool done = false;
- usec_t a, b;
-
- if (t <= 0)
- break;
-
- if (t < accuracy && something)
- break;
-
- if (t < table[i].usec)
- continue;
-
- if (l <= 1)
- break;
-
- a = t / table[i].usec;
- b = t % table[i].usec;
-
- /* Let's see if we should shows this in dot notation */
- if (t < USEC_PER_MINUTE && b > 0) {
- usec_t cc;
- int j;
-
- j = 0;
- for (cc = table[i].usec; cc > 1; cc /= 10)
- j++;
-
- for (cc = accuracy; cc > 1; cc /= 10) {
- b /= 10;
- j--;
- }
-
- if (j > 0) {
- k = snprintf(p, l,
- "%s"USEC_FMT".%0*llu%s",
- p > buf ? " " : "",
- a,
- j,
- (unsigned long long) b,
- table[i].suffix);
-
- t = 0;
- done = true;
- }
- }
-
- /* No? Then let's show it normally */
- if (!done) {
- k = snprintf(p, l,
- "%s"USEC_FMT"%s",
- p > buf ? " " : "",
- a,
- table[i].suffix);
-
- t = b;
- }
-
- n = MIN((size_t) k, l);
-
- l -= n;
- p += n;
-
- something = true;
- }
-
- *p = 0;
-
- return buf;
-}
-
-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="USEC_FMT" "USEC_FMT"\n",
- name,
- t->realtime,
- t->monotonic);
-}
-
-int dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
- unsigned long long a, b;
-
- assert(value);
- assert(t);
-
- if (sscanf(value, "%llu %llu", &a, &b) != 2) {
- log_debug("Failed to parse dual timestamp value \"%s\": %m", value);
- return -EINVAL;
- }
-
- t->realtime = a;
- t->monotonic = b;
-
- return 0;
-}
-
-int timestamp_deserialize(const char *value, usec_t *timestamp) {
- int r;
-
- assert(value);
-
- r = safe_atou64(value, timestamp);
- if (r < 0)
- return log_debug_errno(r, "Failed to parse timestamp value \"%s\": %m", value);
-
- return r;
-}
-
-int parse_timestamp(const char *t, usec_t *usec) {
- static const struct {
- const char *name;
- const int nr;
- } day_nr[] = {
- { "Sunday", 0 },
- { "Sun", 0 },
- { "Monday", 1 },
- { "Mon", 1 },
- { "Tuesday", 2 },
- { "Tue", 2 },
- { "Wednesday", 3 },
- { "Wed", 3 },
- { "Thursday", 4 },
- { "Thu", 4 },
- { "Friday", 5 },
- { "Fri", 5 },
- { "Saturday", 6 },
- { "Sat", 6 },
- };
-
- const char *k, *utc, *tzn = NULL;
- struct tm tm, copy;
- time_t x;
- usec_t x_usec, plus = 0, minus = 0, ret;
- int r, weekday = -1, dst = -1;
- unsigned i;
-
- /*
- * 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
- * @2147483647 (seconds since epoch)
- *
- */
-
- assert(t);
- assert(usec);
-
- if (t[0] == '@')
- return parse_sec(t + 1, usec);
-
- ret = now(CLOCK_REALTIME);
-
- if (streq(t, "now"))
- goto finish;
-
- else if (t[0] == '+') {
- r = parse_sec(t+1, &plus);
- if (r < 0)
- return r;
-
- goto finish;
-
- } else if (t[0] == '-') {
- r = parse_sec(t+1, &minus);
- if (r < 0)
- return r;
-
- goto finish;
-
- } else if ((k = endswith(t, " ago"))) {
- t = strndupa(t, k - t);
-
- r = parse_sec(t, &minus);
- if (r < 0)
- return r;
-
- goto finish;
-
- } else if ((k = endswith(t, " left"))) {
- t = strndupa(t, k - t);
-
- r = parse_sec(t, &plus);
- if (r < 0)
- return r;
-
- goto finish;
- }
-
- /* See if the timestamp is suffixed with UTC */
- utc = endswith_no_case(t, " UTC");
- if (utc)
- t = strndupa(t, utc - t);
- else {
- const char *e = NULL;
- int j;
-
- tzset();
-
- /* See if the timestamp is suffixed by either the DST or non-DST local timezone. Note that we only
- * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because
- * there are no nice APIs available to cover this. By accepting the local time zone strings, we make
- * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't
- * support arbitrary timezone specifications. */
-
- for (j = 0; j <= 1; j++) {
-
- if (isempty(tzname[j]))
- continue;
-
- e = endswith_no_case(t, tzname[j]);
- if (!e)
- continue;
- if (e == t)
- continue;
- if (e[-1] != ' ')
- continue;
-
- break;
- }
-
- if (IN_SET(j, 0, 1)) {
- /* Found one of the two timezones specified. */
- t = strndupa(t, e - t - 1);
- dst = j;
- tzn = tzname[j];
- }
- }
-
- x = (time_t) (ret / USEC_PER_SEC);
- x_usec = 0;
-
- if (!localtime_or_gmtime_r(&x, &tm, utc))
- return -EINVAL;
-
- tm.tm_isdst = dst;
- if (tzn)
- tm.tm_zone = tzn;
-
- if (streq(t, "today")) {
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto from_tm;
-
- } else if (streq(t, "yesterday")) {
- tm.tm_mday--;
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto from_tm;
-
- } else if (streq(t, "tomorrow")) {
- tm.tm_mday++;
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto from_tm;
- }
-
- for (i = 0; i < ELEMENTSOF(day_nr); i++) {
- size_t skip;
-
- if (!startswith_no_case(t, day_nr[i].name))
- continue;
-
- skip = strlen(day_nr[i].name);
- if (t[skip] != ' ')
- continue;
-
- weekday = day_nr[i].nr;
- t += skip + 1;
- break;
- }
-
- copy = tm;
- k = strptime(t, "%y-%m-%d %H:%M:%S", &tm);
- if (k) {
- if (*k == '.')
- goto parse_usec;
- else if (*k == 0)
- goto from_tm;
- }
-
- tm = copy;
- k = strptime(t, "%Y-%m-%d %H:%M:%S", &tm);
- if (k) {
- if (*k == '.')
- goto parse_usec;
- else if (*k == 0)
- goto from_tm;
- }
-
- tm = copy;
- k = strptime(t, "%y-%m-%d %H:%M", &tm);
- if (k && *k == 0) {
- tm.tm_sec = 0;
- goto from_tm;
- }
-
- tm = copy;
- k = strptime(t, "%Y-%m-%d %H:%M", &tm);
- if (k && *k == 0) {
- tm.tm_sec = 0;
- goto from_tm;
- }
-
- tm = copy;
- k = strptime(t, "%y-%m-%d", &tm);
- if (k && *k == 0) {
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto from_tm;
- }
-
- tm = copy;
- k = strptime(t, "%Y-%m-%d", &tm);
- if (k && *k == 0) {
- tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
- goto from_tm;
- }
-
- tm = copy;
- k = strptime(t, "%H:%M:%S", &tm);
- if (k) {
- if (*k == '.')
- goto parse_usec;
- else if (*k == 0)
- goto from_tm;
- }
-
- tm = copy;
- k = strptime(t, "%H:%M", &tm);
- if (k && *k == 0) {
- tm.tm_sec = 0;
- goto from_tm;
- }
-
- return -EINVAL;
-
-parse_usec:
- {
- unsigned add;
-
- k++;
- r = parse_fractional_part_u(&k, 6, &add);
- if (r < 0)
- return -EINVAL;
-
- if (*k)
- return -EINVAL;
-
- x_usec = add;
- }
-
-from_tm:
- x = mktime_or_timegm(&tm, utc);
- if (x == (time_t) -1)
- return -EINVAL;
-
- if (weekday >= 0 && tm.tm_wday != weekday)
- return -EINVAL;
-
- ret = (usec_t) x * USEC_PER_SEC + x_usec;
-
-finish:
- ret += plus;
- if (ret > minus)
- ret -= minus;
- else
- ret = 0;
-
- *usec = ret;
-
- return 0;
-}
-
-static char* extract_multiplier(char *p, usec_t *multiplier) {
- static const struct {
- const char *suffix;
- usec_t usec;
- } table[] = {
- { "seconds", USEC_PER_SEC },
- { "second", USEC_PER_SEC },
- { "sec", USEC_PER_SEC },
- { "s", USEC_PER_SEC },
- { "minutes", USEC_PER_MINUTE },
- { "minute", USEC_PER_MINUTE },
- { "min", USEC_PER_MINUTE },
- { "months", USEC_PER_MONTH },
- { "month", USEC_PER_MONTH },
- { "M", USEC_PER_MONTH },
- { "msec", USEC_PER_MSEC },
- { "ms", USEC_PER_MSEC },
- { "m", USEC_PER_MINUTE },
- { "hours", USEC_PER_HOUR },
- { "hour", USEC_PER_HOUR },
- { "hr", USEC_PER_HOUR },
- { "h", USEC_PER_HOUR },
- { "days", USEC_PER_DAY },
- { "day", USEC_PER_DAY },
- { "d", USEC_PER_DAY },
- { "weeks", USEC_PER_WEEK },
- { "week", USEC_PER_WEEK },
- { "w", USEC_PER_WEEK },
- { "years", USEC_PER_YEAR },
- { "year", USEC_PER_YEAR },
- { "y", USEC_PER_YEAR },
- { "usec", 1ULL },
- { "us", 1ULL },
- };
- unsigned i;
-
- for (i = 0; i < ELEMENTSOF(table); i++) {
- char *e;
-
- e = startswith(p, table[i].suffix);
- if (e) {
- *multiplier = table[i].usec;
- return e;
- }
- }
-
- return p;
-}
-
-int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
- const char *p, *s;
- usec_t r = 0;
- bool something = false;
-
- assert(t);
- assert(usec);
- assert(default_unit > 0);
-
- p = t;
-
- p += strspn(p, WHITESPACE);
- s = startswith(p, "infinity");
- if (s) {
- s += strspn(s, WHITESPACE);
- if (*s != 0)
- return -EINVAL;
-
- *usec = USEC_INFINITY;
- return 0;
- }
-
- for (;;) {
- long long l, z = 0;
- char *e;
- unsigned n = 0;
- usec_t multiplier = default_unit, k;
-
- p += strspn(p, WHITESPACE);
-
- if (*p == 0) {
- if (!something)
- return -EINVAL;
-
- break;
- }
-
- errno = 0;
- l = strtoll(p, &e, 10);
- if (errno > 0)
- return -errno;
- if (l < 0)
- return -ERANGE;
-
- if (*e == '.') {
- char *b = e + 1;
-
- errno = 0;
- z = strtoll(b, &e, 10);
- if (errno > 0)
- return -errno;
-
- if (z < 0)
- return -ERANGE;
-
- if (e == b)
- return -EINVAL;
-
- n = e - b;
-
- } else if (e == p)
- return -EINVAL;
-
- e += strspn(e, WHITESPACE);
- p = extract_multiplier(e, &multiplier);
-
- something = true;
-
- k = (usec_t) z * multiplier;
-
- for (; n > 0; n--)
- k /= 10;
-
- r += (usec_t) l * multiplier + k;
- }
-
- *usec = r;
-
- return 0;
-}
-
-int parse_sec(const char *t, usec_t *usec) {
- return parse_time(t, usec, USEC_PER_SEC);
-}
-
-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, *s;
- nsec_t r = 0;
- bool something = false;
-
- assert(t);
- assert(nsec);
-
- p = t;
-
- p += strspn(p, WHITESPACE);
- s = startswith(p, "infinity");
- if (s) {
- s += strspn(s, WHITESPACE);
- if (*s != 0)
- return -EINVAL;
-
- *nsec = NSEC_INFINITY;
- return 0;
- }
-
- for (;;) {
- long long l, z = 0;
- char *e;
- unsigned i, n = 0;
-
- p += strspn(p, WHITESPACE);
-
- if (*p == 0) {
- if (!something)
- return -EINVAL;
-
- break;
- }
-
- errno = 0;
- l = strtoll(p, &e, 10);
-
- if (errno > 0)
- return -errno;
-
- if (l < 0)
- return -ERANGE;
-
- if (*e == '.') {
- char *b = e + 1;
-
- errno = 0;
- z = strtoll(b, &e, 10);
- if (errno > 0)
- return -errno;
-
- if (z < 0)
- return -ERANGE;
-
- if (e == b)
- return -EINVAL;
-
- n = e - b;
-
- } else if (e == p)
- return -EINVAL;
-
- e += strspn(e, WHITESPACE);
-
- for (i = 0; i < ELEMENTSOF(table); i++)
- if (startswith(e, table[i].suffix)) {
- nsec_t k = (nsec_t) z * table[i].nsec;
-
- for (; n > 0; n--)
- k /= 10;
-
- r += (nsec_t) l * table[i].nsec + k;
- p = e + strlen(table[i].suffix);
-
- something = true;
- break;
- }
-
- if (i >= ELEMENTSOF(table))
- return -EINVAL;
-
- }
-
- *nsec = r;
-
- return 0;
-}
-
-bool ntp_synced(void) {
- struct timex txc = {};
-
- if (adjtimex(&txc) < 0)
- return false;
-
- if (txc.status & STA_UNSYNC)
- return false;
-
- return true;
-}
-
-int get_timezones(char ***ret) {
- _cleanup_fclose_ FILE *f = NULL;
- _cleanup_strv_free_ char **zones = NULL;
- size_t n_zones = 0, n_allocated = 0;
-
- assert(ret);
-
- zones = strv_new("UTC", NULL);
- if (!zones)
- return -ENOMEM;
-
- n_allocated = 2;
- n_zones = 1;
-
- f = fopen("/usr/share/zoneinfo/zone.tab", "re");
- if (f) {
- char l[LINE_MAX];
-
- FOREACH_LINE(l, f, return -errno) {
- char *p, *w;
- size_t k;
-
- p = strstrip(l);
-
- if (isempty(p) || *p == '#')
- continue;
-
- /* Skip over country code */
- p += strcspn(p, WHITESPACE);
- p += strspn(p, WHITESPACE);
-
- /* Skip over coordinates */
- p += strcspn(p, WHITESPACE);
- p += strspn(p, WHITESPACE);
-
- /* Found timezone name */
- k = strcspn(p, WHITESPACE);
- if (k <= 0)
- continue;
-
- w = strndup(p, k);
- if (!w)
- return -ENOMEM;
-
- if (!GREEDY_REALLOC(zones, n_allocated, n_zones + 2)) {
- free(w);
- return -ENOMEM;
- }
-
- zones[n_zones++] = w;
- zones[n_zones] = NULL;
- }
-
- strv_sort(zones);
-
- } else if (errno != ENOENT)
- return -errno;
-
- *ret = zones;
- zones = NULL;
-
- return 0;
-}
-
-bool timezone_is_valid(const char *name) {
- bool slash = false;
- const char *p, *t;
- struct stat st;
-
- if (isempty(name))
- return false;
-
- if (name[0] == '/')
- return false;
-
- for (p = name; *p; p++) {
- if (!(*p >= '0' && *p <= '9') &&
- !(*p >= 'a' && *p <= 'z') &&
- !(*p >= 'A' && *p <= 'Z') &&
- !(*p == '-' || *p == '_' || *p == '+' || *p == '/'))
- return false;
-
- if (*p == '/') {
-
- if (slash)
- return false;
-
- slash = true;
- } else
- slash = false;
- }
-
- if (slash)
- return false;
-
- t = strjoina("/usr/share/zoneinfo/", name);
- if (stat(t, &st) < 0)
- return false;
-
- if (!S_ISREG(st.st_mode))
- return false;
-
- return true;
-}
-
-bool clock_boottime_supported(void) {
- static int supported = -1;
-
- /* Note that this checks whether CLOCK_BOOTTIME is available in general as well as available for timerfds()! */
-
- if (supported < 0) {
- int fd;
-
- fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC);
- if (fd < 0)
- supported = false;
- else {
- safe_close(fd);
- supported = true;
- }
- }
-
- return supported;
-}
-
-clockid_t clock_boottime_or_monotonic(void) {
- if (clock_boottime_supported())
- return CLOCK_BOOTTIME;
- else
- return CLOCK_MONOTONIC;
-}
-
-bool clock_supported(clockid_t clock) {
- struct timespec ts;
-
- switch (clock) {
-
- case CLOCK_MONOTONIC:
- case CLOCK_REALTIME:
- return true;
-
- case CLOCK_BOOTTIME:
- return clock_boottime_supported();
-
- case CLOCK_BOOTTIME_ALARM:
- if (!clock_boottime_supported())
- return false;
-
- /* fall through, after checking the cached value for CLOCK_BOOTTIME. */
-
- default:
- /* For everything else, check properly */
- return clock_gettime(clock, &ts) >= 0;
- }
-}
-
-int get_timezone(char **tz) {
- _cleanup_free_ char *t = NULL;
- const char *e;
- char *z;
- int r;
-
- r = readlink_malloc("/etc/localtime", &t);
- if (r < 0)
- return r; /* returns EINVAL if not a symlink */
-
- e = path_startswith(t, "/usr/share/zoneinfo/");
- if (!e)
- e = path_startswith(t, "../usr/share/zoneinfo/");
- if (!e)
- return -EINVAL;
-
- if (!timezone_is_valid(e))
- return -EINVAL;
-
- z = strdup(e);
- if (!z)
- return -ENOMEM;
-
- *tz = z;
- return 0;
-}
-
-time_t mktime_or_timegm(struct tm *tm, bool utc) {
- return utc ? timegm(tm) : mktime(tm);
-}
-
-struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc) {
- return utc ? gmtime_r(t, tm) : localtime_r(t, tm);
-}
-
-unsigned long usec_to_jiffies(usec_t u) {
- static thread_local unsigned long hz = 0;
- long r;
-
- if (hz == 0) {
- r = sysconf(_SC_CLK_TCK);
-
- assert(r > 0);
- hz = (unsigned long) r;
- }
-
- return DIV_ROUND_UP(u , USEC_PER_SEC / hz);
-}
diff --git a/src/basic/time-util.h b/src/basic/time-util.h
deleted file mode 100644
index 558b0b5b7f..0000000000
--- a/src/basic/time-util.h
+++ /dev/null
@@ -1,181 +0,0 @@
-#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 <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <time.h>
-
-typedef uint64_t usec_t;
-typedef uint64_t nsec_t;
-
-#define NSEC_FMT "%" PRIu64
-#define USEC_FMT "%" PRIu64
-
-#include "macro.h"
-
-typedef struct dual_timestamp {
- usec_t realtime;
- usec_t monotonic;
-} dual_timestamp;
-
-typedef struct triple_timestamp {
- usec_t realtime;
- usec_t monotonic;
- usec_t boottime;
-} triple_timestamp;
-
-#define USEC_INFINITY ((usec_t) -1)
-#define NSEC_INFINITY ((nsec_t) -1)
-
-#define MSEC_PER_SEC 1000ULL
-#define USEC_PER_SEC ((usec_t) 1000000ULL)
-#define USEC_PER_MSEC ((usec_t) 1000ULL)
-#define NSEC_PER_SEC ((nsec_t) 1000000000ULL)
-#define NSEC_PER_MSEC ((nsec_t) 1000000ULL)
-#define NSEC_PER_USEC ((nsec_t) 1000ULL)
-
-#define USEC_PER_MINUTE ((usec_t) (60ULL*USEC_PER_SEC))
-#define NSEC_PER_MINUTE ((nsec_t) (60ULL*NSEC_PER_SEC))
-#define USEC_PER_HOUR ((usec_t) (60ULL*USEC_PER_MINUTE))
-#define NSEC_PER_HOUR ((nsec_t) (60ULL*NSEC_PER_MINUTE))
-#define USEC_PER_DAY ((usec_t) (24ULL*USEC_PER_HOUR))
-#define NSEC_PER_DAY ((nsec_t) (24ULL*NSEC_PER_HOUR))
-#define USEC_PER_WEEK ((usec_t) (7ULL*USEC_PER_DAY))
-#define NSEC_PER_WEEK ((nsec_t) (7ULL*NSEC_PER_DAY))
-#define USEC_PER_MONTH ((usec_t) (2629800ULL*USEC_PER_SEC))
-#define NSEC_PER_MONTH ((nsec_t) (2629800ULL*NSEC_PER_SEC))
-#define USEC_PER_YEAR ((usec_t) (31557600ULL*USEC_PER_SEC))
-#define NSEC_PER_YEAR ((nsec_t) (31557600ULL*NSEC_PER_SEC))
-
-/* We assume a maximum timezone length of 6. TZNAME_MAX is not defined on Linux, but glibc internally initializes this
- * to 6. Let's rely on that. */
-#define FORMAT_TIMESTAMP_MAX (3+1+10+1+8+1+6+1+6+1)
-#define FORMAT_TIMESTAMP_WIDTH 28 /* when outputting, assume this width */
-#define FORMAT_TIMESTAMP_RELATIVE_MAX 256
-#define FORMAT_TIMESPAN_MAX 64
-
-#define TIME_T_MAX (time_t)((UINTMAX_C(1) << ((sizeof(time_t) << 3) - 1)) - 1)
-
-#define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) {})
-#define TRIPLE_TIMESTAMP_NULL ((struct triple_timestamp) {})
-
-usec_t now(clockid_t clock);
-nsec_t now_nsec(clockid_t clock);
-
-dual_timestamp* dual_timestamp_get(dual_timestamp *ts);
-dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u);
-dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u);
-dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, usec_t u);
-
-triple_timestamp* triple_timestamp_get(triple_timestamp *ts);
-triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u);
-
-#define DUAL_TIMESTAMP_HAS_CLOCK(clock) \
- IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC)
-
-#define TRIPLE_TIMESTAMP_HAS_CLOCK(clock) \
- IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM)
-
-static inline bool dual_timestamp_is_set(dual_timestamp *ts) {
- return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) ||
- (ts->monotonic > 0 && ts->monotonic != USEC_INFINITY));
-}
-
-static inline bool triple_timestamp_is_set(triple_timestamp *ts) {
- return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) ||
- (ts->monotonic > 0 && ts->monotonic != USEC_INFINITY) ||
- (ts->boottime > 0 && ts->boottime != USEC_INFINITY));
-}
-
-usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock);
-
-usec_t timespec_load(const struct timespec *ts) _pure_;
-nsec_t timespec_load_nsec(const struct timespec *ts) _pure_;
-struct timespec *timespec_store(struct timespec *ts, usec_t u);
-
-usec_t timeval_load(const struct timeval *tv) _pure_;
-struct timeval *timeval_store(struct timeval *tv, usec_t u);
-
-char *format_timestamp(char *buf, size_t l, usec_t t);
-char *format_timestamp_utc(char *buf, size_t l, usec_t t);
-char *format_timestamp_us(char *buf, size_t l, usec_t t);
-char *format_timestamp_us_utc(char *buf, size_t l, usec_t t);
-char *format_timestamp_relative(char *buf, size_t l, usec_t t);
-char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy);
-
-void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t);
-int dual_timestamp_deserialize(const char *value, dual_timestamp *t);
-int timestamp_deserialize(const char *value, usec_t *timestamp);
-
-int parse_timestamp(const char *t, usec_t *usec);
-
-int parse_sec(const char *t, usec_t *usec);
-int parse_time(const char *t, usec_t *usec, usec_t default_unit);
-int parse_nsec(const char *t, nsec_t *nsec);
-
-bool ntp_synced(void);
-
-int get_timezones(char ***l);
-bool timezone_is_valid(const char *name);
-
-bool clock_boottime_supported(void);
-bool clock_supported(clockid_t clock);
-clockid_t clock_boottime_or_monotonic(void);
-
-#define xstrftime(buf, fmt, tm) \
- assert_message_se(strftime(buf, ELEMENTSOF(buf), fmt, tm) > 0, \
- "xstrftime: " #buf "[] must be big enough")
-
-int get_timezone(char **timezone);
-
-time_t mktime_or_timegm(struct tm *tm, bool utc);
-struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc);
-
-unsigned long usec_to_jiffies(usec_t usec);
-
-static inline usec_t usec_add(usec_t a, usec_t b) {
- usec_t c;
-
- /* Adds two time values, and makes sure USEC_INFINITY as input results as USEC_INFINITY in output, and doesn't
- * overflow. */
-
- c = a + b;
- if (c < a || c < b) /* overflow check */
- return USEC_INFINITY;
-
- return c;
-}
-
-static inline usec_t usec_sub(usec_t timestamp, int64_t delta) {
- if (delta < 0)
- return usec_add(timestamp, (usec_t) (-delta));
-
- if (timestamp == USEC_INFINITY) /* Make sure infinity doesn't degrade */
- return USEC_INFINITY;
-
- if (timestamp < (usec_t) delta)
- return 0;
-
- return timestamp - delta;
-}
diff --git a/src/basic/umask-util.h b/src/basic/umask-util.h
deleted file mode 100644
index 359d87d27c..0000000000
--- a/src/basic/umask-util.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#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 <sys/stat.h>
-#include <sys/types.h>
-
-#include "macro.h"
-
-static inline void umaskp(mode_t *u) {
- umask(*u);
-}
-
-#define _cleanup_umask_ _cleanup_(umaskp)
-
-struct _umask_struct_ {
- mode_t mask;
- bool quit;
-};
-
-static inline void _reset_umask_(struct _umask_struct_ *s) {
- umask(s->mask);
-};
-
-#define RUN_WITH_UMASK(mask) \
- for (_cleanup_(_reset_umask_) struct _umask_struct_ _saved_umask_ = { umask(mask), false }; \
- !_saved_umask_.quit ; \
- _saved_umask_.quit = true)
diff --git a/src/basic/unaligned.h b/src/basic/unaligned.h
deleted file mode 100644
index 7c847a3ccb..0000000000
--- a/src/basic/unaligned.h
+++ /dev/null
@@ -1,129 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen
-
- 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 <endian.h>
-#include <stdint.h>
-
-/* BE */
-
-static inline uint16_t unaligned_read_be16(const void *_u) {
- const uint8_t *u = _u;
-
- return (((uint16_t) u[0]) << 8) |
- ((uint16_t) u[1]);
-}
-
-static inline uint32_t unaligned_read_be32(const void *_u) {
- const uint8_t *u = _u;
-
- return (((uint32_t) unaligned_read_be16(u)) << 16) |
- ((uint32_t) unaligned_read_be16(u + 2));
-}
-
-static inline uint64_t unaligned_read_be64(const void *_u) {
- const uint8_t *u = _u;
-
- return (((uint64_t) unaligned_read_be32(u)) << 32) |
- ((uint64_t) unaligned_read_be32(u + 4));
-}
-
-static inline void unaligned_write_be16(void *_u, uint16_t a) {
- uint8_t *u = _u;
-
- u[0] = (uint8_t) (a >> 8);
- u[1] = (uint8_t) a;
-}
-
-static inline void unaligned_write_be32(void *_u, uint32_t a) {
- uint8_t *u = _u;
-
- unaligned_write_be16(u, (uint16_t) (a >> 16));
- unaligned_write_be16(u + 2, (uint16_t) a);
-}
-
-static inline void unaligned_write_be64(void *_u, uint64_t a) {
- uint8_t *u = _u;
-
- unaligned_write_be32(u, (uint32_t) (a >> 32));
- unaligned_write_be32(u + 4, (uint32_t) a);
-}
-
-/* LE */
-
-static inline uint16_t unaligned_read_le16(const void *_u) {
- const uint8_t *u = _u;
-
- return (((uint16_t) u[1]) << 8) |
- ((uint16_t) u[0]);
-}
-
-static inline uint32_t unaligned_read_le32(const void *_u) {
- const uint8_t *u = _u;
-
- return (((uint32_t) unaligned_read_le16(u + 2)) << 16) |
- ((uint32_t) unaligned_read_le16(u));
-}
-
-static inline uint64_t unaligned_read_le64(const void *_u) {
- const uint8_t *u = _u;
-
- return (((uint64_t) unaligned_read_le32(u + 4)) << 32) |
- ((uint64_t) unaligned_read_le32(u));
-}
-
-static inline void unaligned_write_le16(void *_u, uint16_t a) {
- uint8_t *u = _u;
-
- u[0] = (uint8_t) a;
- u[1] = (uint8_t) (a >> 8);
-}
-
-static inline void unaligned_write_le32(void *_u, uint32_t a) {
- uint8_t *u = _u;
-
- unaligned_write_le16(u, (uint16_t) a);
- unaligned_write_le16(u + 2, (uint16_t) (a >> 16));
-}
-
-static inline void unaligned_write_le64(void *_u, uint64_t a) {
- uint8_t *u = _u;
-
- unaligned_write_le32(u, (uint32_t) a);
- unaligned_write_le32(u + 4, (uint32_t) (a >> 32));
-}
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-#define unaligned_read_ne16 unaligned_read_be16
-#define unaligned_read_ne32 unaligned_read_be32
-#define unaligned_read_ne64 unaligned_read_be64
-
-#define unaligned_write_ne16 unaligned_write_be16
-#define unaligned_write_ne32 unaligned_write_be32
-#define unaligned_write_ne64 unaligned_write_be64
-#else
-#define unaligned_read_ne16 unaligned_read_le16
-#define unaligned_read_ne32 unaligned_read_le32
-#define unaligned_read_ne64 unaligned_read_le64
-
-#define unaligned_write_ne16 unaligned_write_le16
-#define unaligned_write_ne32 unaligned_write_le32
-#define unaligned_write_ne64 unaligned_write_le64
-#endif
diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c
deleted file mode 100644
index fe883b95c7..0000000000
--- a/src/basic/unit-name.c
+++ /dev/null
@@ -1,1049 +0,0 @@
-/***
- 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 <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "alloc-util.h"
-#include "bus-label.h"
-#include "glob-util.h"
-#include "hexdecoct.h"
-#include "macro.h"
-#include "path-util.h"
-#include "string-table.h"
-#include "string-util.h"
-#include "strv.h"
-#include "unit-name.h"
-
-/* Characters valid in a unit name. */
-#define VALID_CHARS \
- DIGITS \
- LETTERS \
- ":-_.\\"
-
-/* The same, but also permits the single @ character that may appear */
-#define VALID_CHARS_WITH_AT \
- "@" \
- VALID_CHARS
-
-/* All chars valid in a unit name glob */
-#define VALID_CHARS_GLOB \
- VALID_CHARS_WITH_AT \
- "[]!-*?"
-
-bool unit_name_is_valid(const char *n, UnitNameFlags flags) {
- const char *e, *i, *at;
-
- assert((flags & ~(UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)) == 0);
-
- if (_unlikely_(flags == 0))
- return false;
-
- if (isempty(n))
- return false;
-
- if (strlen(n) >= UNIT_NAME_MAX)
- return false;
-
- e = strrchr(n, '.');
- if (!e || e == n)
- return false;
-
- if (unit_type_from_string(e + 1) < 0)
- return false;
-
- for (i = n, at = NULL; i < e; i++) {
-
- if (*i == '@' && !at)
- at = i;
-
- if (!strchr("@" VALID_CHARS, *i))
- return false;
- }
-
- if (at == n)
- return false;
-
- if (flags & UNIT_NAME_PLAIN)
- if (!at)
- return true;
-
- if (flags & UNIT_NAME_INSTANCE)
- if (at && e > at + 1)
- return true;
-
- if (flags & UNIT_NAME_TEMPLATE)
- if (at && e == at + 1)
- return true;
-
- return false;
-}
-
-bool unit_prefix_is_valid(const char *p) {
-
- /* We don't allow additional @ in the prefix string */
-
- if (isempty(p))
- return false;
-
- return in_charset(p, VALID_CHARS);
-}
-
-bool unit_instance_is_valid(const char *i) {
-
- /* The max length depends on the length of the string, so we
- * don't really check this here. */
-
- if (isempty(i))
- return false;
-
- /* We allow additional @ in the instance string, we do not
- * allow them in the prefix! */
-
- return in_charset(i, "@" VALID_CHARS);
-}
-
-bool unit_suffix_is_valid(const char *s) {
- if (isempty(s))
- return false;
-
- if (s[0] != '.')
- return false;
-
- if (unit_type_from_string(s + 1) < 0)
- return false;
-
- return true;
-}
-
-int unit_name_to_prefix(const char *n, char **ret) {
- const char *p;
- char *s;
-
- assert(n);
- assert(ret);
-
- if (!unit_name_is_valid(n, UNIT_NAME_ANY))
- return -EINVAL;
-
- p = strchr(n, '@');
- if (!p)
- p = strrchr(n, '.');
-
- assert_se(p);
-
- s = strndup(n, p - n);
- if (!s)
- return -ENOMEM;
-
- *ret = s;
- return 0;
-}
-
-int unit_name_to_instance(const char *n, char **instance) {
- const char *p, *d;
- char *i;
-
- assert(n);
- assert(instance);
-
- if (!unit_name_is_valid(n, UNIT_NAME_ANY))
- return -EINVAL;
-
- /* Everything past the first @ and before the last . is the instance */
- p = strchr(n, '@');
- if (!p) {
- *instance = NULL;
- return 0;
- }
-
- p++;
-
- d = strrchr(p, '.');
- if (!d)
- return -EINVAL;
-
- i = strndup(p, d-p);
- if (!i)
- return -ENOMEM;
-
- *instance = i;
- return 1;
-}
-
-int unit_name_to_prefix_and_instance(const char *n, char **ret) {
- const char *d;
- char *s;
-
- assert(n);
- assert(ret);
-
- if (!unit_name_is_valid(n, UNIT_NAME_ANY))
- return -EINVAL;
-
- d = strrchr(n, '.');
- if (!d)
- return -EINVAL;
-
- s = strndup(n, d - n);
- if (!s)
- return -ENOMEM;
-
- *ret = s;
- return 0;
-}
-
-UnitType unit_name_to_type(const char *n) {
- const char *e;
-
- assert(n);
-
- if (!unit_name_is_valid(n, UNIT_NAME_ANY))
- return _UNIT_TYPE_INVALID;
-
- assert_se(e = strrchr(n, '.'));
-
- return unit_type_from_string(e + 1);
-}
-
-int unit_name_change_suffix(const char *n, const char *suffix, char **ret) {
- char *e, *s;
- size_t a, b;
-
- assert(n);
- assert(suffix);
- assert(ret);
-
- if (!unit_name_is_valid(n, UNIT_NAME_ANY))
- return -EINVAL;
-
- if (!unit_suffix_is_valid(suffix))
- return -EINVAL;
-
- assert_se(e = strrchr(n, '.'));
-
- a = e - n;
- b = strlen(suffix);
-
- s = new(char, a + b + 1);
- if (!s)
- return -ENOMEM;
-
- strcpy(mempcpy(s, n, a), suffix);
- *ret = s;
-
- return 0;
-}
-
-int unit_name_build(const char *prefix, const char *instance, const char *suffix, char **ret) {
- char *s;
-
- assert(prefix);
- assert(suffix);
- assert(ret);
-
- if (!unit_prefix_is_valid(prefix))
- return -EINVAL;
-
- if (instance && !unit_instance_is_valid(instance))
- return -EINVAL;
-
- if (!unit_suffix_is_valid(suffix))
- return -EINVAL;
-
- if (!instance)
- s = strappend(prefix, suffix);
- else
- s = strjoin(prefix, "@", instance, suffix, NULL);
- if (!s)
- return -ENOMEM;
-
- *ret = s;
- return 0;
-}
-
-static char *do_escape_char(char c, char *t) {
- assert(t);
-
- *(t++) = '\\';
- *(t++) = 'x';
- *(t++) = hexchar(c >> 4);
- *(t++) = hexchar(c);
-
- return t;
-}
-
-static char *do_escape(const char *f, char *t) {
- assert(f);
- assert(t);
-
- /* do not create units with a leading '.', like for "/.dotdir" mount points */
- if (*f == '.') {
- t = do_escape_char(*f, t);
- f++;
- }
-
- for (; *f; f++) {
- if (*f == '/')
- *(t++) = '-';
- else if (*f == '-' || *f == '\\' || !strchr(VALID_CHARS, *f))
- t = do_escape_char(*f, t);
- else
- *(t++) = *f;
- }
-
- return t;
-}
-
-char *unit_name_escape(const char *f) {
- char *r, *t;
-
- assert(f);
-
- r = new(char, strlen(f)*4+1);
- if (!r)
- return NULL;
-
- t = do_escape(f, r);
- *t = 0;
-
- return r;
-}
-
-int unit_name_unescape(const char *f, char **ret) {
- _cleanup_free_ char *r = NULL;
- char *t;
-
- assert(f);
-
- r = strdup(f);
- if (!r)
- return -ENOMEM;
-
- for (t = r; *f; f++) {
- if (*f == '-')
- *(t++) = '/';
- else if (*f == '\\') {
- int a, b;
-
- if (f[1] != 'x')
- return -EINVAL;
-
- a = unhexchar(f[2]);
- if (a < 0)
- return -EINVAL;
-
- b = unhexchar(f[3]);
- if (b < 0)
- return -EINVAL;
-
- *(t++) = (char) (((uint8_t) a << 4U) | (uint8_t) b);
- f += 3;
- } else
- *(t++) = *f;
- }
-
- *t = 0;
-
- *ret = r;
- r = NULL;
-
- return 0;
-}
-
-int unit_name_path_escape(const char *f, char **ret) {
- char *p, *s;
-
- assert(f);
- assert(ret);
-
- p = strdupa(f);
- if (!p)
- return -ENOMEM;
-
- path_kill_slashes(p);
-
- if (STR_IN_SET(p, "/", ""))
- s = strdup("-");
- else {
- char *e;
-
- if (!path_is_safe(p))
- return -EINVAL;
-
- /* Truncate trailing slashes */
- e = endswith(p, "/");
- if (e)
- *e = 0;
-
- /* Truncate leading slashes */
- if (p[0] == '/')
- p++;
-
- s = unit_name_escape(p);
- }
- if (!s)
- return -ENOMEM;
-
- *ret = s;
- return 0;
-}
-
-int unit_name_path_unescape(const char *f, char **ret) {
- char *s;
- int r;
-
- assert(f);
-
- if (isempty(f))
- return -EINVAL;
-
- if (streq(f, "-")) {
- s = strdup("/");
- if (!s)
- return -ENOMEM;
- } else {
- char *w;
-
- r = unit_name_unescape(f, &w);
- if (r < 0)
- return r;
-
- /* Don't accept trailing or leading slashes */
- if (startswith(w, "/") || endswith(w, "/")) {
- free(w);
- return -EINVAL;
- }
-
- /* Prefix a slash again */
- s = strappend("/", w);
- free(w);
- if (!s)
- return -ENOMEM;
-
- if (!path_is_safe(s)) {
- free(s);
- return -EINVAL;
- }
- }
-
- if (ret)
- *ret = s;
- else
- free(s);
-
- return 0;
-}
-
-int unit_name_replace_instance(const char *f, const char *i, char **ret) {
- const char *p, *e;
- char *s;
- size_t a, b;
-
- assert(f);
- assert(i);
- assert(ret);
-
- if (!unit_name_is_valid(f, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE))
- return -EINVAL;
- if (!unit_instance_is_valid(i))
- return -EINVAL;
-
- assert_se(p = strchr(f, '@'));
- assert_se(e = strrchr(f, '.'));
-
- a = p - f;
- b = strlen(i);
-
- s = new(char, a + 1 + b + strlen(e) + 1);
- if (!s)
- return -ENOMEM;
-
- strcpy(mempcpy(mempcpy(s, f, a + 1), i, b), e);
-
- *ret = s;
- return 0;
-}
-
-int unit_name_template(const char *f, char **ret) {
- const char *p, *e;
- char *s;
- size_t a;
-
- assert(f);
- assert(ret);
-
- if (!unit_name_is_valid(f, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE))
- return -EINVAL;
-
- assert_se(p = strchr(f, '@'));
- assert_se(e = strrchr(f, '.'));
-
- a = p - f;
-
- s = new(char, a + 1 + strlen(e) + 1);
- if (!s)
- return -ENOMEM;
-
- strcpy(mempcpy(s, f, a + 1), e);
-
- *ret = s;
- return 0;
-}
-
-int unit_name_from_path(const char *path, const char *suffix, char **ret) {
- _cleanup_free_ char *p = NULL;
- char *s = NULL;
- int r;
-
- assert(path);
- assert(suffix);
- assert(ret);
-
- if (!unit_suffix_is_valid(suffix))
- return -EINVAL;
-
- r = unit_name_path_escape(path, &p);
- if (r < 0)
- return r;
-
- s = strappend(p, suffix);
- if (!s)
- return -ENOMEM;
-
- *ret = s;
- return 0;
-}
-
-int unit_name_from_path_instance(const char *prefix, const char *path, const char *suffix, char **ret) {
- _cleanup_free_ char *p = NULL;
- char *s;
- int r;
-
- assert(prefix);
- assert(path);
- assert(suffix);
- assert(ret);
-
- if (!unit_prefix_is_valid(prefix))
- return -EINVAL;
-
- if (!unit_suffix_is_valid(suffix))
- return -EINVAL;
-
- r = unit_name_path_escape(path, &p);
- if (r < 0)
- return r;
-
- s = strjoin(prefix, "@", p, suffix, NULL);
- if (!s)
- return -ENOMEM;
-
- *ret = s;
- return 0;
-}
-
-int unit_name_to_path(const char *name, char **ret) {
- _cleanup_free_ char *prefix = NULL;
- int r;
-
- assert(name);
-
- r = unit_name_to_prefix(name, &prefix);
- if (r < 0)
- return r;
-
- return unit_name_path_unescape(prefix, ret);
-}
-
-char *unit_dbus_path_from_name(const char *name) {
- _cleanup_free_ char *e = NULL;
-
- assert(name);
-
- e = bus_label_escape(name);
- if (!e)
- return NULL;
-
- return strappend("/org/freedesktop/systemd1/unit/", e);
-}
-
-int unit_name_from_dbus_path(const char *path, char **name) {
- const char *e;
- char *n;
-
- e = startswith(path, "/org/freedesktop/systemd1/unit/");
- if (!e)
- return -EINVAL;
-
- n = bus_label_unescape(e);
- if (!n)
- return -ENOMEM;
-
- *name = n;
- return 0;
-}
-
-const char* unit_dbus_interface_from_type(UnitType t) {
-
- static const char *const table[_UNIT_TYPE_MAX] = {
- [UNIT_SERVICE] = "org.freedesktop.systemd1.Service",
- [UNIT_SOCKET] = "org.freedesktop.systemd1.Socket",
- [UNIT_BUSNAME] = "org.freedesktop.systemd1.BusName",
- [UNIT_TARGET] = "org.freedesktop.systemd1.Target",
- [UNIT_DEVICE] = "org.freedesktop.systemd1.Device",
- [UNIT_MOUNT] = "org.freedesktop.systemd1.Mount",
- [UNIT_AUTOMOUNT] = "org.freedesktop.systemd1.Automount",
- [UNIT_SWAP] = "org.freedesktop.systemd1.Swap",
- [UNIT_TIMER] = "org.freedesktop.systemd1.Timer",
- [UNIT_PATH] = "org.freedesktop.systemd1.Path",
- [UNIT_SLICE] = "org.freedesktop.systemd1.Slice",
- [UNIT_SCOPE] = "org.freedesktop.systemd1.Scope",
- };
-
- if (t < 0)
- return NULL;
- if (t >= _UNIT_TYPE_MAX)
- return NULL;
-
- return table[t];
-}
-
-const char *unit_dbus_interface_from_name(const char *name) {
- UnitType t;
-
- t = unit_name_to_type(name);
- if (t < 0)
- return NULL;
-
- return unit_dbus_interface_from_type(t);
-}
-
-static char *do_escape_mangle(const char *f, UnitNameMangle allow_globs, char *t) {
- const char *valid_chars;
-
- assert(f);
- assert(IN_SET(allow_globs, UNIT_NAME_GLOB, UNIT_NAME_NOGLOB));
- assert(t);
-
- /* We'll only escape the obvious characters here, to play
- * safe. */
-
- valid_chars = allow_globs == UNIT_NAME_GLOB ? VALID_CHARS_GLOB : VALID_CHARS_WITH_AT;
-
- for (; *f; f++) {
- if (*f == '/')
- *(t++) = '-';
- else if (!strchr(valid_chars, *f))
- t = do_escape_char(*f, t);
- else
- *(t++) = *f;
- }
-
- return t;
-}
-
-/**
- * Convert a string to a unit name. /dev/blah is converted to dev-blah.device,
- * /blah/blah is converted to blah-blah.mount, anything else is left alone,
- * except that @suffix is appended if a valid unit suffix is not present.
- *
- * If @allow_globs, globs characters are preserved. Otherwise, they are escaped.
- */
-int unit_name_mangle_with_suffix(const char *name, UnitNameMangle allow_globs, const char *suffix, char **ret) {
- char *s, *t;
- int r;
-
- assert(name);
- assert(suffix);
- assert(ret);
-
- if (isempty(name)) /* We cannot mangle empty unit names to become valid, sorry. */
- return -EINVAL;
-
- if (!unit_suffix_is_valid(suffix))
- return -EINVAL;
-
- /* Already a fully valid unit name? If so, no mangling is necessary... */
- if (unit_name_is_valid(name, UNIT_NAME_ANY))
- goto good;
-
- /* Already a fully valid globbing expression? If so, no mangling is necessary either... */
- if (allow_globs == UNIT_NAME_GLOB &&
- string_is_glob(name) &&
- in_charset(name, VALID_CHARS_GLOB))
- goto good;
-
- if (is_device_path(name)) {
- r = unit_name_from_path(name, ".device", ret);
- if (r >= 0)
- return 1;
- if (r != -EINVAL)
- return r;
- }
-
- if (path_is_absolute(name)) {
- r = unit_name_from_path(name, ".mount", ret);
- if (r >= 0)
- return 1;
- if (r != -EINVAL)
- return r;
- }
-
- s = new(char, strlen(name) * 4 + strlen(suffix) + 1);
- if (!s)
- return -ENOMEM;
-
- t = do_escape_mangle(name, allow_globs, s);
- *t = 0;
-
- /* Append a suffix if it doesn't have any, but only if this is not a glob, so that we can allow "foo.*" as a
- * valid glob. */
- if ((allow_globs != UNIT_NAME_GLOB || !string_is_glob(s)) && unit_name_to_type(s) < 0)
- strcpy(t, suffix);
-
- *ret = s;
- return 1;
-
-good:
- s = strdup(name);
- if (!s)
- return -ENOMEM;
-
- *ret = s;
- return 0;
-}
-
-int slice_build_parent_slice(const char *slice, char **ret) {
- char *s, *dash;
- int r;
-
- assert(slice);
- assert(ret);
-
- if (!slice_name_is_valid(slice))
- return -EINVAL;
-
- if (streq(slice, "-.slice")) {
- *ret = NULL;
- return 0;
- }
-
- s = strdup(slice);
- if (!s)
- return -ENOMEM;
-
- dash = strrchr(s, '-');
- if (dash)
- strcpy(dash, ".slice");
- else {
- r = free_and_strdup(&s, "-.slice");
- if (r < 0) {
- free(s);
- return r;
- }
- }
-
- *ret = s;
- return 1;
-}
-
-int slice_build_subslice(const char *slice, const char*name, char **ret) {
- char *subslice;
-
- assert(slice);
- assert(name);
- assert(ret);
-
- if (!slice_name_is_valid(slice))
- return -EINVAL;
-
- if (!unit_prefix_is_valid(name))
- return -EINVAL;
-
- if (streq(slice, "-.slice"))
- subslice = strappend(name, ".slice");
- else {
- char *e;
-
- assert_se(e = endswith(slice, ".slice"));
-
- subslice = new(char, (e - slice) + 1 + strlen(name) + 6 + 1);
- if (!subslice)
- return -ENOMEM;
-
- stpcpy(stpcpy(stpcpy(mempcpy(subslice, slice, e - slice), "-"), name), ".slice");
- }
-
- *ret = subslice;
- return 0;
-}
-
-bool slice_name_is_valid(const char *name) {
- const char *p, *e;
- bool dash = false;
-
- if (!unit_name_is_valid(name, UNIT_NAME_PLAIN))
- return false;
-
- if (streq(name, "-.slice"))
- return true;
-
- e = endswith(name, ".slice");
- if (!e)
- return false;
-
- for (p = name; p < e; p++) {
-
- if (*p == '-') {
-
- /* Don't allow initial dash */
- if (p == name)
- return false;
-
- /* Don't allow multiple dashes */
- if (dash)
- return false;
-
- dash = true;
- } else
- dash = false;
- }
-
- /* Don't allow trailing hash */
- if (dash)
- return false;
-
- return true;
-}
-
-static const char* const unit_type_table[_UNIT_TYPE_MAX] = {
- [UNIT_SERVICE] = "service",
- [UNIT_SOCKET] = "socket",
- [UNIT_BUSNAME] = "busname",
- [UNIT_TARGET] = "target",
- [UNIT_DEVICE] = "device",
- [UNIT_MOUNT] = "mount",
- [UNIT_AUTOMOUNT] = "automount",
- [UNIT_SWAP] = "swap",
- [UNIT_TIMER] = "timer",
- [UNIT_PATH] = "path",
- [UNIT_SLICE] = "slice",
- [UNIT_SCOPE] = "scope",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(unit_type, UnitType);
-
-static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
- [UNIT_STUB] = "stub",
- [UNIT_LOADED] = "loaded",
- [UNIT_NOT_FOUND] = "not-found",
- [UNIT_ERROR] = "error",
- [UNIT_MERGED] = "merged",
- [UNIT_MASKED] = "masked"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
-
-static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
- [UNIT_ACTIVE] = "active",
- [UNIT_RELOADING] = "reloading",
- [UNIT_INACTIVE] = "inactive",
- [UNIT_FAILED] = "failed",
- [UNIT_ACTIVATING] = "activating",
- [UNIT_DEACTIVATING] = "deactivating"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState);
-
-static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = {
- [AUTOMOUNT_DEAD] = "dead",
- [AUTOMOUNT_WAITING] = "waiting",
- [AUTOMOUNT_RUNNING] = "running",
- [AUTOMOUNT_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(automount_state, AutomountState);
-
-static const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
- [BUSNAME_DEAD] = "dead",
- [BUSNAME_MAKING] = "making",
- [BUSNAME_REGISTERED] = "registered",
- [BUSNAME_LISTENING] = "listening",
- [BUSNAME_RUNNING] = "running",
- [BUSNAME_SIGTERM] = "sigterm",
- [BUSNAME_SIGKILL] = "sigkill",
- [BUSNAME_FAILED] = "failed",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
-
-static const char* const device_state_table[_DEVICE_STATE_MAX] = {
- [DEVICE_DEAD] = "dead",
- [DEVICE_TENTATIVE] = "tentative",
- [DEVICE_PLUGGED] = "plugged",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
-
-static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
- [MOUNT_DEAD] = "dead",
- [MOUNT_MOUNTING] = "mounting",
- [MOUNT_MOUNTING_DONE] = "mounting-done",
- [MOUNT_MOUNTED] = "mounted",
- [MOUNT_REMOUNTING] = "remounting",
- [MOUNT_UNMOUNTING] = "unmounting",
- [MOUNT_MOUNTING_SIGTERM] = "mounting-sigterm",
- [MOUNT_MOUNTING_SIGKILL] = "mounting-sigkill",
- [MOUNT_REMOUNTING_SIGTERM] = "remounting-sigterm",
- [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
- [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
- [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill",
- [MOUNT_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
-
-static const char* const path_state_table[_PATH_STATE_MAX] = {
- [PATH_DEAD] = "dead",
- [PATH_WAITING] = "waiting",
- [PATH_RUNNING] = "running",
- [PATH_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(path_state, PathState);
-
-static const char* const scope_state_table[_SCOPE_STATE_MAX] = {
- [SCOPE_DEAD] = "dead",
- [SCOPE_RUNNING] = "running",
- [SCOPE_ABANDONED] = "abandoned",
- [SCOPE_STOP_SIGTERM] = "stop-sigterm",
- [SCOPE_STOP_SIGKILL] = "stop-sigkill",
- [SCOPE_FAILED] = "failed",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
-
-static const char* const service_state_table[_SERVICE_STATE_MAX] = {
- [SERVICE_DEAD] = "dead",
- [SERVICE_START_PRE] = "start-pre",
- [SERVICE_START] = "start",
- [SERVICE_START_POST] = "start-post",
- [SERVICE_RUNNING] = "running",
- [SERVICE_EXITED] = "exited",
- [SERVICE_RELOAD] = "reload",
- [SERVICE_STOP] = "stop",
- [SERVICE_STOP_SIGABRT] = "stop-sigabrt",
- [SERVICE_STOP_SIGTERM] = "stop-sigterm",
- [SERVICE_STOP_SIGKILL] = "stop-sigkill",
- [SERVICE_STOP_POST] = "stop-post",
- [SERVICE_FINAL_SIGTERM] = "final-sigterm",
- [SERVICE_FINAL_SIGKILL] = "final-sigkill",
- [SERVICE_FAILED] = "failed",
- [SERVICE_AUTO_RESTART] = "auto-restart",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(service_state, ServiceState);
-
-static const char* const slice_state_table[_SLICE_STATE_MAX] = {
- [SLICE_DEAD] = "dead",
- [SLICE_ACTIVE] = "active"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
-
-static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
- [SOCKET_DEAD] = "dead",
- [SOCKET_START_PRE] = "start-pre",
- [SOCKET_START_CHOWN] = "start-chown",
- [SOCKET_START_POST] = "start-post",
- [SOCKET_LISTENING] = "listening",
- [SOCKET_RUNNING] = "running",
- [SOCKET_STOP_PRE] = "stop-pre",
- [SOCKET_STOP_PRE_SIGTERM] = "stop-pre-sigterm",
- [SOCKET_STOP_PRE_SIGKILL] = "stop-pre-sigkill",
- [SOCKET_STOP_POST] = "stop-post",
- [SOCKET_FINAL_SIGTERM] = "final-sigterm",
- [SOCKET_FINAL_SIGKILL] = "final-sigkill",
- [SOCKET_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(socket_state, SocketState);
-
-static const char* const swap_state_table[_SWAP_STATE_MAX] = {
- [SWAP_DEAD] = "dead",
- [SWAP_ACTIVATING] = "activating",
- [SWAP_ACTIVATING_DONE] = "activating-done",
- [SWAP_ACTIVE] = "active",
- [SWAP_DEACTIVATING] = "deactivating",
- [SWAP_ACTIVATING_SIGTERM] = "activating-sigterm",
- [SWAP_ACTIVATING_SIGKILL] = "activating-sigkill",
- [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm",
- [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill",
- [SWAP_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
-
-static const char* const target_state_table[_TARGET_STATE_MAX] = {
- [TARGET_DEAD] = "dead",
- [TARGET_ACTIVE] = "active"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(target_state, TargetState);
-
-static const char* const timer_state_table[_TIMER_STATE_MAX] = {
- [TIMER_DEAD] = "dead",
- [TIMER_WAITING] = "waiting",
- [TIMER_RUNNING] = "running",
- [TIMER_ELAPSED] = "elapsed",
- [TIMER_FAILED] = "failed"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
-
-static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
- [UNIT_REQUIRES] = "Requires",
- [UNIT_REQUISITE] = "Requisite",
- [UNIT_WANTS] = "Wants",
- [UNIT_BINDS_TO] = "BindsTo",
- [UNIT_PART_OF] = "PartOf",
- [UNIT_REQUIRED_BY] = "RequiredBy",
- [UNIT_REQUISITE_OF] = "RequisiteOf",
- [UNIT_WANTED_BY] = "WantedBy",
- [UNIT_BOUND_BY] = "BoundBy",
- [UNIT_CONSISTS_OF] = "ConsistsOf",
- [UNIT_CONFLICTS] = "Conflicts",
- [UNIT_CONFLICTED_BY] = "ConflictedBy",
- [UNIT_BEFORE] = "Before",
- [UNIT_AFTER] = "After",
- [UNIT_ON_FAILURE] = "OnFailure",
- [UNIT_TRIGGERS] = "Triggers",
- [UNIT_TRIGGERED_BY] = "TriggeredBy",
- [UNIT_PROPAGATES_RELOAD_TO] = "PropagatesReloadTo",
- [UNIT_RELOAD_PROPAGATED_FROM] = "ReloadPropagatedFrom",
- [UNIT_JOINS_NAMESPACE_OF] = "JoinsNamespaceOf",
- [UNIT_REFERENCES] = "References",
- [UNIT_REFERENCED_BY] = "ReferencedBy",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);
diff --git a/src/basic/unit-name.h b/src/basic/unit-name.h
deleted file mode 100644
index 44eadf0347..0000000000
--- a/src/basic/unit-name.h
+++ /dev/null
@@ -1,367 +0,0 @@
-#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 "macro.h"
-
-#define UNIT_NAME_MAX 256
-
-typedef enum UnitType {
- UNIT_SERVICE = 0,
- UNIT_SOCKET,
- UNIT_BUSNAME,
- UNIT_TARGET,
- UNIT_DEVICE,
- UNIT_MOUNT,
- UNIT_AUTOMOUNT,
- UNIT_SWAP,
- UNIT_TIMER,
- UNIT_PATH,
- UNIT_SLICE,
- UNIT_SCOPE,
- _UNIT_TYPE_MAX,
- _UNIT_TYPE_INVALID = -1
-} UnitType;
-
-typedef enum UnitLoadState {
- UNIT_STUB = 0,
- UNIT_LOADED,
- UNIT_NOT_FOUND,
- UNIT_ERROR,
- UNIT_MERGED,
- UNIT_MASKED,
- _UNIT_LOAD_STATE_MAX,
- _UNIT_LOAD_STATE_INVALID = -1
-} UnitLoadState;
-
-typedef enum UnitActiveState {
- UNIT_ACTIVE,
- UNIT_RELOADING,
- UNIT_INACTIVE,
- UNIT_FAILED,
- UNIT_ACTIVATING,
- UNIT_DEACTIVATING,
- _UNIT_ACTIVE_STATE_MAX,
- _UNIT_ACTIVE_STATE_INVALID = -1
-} UnitActiveState;
-
-typedef enum AutomountState {
- AUTOMOUNT_DEAD,
- AUTOMOUNT_WAITING,
- AUTOMOUNT_RUNNING,
- AUTOMOUNT_FAILED,
- _AUTOMOUNT_STATE_MAX,
- _AUTOMOUNT_STATE_INVALID = -1
-} AutomountState;
-
-typedef enum BusNameState {
- BUSNAME_DEAD,
- BUSNAME_MAKING,
- BUSNAME_REGISTERED,
- BUSNAME_LISTENING,
- BUSNAME_RUNNING,
- BUSNAME_SIGTERM,
- BUSNAME_SIGKILL,
- BUSNAME_FAILED,
- _BUSNAME_STATE_MAX,
- _BUSNAME_STATE_INVALID = -1
-} BusNameState;
-
-/* We simply watch devices, we cannot plug/unplug them. That
- * simplifies the state engine greatly */
-typedef enum DeviceState {
- DEVICE_DEAD,
- DEVICE_TENTATIVE, /* mounted or swapped, but not (yet) announced by udev */
- DEVICE_PLUGGED, /* announced by udev */
- _DEVICE_STATE_MAX,
- _DEVICE_STATE_INVALID = -1
-} DeviceState;
-
-typedef enum MountState {
- MOUNT_DEAD,
- MOUNT_MOUNTING, /* /usr/bin/mount is running, but the mount is not done yet. */
- MOUNT_MOUNTING_DONE, /* /usr/bin/mount is running, and the mount is done. */
- MOUNT_MOUNTED,
- MOUNT_REMOUNTING,
- MOUNT_UNMOUNTING,
- MOUNT_MOUNTING_SIGTERM,
- MOUNT_MOUNTING_SIGKILL,
- MOUNT_REMOUNTING_SIGTERM,
- MOUNT_REMOUNTING_SIGKILL,
- MOUNT_UNMOUNTING_SIGTERM,
- MOUNT_UNMOUNTING_SIGKILL,
- MOUNT_FAILED,
- _MOUNT_STATE_MAX,
- _MOUNT_STATE_INVALID = -1
-} MountState;
-
-typedef enum PathState {
- PATH_DEAD,
- PATH_WAITING,
- PATH_RUNNING,
- PATH_FAILED,
- _PATH_STATE_MAX,
- _PATH_STATE_INVALID = -1
-} PathState;
-
-typedef enum ScopeState {
- SCOPE_DEAD,
- SCOPE_RUNNING,
- SCOPE_ABANDONED,
- SCOPE_STOP_SIGTERM,
- SCOPE_STOP_SIGKILL,
- SCOPE_FAILED,
- _SCOPE_STATE_MAX,
- _SCOPE_STATE_INVALID = -1
-} ScopeState;
-
-typedef enum ServiceState {
- SERVICE_DEAD,
- SERVICE_START_PRE,
- SERVICE_START,
- SERVICE_START_POST,
- SERVICE_RUNNING,
- SERVICE_EXITED, /* Nothing is running anymore, but RemainAfterExit is true hence this is OK */
- SERVICE_RELOAD,
- SERVICE_STOP, /* No STOP_PRE state, instead just register multiple STOP executables */
- SERVICE_STOP_SIGABRT, /* Watchdog timeout */
- SERVICE_STOP_SIGTERM,
- SERVICE_STOP_SIGKILL,
- SERVICE_STOP_POST,
- SERVICE_FINAL_SIGTERM, /* In case the STOP_POST executable hangs, we shoot that down, too */
- SERVICE_FINAL_SIGKILL,
- SERVICE_FAILED,
- SERVICE_AUTO_RESTART,
- _SERVICE_STATE_MAX,
- _SERVICE_STATE_INVALID = -1
-} ServiceState;
-
-typedef enum SliceState {
- SLICE_DEAD,
- SLICE_ACTIVE,
- _SLICE_STATE_MAX,
- _SLICE_STATE_INVALID = -1
-} SliceState;
-
-typedef enum SocketState {
- SOCKET_DEAD,
- SOCKET_START_PRE,
- SOCKET_START_CHOWN,
- SOCKET_START_POST,
- SOCKET_LISTENING,
- SOCKET_RUNNING,
- SOCKET_STOP_PRE,
- SOCKET_STOP_PRE_SIGTERM,
- SOCKET_STOP_PRE_SIGKILL,
- SOCKET_STOP_POST,
- SOCKET_FINAL_SIGTERM,
- SOCKET_FINAL_SIGKILL,
- SOCKET_FAILED,
- _SOCKET_STATE_MAX,
- _SOCKET_STATE_INVALID = -1
-} SocketState;
-
-typedef enum SwapState {
- SWAP_DEAD,
- SWAP_ACTIVATING, /* /sbin/swapon is running, but the swap not yet enabled. */
- SWAP_ACTIVATING_DONE, /* /sbin/swapon is running, and the swap is done. */
- SWAP_ACTIVE,
- SWAP_DEACTIVATING,
- SWAP_ACTIVATING_SIGTERM,
- SWAP_ACTIVATING_SIGKILL,
- SWAP_DEACTIVATING_SIGTERM,
- SWAP_DEACTIVATING_SIGKILL,
- SWAP_FAILED,
- _SWAP_STATE_MAX,
- _SWAP_STATE_INVALID = -1
-} SwapState;
-
-typedef enum TargetState {
- TARGET_DEAD,
- TARGET_ACTIVE,
- _TARGET_STATE_MAX,
- _TARGET_STATE_INVALID = -1
-} TargetState;
-
-typedef enum TimerState {
- TIMER_DEAD,
- TIMER_WAITING,
- TIMER_RUNNING,
- TIMER_ELAPSED,
- TIMER_FAILED,
- _TIMER_STATE_MAX,
- _TIMER_STATE_INVALID = -1
-} TimerState;
-
-typedef enum UnitDependency {
- /* Positive dependencies */
- UNIT_REQUIRES,
- UNIT_REQUISITE,
- UNIT_WANTS,
- UNIT_BINDS_TO,
- UNIT_PART_OF,
-
- /* Inverse of the above */
- UNIT_REQUIRED_BY, /* inverse of 'requires' is 'required_by' */
- UNIT_REQUISITE_OF, /* inverse of 'requisite' is 'requisite_of' */
- UNIT_WANTED_BY, /* inverse of 'wants' */
- UNIT_BOUND_BY, /* inverse of 'binds_to' */
- UNIT_CONSISTS_OF, /* inverse of 'part_of' */
-
- /* Negative dependencies */
- UNIT_CONFLICTS, /* inverse of 'conflicts' is 'conflicted_by' */
- UNIT_CONFLICTED_BY,
-
- /* Order */
- UNIT_BEFORE, /* inverse of 'before' is 'after' and vice versa */
- UNIT_AFTER,
-
- /* On Failure */
- UNIT_ON_FAILURE,
-
- /* Triggers (i.e. a socket triggers a service) */
- UNIT_TRIGGERS,
- UNIT_TRIGGERED_BY,
-
- /* Propagate reloads */
- UNIT_PROPAGATES_RELOAD_TO,
- UNIT_RELOAD_PROPAGATED_FROM,
-
- /* Joins namespace of */
- UNIT_JOINS_NAMESPACE_OF,
-
- /* Reference information for GC logic */
- UNIT_REFERENCES, /* Inverse of 'references' is 'referenced_by' */
- UNIT_REFERENCED_BY,
-
- _UNIT_DEPENDENCY_MAX,
- _UNIT_DEPENDENCY_INVALID = -1
-} UnitDependency;
-
-typedef enum UnitNameFlags {
- UNIT_NAME_PLAIN = 1, /* Allow foo.service */
- UNIT_NAME_INSTANCE = 2, /* Allow foo@bar.service */
- UNIT_NAME_TEMPLATE = 4, /* Allow foo@.service */
- UNIT_NAME_ANY = UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE,
-} UnitNameFlags;
-
-bool unit_name_is_valid(const char *n, UnitNameFlags flags) _pure_;
-bool unit_prefix_is_valid(const char *p) _pure_;
-bool unit_instance_is_valid(const char *i) _pure_;
-bool unit_suffix_is_valid(const char *s) _pure_;
-
-static inline int unit_prefix_and_instance_is_valid(const char *p) {
- /* For prefix+instance and instance the same rules apply */
- return unit_instance_is_valid(p);
-}
-
-int unit_name_to_prefix(const char *n, char **prefix);
-int unit_name_to_instance(const char *n, char **instance);
-int unit_name_to_prefix_and_instance(const char *n, char **ret);
-
-UnitType unit_name_to_type(const char *n) _pure_;
-
-int unit_name_change_suffix(const char *n, const char *suffix, char **ret);
-
-int unit_name_build(const char *prefix, const char *instance, const char *suffix, char **ret);
-
-char *unit_name_escape(const char *f);
-int unit_name_unescape(const char *f, char **ret);
-int unit_name_path_escape(const char *f, char **ret);
-int unit_name_path_unescape(const char *f, char **ret);
-
-int unit_name_replace_instance(const char *f, const char *i, char **ret);
-
-int unit_name_template(const char *f, char **ret);
-
-int unit_name_from_path(const char *path, const char *suffix, char **ret);
-int unit_name_from_path_instance(const char *prefix, const char *path, const char *suffix, char **ret);
-int unit_name_to_path(const char *name, char **ret);
-
-char *unit_dbus_path_from_name(const char *name);
-int unit_name_from_dbus_path(const char *path, char **name);
-
-const char* unit_dbus_interface_from_type(UnitType t);
-const char *unit_dbus_interface_from_name(const char *name);
-
-typedef enum UnitNameMangle {
- UNIT_NAME_NOGLOB,
- UNIT_NAME_GLOB,
-} UnitNameMangle;
-
-int unit_name_mangle_with_suffix(const char *name, UnitNameMangle allow_globs, const char *suffix, char **ret);
-
-static inline int unit_name_mangle(const char *name, UnitNameMangle allow_globs, char **ret) {
- return unit_name_mangle_with_suffix(name, allow_globs, ".service", ret);
-}
-
-int slice_build_parent_slice(const char *slice, char **ret);
-int slice_build_subslice(const char *slice, const char*name, char **subslice);
-bool slice_name_is_valid(const char *name);
-
-const char *unit_type_to_string(UnitType i) _const_;
-UnitType unit_type_from_string(const char *s) _pure_;
-
-const char *unit_load_state_to_string(UnitLoadState i) _const_;
-UnitLoadState unit_load_state_from_string(const char *s) _pure_;
-
-const char *unit_active_state_to_string(UnitActiveState i) _const_;
-UnitActiveState unit_active_state_from_string(const char *s) _pure_;
-
-const char* automount_state_to_string(AutomountState i) _const_;
-AutomountState automount_state_from_string(const char *s) _pure_;
-
-const char* busname_state_to_string(BusNameState i) _const_;
-BusNameState busname_state_from_string(const char *s) _pure_;
-
-const char* device_state_to_string(DeviceState i) _const_;
-DeviceState device_state_from_string(const char *s) _pure_;
-
-const char* mount_state_to_string(MountState i) _const_;
-MountState mount_state_from_string(const char *s) _pure_;
-
-const char* path_state_to_string(PathState i) _const_;
-PathState path_state_from_string(const char *s) _pure_;
-
-const char* scope_state_to_string(ScopeState i) _const_;
-ScopeState scope_state_from_string(const char *s) _pure_;
-
-const char* service_state_to_string(ServiceState i) _const_;
-ServiceState service_state_from_string(const char *s) _pure_;
-
-const char* slice_state_to_string(SliceState i) _const_;
-SliceState slice_state_from_string(const char *s) _pure_;
-
-const char* socket_state_to_string(SocketState i) _const_;
-SocketState socket_state_from_string(const char *s) _pure_;
-
-const char* swap_state_to_string(SwapState i) _const_;
-SwapState swap_state_from_string(const char *s) _pure_;
-
-const char* target_state_to_string(TargetState i) _const_;
-TargetState target_state_from_string(const char *s) _pure_;
-
-const char *timer_state_to_string(TimerState i) _const_;
-TimerState timer_state_from_string(const char *s) _pure_;
-
-const char *unit_dependency_to_string(UnitDependency i) _const_;
-UnitDependency unit_dependency_from_string(const char *s) _pure_;
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
deleted file mode 100644
index de6c93056e..0000000000
--- a/src/basic/user-util.c
+++ /dev/null
@@ -1,636 +0,0 @@
-/***
- 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 <alloca.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <grp.h>
-#include <pwd.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <utmp.h>
-
-#include "alloc-util.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "formats-util.h"
-#include "macro.h"
-#include "missing.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "string-util.h"
-#include "strv.h"
-#include "user-util.h"
-#include "utf8.h"
-
-bool uid_is_valid(uid_t uid) {
-
- /* Some libc APIs use UID_INVALID as special placeholder */
- if (uid == (uid_t) UINT32_C(0xFFFFFFFF))
- return false;
-
- /* A long time ago UIDs where 16bit, hence explicitly avoid the 16bit -1 too */
- if (uid == (uid_t) UINT32_C(0xFFFF))
- return false;
-
- return true;
-}
-
-int parse_uid(const char *s, uid_t *ret) {
- uint32_t uid = 0;
- int r;
-
- assert(s);
-
- assert_cc(sizeof(uid_t) == sizeof(uint32_t));
- r = safe_atou32(s, &uid);
- if (r < 0)
- return r;
-
- if (!uid_is_valid(uid))
- return -ENXIO; /* we return ENXIO instead of EINVAL
- * here, to make it easy to distuingish
- * invalid numeric uids from invalid
- * strings. */
-
- if (ret)
- *ret = uid;
-
- return 0;
-}
-
-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 uid_to_name(uid);
-}
-
-char *getusername_malloc(void) {
- const char *e;
-
- e = getenv("USER");
- if (e)
- return strdup(e);
-
- return uid_to_name(getuid());
-}
-
-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) {
- if (!uid_is_valid(p->pw_uid))
- return -EBADMSG;
-
- *uid = p->pw_uid;
- }
-
- if (gid) {
- if (!gid_is_valid(p->pw_gid))
- return -EBADMSG;
-
- *gid = p->pw_gid;
- }
-
- if (home)
- *home = p->pw_dir;
-
- if (shell)
- *shell = p->pw_shell;
-
- return 0;
-}
-
-int get_user_creds_clean(
- const char **username,
- uid_t *uid, gid_t *gid,
- const char **home,
- const char **shell) {
-
- int r;
-
- /* Like get_user_creds(), but resets home/shell to NULL if they don't contain anything relevant. */
-
- r = get_user_creds(username, uid, gid, home, shell);
- if (r < 0)
- return r;
-
- if (shell &&
- (isempty(*shell) || PATH_IN_SET(*shell,
- "/bin/nologin",
- "/sbin/nologin",
- "/usr/bin/nologin",
- "/usr/sbin/nologin")))
- *shell = NULL;
-
- if (home &&
- (isempty(*home) || path_equal(*home, "/")))
- *home = NULL;
-
- 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) {
- if (!gid_is_valid(g->gr_gid))
- return -EBADMSG;
-
- *gid = g->gr_gid;
- }
-
- return 0;
-}
-
-char* uid_to_name(uid_t uid) {
- char *ret;
- int r;
-
- /* Shortcut things to avoid NSS lookups */
- if (uid == 0)
- return strdup("root");
-
- if (uid_is_valid(uid)) {
- long bufsize;
-
- bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
- if (bufsize <= 0)
- bufsize = 4096;
-
- for (;;) {
- struct passwd pwbuf, *pw = NULL;
- _cleanup_free_ char *buf = NULL;
-
- buf = malloc(bufsize);
- if (!buf)
- return NULL;
-
- r = getpwuid_r(uid, &pwbuf, buf, (size_t) bufsize, &pw);
- if (r == 0 && pw)
- return strdup(pw->pw_name);
- if (r != ERANGE)
- break;
-
- bufsize *= 2;
- }
- }
-
- if (asprintf(&ret, UID_FMT, uid) < 0)
- return NULL;
-
- return ret;
-}
-
-char* gid_to_name(gid_t gid) {
- char *ret;
- int r;
-
- if (gid == 0)
- return strdup("root");
-
- if (gid_is_valid(gid)) {
- long bufsize;
-
- bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
- if (bufsize <= 0)
- bufsize = 4096;
-
- for (;;) {
- struct group grbuf, *gr = NULL;
- _cleanup_free_ char *buf = NULL;
-
- buf = malloc(bufsize);
- if (!buf)
- return NULL;
-
- r = getgrgid_r(gid, &grbuf, buf, (size_t) bufsize, &gr);
- if (r == 0 && gr)
- return strdup(gr->gr_name);
- if (r != ERANGE)
- break;
-
- bufsize *= 2;
- }
- }
-
- if (asprintf(&ret, GID_FMT, gid) < 0)
- return NULL;
-
- return ret;
-}
-
-int in_gid(gid_t gid) {
- gid_t *gids;
- int ngroups_max, r, i;
-
- if (getgid() == gid)
- return 1;
-
- if (getegid() == gid)
- return 1;
-
- if (!gid_is_valid(gid))
- return -EINVAL;
-
- 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 in_group(const char *name) {
- int r;
- gid_t gid;
-
- r = get_group_creds(&name, &gid);
- if (r < 0)
- return r;
-
- return in_gid(gid);
-}
-
-int get_home_dir(char **_h) {
- struct passwd *p;
- const char *e;
- char *h;
- uid_t u;
-
- assert(_h);
-
- /* Take the user specified one */
- e = secure_getenv("HOME");
- if (e && path_is_absolute(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 > 0 ? -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 **_s) {
- struct passwd *p;
- const char *e;
- char *s;
- uid_t u;
-
- assert(_s);
-
- /* Take the user specified one */
- e = getenv("SHELL");
- if (e) {
- s = strdup(e);
- if (!s)
- return -ENOMEM;
-
- *_s = s;
- return 0;
- }
-
- /* Hardcode home directory for root to avoid NSS */
- u = getuid();
- if (u == 0) {
- s = strdup("/bin/sh");
- if (!s)
- return -ENOMEM;
-
- *_s = s;
- return 0;
- }
-
- /* Check the database... */
- errno = 0;
- p = getpwuid(u);
- if (!p)
- return errno > 0 ? -errno : -ESRCH;
-
- if (!path_is_absolute(p->pw_shell))
- return -EINVAL;
-
- s = strdup(p->pw_shell);
- if (!s)
- return -ENOMEM;
-
- *_s = s;
- return 0;
-}
-
-int reset_uid_gid(void) {
- int r;
-
- r = maybe_setgroups(0, NULL);
- if (r < 0)
- return r;
-
- if (setresgid(0, 0, 0) < 0)
- return -errno;
-
- if (setresuid(0, 0, 0) < 0)
- return -errno;
-
- return 0;
-}
-
-int take_etc_passwd_lock(const char *root) {
-
- struct flock flock = {
- .l_type = F_WRLCK,
- .l_whence = SEEK_SET,
- .l_start = 0,
- .l_len = 0,
- };
-
- const char *path;
- int fd, r;
-
- /* This is roughly the same as lckpwdf(), but not as awful. We
- * don't want to use alarm() and signals, hence we implement
- * our own trivial version of this.
- *
- * Note that shadow-utils also takes per-database locks in
- * addition to lckpwdf(). However, we don't given that they
- * are redundant as they invoke lckpwdf() first and keep
- * it during everything they do. The per-database locks are
- * awfully racy, and thus we just won't do them. */
-
- if (root)
- path = prefix_roota(root, "/etc/.pwd.lock");
- else
- path = "/etc/.pwd.lock";
-
- fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600);
- if (fd < 0)
- return -errno;
-
- r = fcntl(fd, F_SETLKW, &flock);
- if (r < 0) {
- safe_close(fd);
- return -errno;
- }
-
- return fd;
-}
-
-bool valid_user_group_name(const char *u) {
- const char *i;
- long sz;
-
- /* Checks if the specified name is a valid user/group name. */
-
- if (isempty(u))
- return false;
-
- if (!(u[0] >= 'a' && u[0] <= 'z') &&
- !(u[0] >= 'A' && u[0] <= 'Z') &&
- u[0] != '_')
- return false;
-
- for (i = u+1; *i; i++) {
- if (!(*i >= 'a' && *i <= 'z') &&
- !(*i >= 'A' && *i <= 'Z') &&
- !(*i >= '0' && *i <= '9') &&
- *i != '_' &&
- *i != '-')
- return false;
- }
-
- sz = sysconf(_SC_LOGIN_NAME_MAX);
- assert_se(sz > 0);
-
- if ((size_t) (i-u) > (size_t) sz)
- return false;
-
- if ((size_t) (i-u) > UT_NAMESIZE - 1)
- return false;
-
- return true;
-}
-
-bool valid_user_group_name_or_id(const char *u) {
-
- /* Similar as above, but is also fine with numeric UID/GID specifications, as long as they are in the right
- * range, and not the invalid user ids. */
-
- if (isempty(u))
- return false;
-
- if (valid_user_group_name(u))
- return true;
-
- return parse_uid(u, NULL) >= 0;
-}
-
-bool valid_gecos(const char *d) {
-
- if (!d)
- return false;
-
- if (!utf8_is_valid(d))
- return false;
-
- if (string_has_cc(d, NULL))
- return false;
-
- /* Colons are used as field separators, and hence not OK */
- if (strchr(d, ':'))
- return false;
-
- return true;
-}
-
-bool valid_home(const char *p) {
-
- if (isempty(p))
- return false;
-
- if (!utf8_is_valid(p))
- return false;
-
- if (string_has_cc(p, NULL))
- return false;
-
- if (!path_is_absolute(p))
- return false;
-
- if (!path_is_safe(p))
- return false;
-
- /* Colons are used as field separators, and hence not OK */
- if (strchr(p, ':'))
- return false;
-
- return true;
-}
-
-int maybe_setgroups(size_t size, const gid_t *list) {
- int r;
-
- /* Check if setgroups is allowed before we try to drop all the auxiliary groups */
- if (size == 0) { /* Dropping all aux groups? */
- _cleanup_free_ char *setgroups_content = NULL;
- bool can_setgroups;
-
- r = read_one_line_file("/proc/self/setgroups", &setgroups_content);
- if (r == -ENOENT)
- /* Old kernels don't have /proc/self/setgroups, so assume we can use setgroups */
- can_setgroups = true;
- else if (r < 0)
- return r;
- else
- can_setgroups = streq(setgroups_content, "allow");
-
- if (!can_setgroups) {
- log_debug("Skipping setgroups(), /proc/self/setgroups is set to 'deny'");
- return 0;
- }
- }
-
- if (setgroups(size, list) < 0)
- return -errno;
-
- return 0;
-}
diff --git a/src/basic/user-util.h b/src/basic/user-util.h
deleted file mode 100644
index dfea561bde..0000000000
--- a/src/basic/user-util.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#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 <stdint.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-bool uid_is_valid(uid_t uid);
-
-static inline bool gid_is_valid(gid_t gid) {
- return uid_is_valid((uid_t) gid);
-}
-
-int parse_uid(const char *s, uid_t* ret_uid);
-
-static inline int parse_gid(const char *s, gid_t *ret_gid) {
- return parse_uid(s, (uid_t*) ret_gid);
-}
-
-char* getlogname_malloc(void);
-char* getusername_malloc(void);
-
-int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home, const char **shell);
-int get_user_creds_clean(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);
-
-char* uid_to_name(uid_t uid);
-char* gid_to_name(gid_t gid);
-
-int in_gid(gid_t gid);
-int in_group(const char *name);
-
-int get_home_dir(char **ret);
-int get_shell(char **_ret);
-
-int reset_uid_gid(void);
-
-int take_etc_passwd_lock(const char *root);
-
-#define UID_INVALID ((uid_t) -1)
-#define GID_INVALID ((gid_t) -1)
-
-/* Let's pick a UIDs within the 16bit range, so that we are compatible with containers using 16bit
- * user namespacing. At least on Fedora normal users are allocated until UID 60000, hence do not
- * allocate from below this. Also stay away from the upper end of the range as that is often used
- * for overflow/nobody users. */
-#define DYNAMIC_UID_MIN ((uid_t) UINT32_C(0x0000EF00))
-#define DYNAMIC_UID_MAX ((uid_t) UINT32_C(0x0000FFEF))
-
-static inline bool uid_is_dynamic(uid_t uid) {
- return DYNAMIC_UID_MIN <= uid && uid <= DYNAMIC_UID_MAX;
-}
-
-/* The following macros add 1 when converting things, since UID 0 is a valid UID, while the pointer
- * NULL is special */
-#define PTR_TO_UID(p) ((uid_t) (((uintptr_t) (p))-1))
-#define UID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1))
-
-#define PTR_TO_GID(p) ((gid_t) (((uintptr_t) (p))-1))
-#define GID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1))
-
-static inline bool userns_supported(void) {
- return access("/proc/self/uid_map", F_OK) >= 0;
-}
-
-bool valid_user_group_name(const char *u);
-bool valid_user_group_name_or_id(const char *u);
-bool valid_gecos(const char *d);
-bool valid_home(const char *p);
-
-int maybe_setgroups(size_t size, const gid_t *list);
diff --git a/src/basic/utf8.c b/src/basic/utf8.c
deleted file mode 100644
index 6eae2b983d..0000000000
--- a/src/basic/utf8.c
+++ /dev/null
@@ -1,409 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2008-2011 Kay Sievers
- Copyright 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/>.
-***/
-
-/* Parts of this file are based on the GLIB utf8 validation functions. The
- * original license text follows. */
-
-/* gutf8.c - Operations on UTF-8 strings.
- *
- * Copyright (C) 1999 Tom Tromey
- * Copyright (C) 2000 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <errno.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "alloc-util.h"
-#include "hexdecoct.h"
-#include "macro.h"
-#include "utf8.h"
-
-bool unichar_is_valid(char32_t ch) {
-
- if (ch >= 0x110000) /* End of unicode space */
- return false;
- if ((ch & 0xFFFFF800) == 0xD800) /* Reserved area for UTF-16 */
- return false;
- if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) /* Reserved */
- return false;
- if ((ch & 0xFFFE) == 0xFFFE) /* BOM (Byte Order Mark) */
- return false;
-
- return true;
-}
-
-static bool unichar_is_control(char32_t ch) {
-
- /*
- 0 to ' '-1 is the C0 range.
- DEL=0x7F, and DEL+1 to 0x9F is C1 range.
- '\t' is in C0 range, but more or less harmless and commonly used.
- */
-
- return (ch < ' ' && ch != '\t' && ch != '\n') ||
- (0x7F <= ch && ch <= 0x9F);
-}
-
-/* count of characters used to encode one unicode char */
-static int utf8_encoded_expected_len(const char *str) {
- unsigned char c;
-
- assert(str);
-
- c = (unsigned char) str[0];
- if (c < 0x80)
- return 1;
- if ((c & 0xe0) == 0xc0)
- return 2;
- if ((c & 0xf0) == 0xe0)
- return 3;
- if ((c & 0xf8) == 0xf0)
- return 4;
- if ((c & 0xfc) == 0xf8)
- return 5;
- if ((c & 0xfe) == 0xfc)
- return 6;
-
- return 0;
-}
-
-/* decode one unicode char */
-int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar) {
- char32_t unichar;
- int len, i;
-
- assert(str);
-
- len = utf8_encoded_expected_len(str);
-
- switch (len) {
- case 1:
- *ret_unichar = (char32_t)str[0];
- return 0;
- case 2:
- unichar = str[0] & 0x1f;
- break;
- case 3:
- unichar = (char32_t)str[0] & 0x0f;
- break;
- case 4:
- unichar = (char32_t)str[0] & 0x07;
- break;
- case 5:
- unichar = (char32_t)str[0] & 0x03;
- break;
- case 6:
- unichar = (char32_t)str[0] & 0x01;
- break;
- default:
- return -EINVAL;
- }
-
- for (i = 1; i < len; i++) {
- if (((char32_t)str[i] & 0xc0) != 0x80)
- return -EINVAL;
- unichar <<= 6;
- unichar |= (char32_t)str[i] & 0x3f;
- }
-
- *ret_unichar = unichar;
-
- return 0;
-}
-
-bool utf8_is_printable_newline(const char* str, size_t length, bool newline) {
- const char *p;
-
- assert(str);
-
- for (p = str; length;) {
- int encoded_len, r;
- char32_t val;
-
- encoded_len = utf8_encoded_valid_unichar(p);
- if (encoded_len < 0 ||
- (size_t) encoded_len > length)
- return false;
-
- r = utf8_encoded_to_unichar(p, &val);
- if (r < 0 ||
- unichar_is_control(val) ||
- (!newline && val == '\n'))
- return false;
-
- length -= encoded_len;
- p += encoded_len;
- }
-
- return true;
-}
-
-const char *utf8_is_valid(const char *str) {
- const uint8_t *p;
-
- assert(str);
-
- for (p = (const uint8_t*) str; *p; ) {
- int len;
-
- len = utf8_encoded_valid_unichar((const char *)p);
- if (len < 0)
- return NULL;
-
- p += len;
- }
-
- return str;
-}
-
-char *utf8_escape_invalid(const char *str) {
- char *p, *s;
-
- assert(str);
-
- p = s = malloc(strlen(str) * 4 + 1);
- if (!p)
- return NULL;
-
- while (*str) {
- int len;
-
- len = utf8_encoded_valid_unichar(str);
- if (len > 0) {
- s = mempcpy(s, str, len);
- str += len;
- } else {
- s = stpcpy(s, UTF8_REPLACEMENT_CHARACTER);
- str += 1;
- }
- }
-
- *s = '\0';
-
- return p;
-}
-
-char *utf8_escape_non_printable(const char *str) {
- char *p, *s;
-
- assert(str);
-
- p = s = malloc(strlen(str) * 4 + 1);
- if (!p)
- return NULL;
-
- while (*str) {
- int len;
-
- len = utf8_encoded_valid_unichar(str);
- if (len > 0) {
- if (utf8_is_printable(str, len)) {
- s = mempcpy(s, str, len);
- str += len;
- } else {
- while (len > 0) {
- *(s++) = '\\';
- *(s++) = 'x';
- *(s++) = hexchar((int) *str >> 4);
- *(s++) = hexchar((int) *str);
-
- str += 1;
- len--;
- }
- }
- } else {
- s = stpcpy(s, UTF8_REPLACEMENT_CHARACTER);
- str += 1;
- }
- }
-
- *s = '\0';
-
- return p;
-}
-
-char *ascii_is_valid(const char *str) {
- const char *p;
-
- assert(str);
-
- for (p = str; *p; p++)
- if ((unsigned char) *p >= 128)
- return NULL;
-
- return (char*) str;
-}
-
-/**
- * utf8_encode_unichar() - Encode single UCS-4 character as UTF-8
- * @out_utf8: output buffer of at least 4 bytes or NULL
- * @g: UCS-4 character to encode
- *
- * This encodes a single UCS-4 character as UTF-8 and writes it into @out_utf8.
- * The length of the character is returned. It is not zero-terminated! If the
- * output buffer is NULL, only the length is returned.
- *
- * Returns: The length in bytes that the UTF-8 representation does or would
- * occupy.
- */
-size_t utf8_encode_unichar(char *out_utf8, char32_t g) {
-
- if (g < (1 << 7)) {
- if (out_utf8)
- out_utf8[0] = g & 0x7f;
- return 1;
- } else if (g < (1 << 11)) {
- if (out_utf8) {
- out_utf8[0] = 0xc0 | ((g >> 6) & 0x1f);
- out_utf8[1] = 0x80 | (g & 0x3f);
- }
- return 2;
- } else if (g < (1 << 16)) {
- if (out_utf8) {
- out_utf8[0] = 0xe0 | ((g >> 12) & 0x0f);
- out_utf8[1] = 0x80 | ((g >> 6) & 0x3f);
- out_utf8[2] = 0x80 | (g & 0x3f);
- }
- return 3;
- } else if (g < (1 << 21)) {
- if (out_utf8) {
- out_utf8[0] = 0xf0 | ((g >> 18) & 0x07);
- out_utf8[1] = 0x80 | ((g >> 12) & 0x3f);
- out_utf8[2] = 0x80 | ((g >> 6) & 0x3f);
- out_utf8[3] = 0x80 | (g & 0x3f);
- }
- return 4;
- }
-
- return 0;
-}
-
-char *utf16_to_utf8(const void *s, size_t length) {
- const uint8_t *f;
- char *r, *t;
-
- r = new(char, (length * 4 + 1) / 2 + 1);
- if (!r)
- return NULL;
-
- f = s;
- t = r;
-
- while (f < (const uint8_t*) s + length) {
- char16_t w1, w2;
-
- /* see RFC 2781 section 2.2 */
-
- w1 = f[1] << 8 | f[0];
- f += 2;
-
- if (!utf16_is_surrogate(w1)) {
- t += utf8_encode_unichar(t, w1);
-
- continue;
- }
-
- if (utf16_is_trailing_surrogate(w1))
- continue;
- else if (f >= (const uint8_t*) s + length)
- break;
-
- w2 = f[1] << 8 | f[0];
- f += 2;
-
- if (!utf16_is_trailing_surrogate(w2)) {
- f -= 2;
- continue;
- }
-
- t += utf8_encode_unichar(t, utf16_surrogate_pair_to_unichar(w1, w2));
- }
-
- *t = 0;
- return r;
-}
-
-/* expected size used to encode one unicode char */
-static int utf8_unichar_to_encoded_len(char32_t unichar) {
-
- if (unichar < 0x80)
- return 1;
- if (unichar < 0x800)
- return 2;
- if (unichar < 0x10000)
- return 3;
- if (unichar < 0x200000)
- return 4;
- if (unichar < 0x4000000)
- return 5;
-
- return 6;
-}
-
-/* validate one encoded unicode char and return its length */
-int utf8_encoded_valid_unichar(const char *str) {
- int len, i, r;
- char32_t unichar;
-
- assert(str);
-
- len = utf8_encoded_expected_len(str);
- if (len == 0)
- return -EINVAL;
-
- /* ascii is valid */
- if (len == 1)
- return 1;
-
- /* check if expected encoded chars are available */
- for (i = 0; i < len; i++)
- if ((str[i] & 0x80) != 0x80)
- return -EINVAL;
-
- r = utf8_encoded_to_unichar(str, &unichar);
- if (r < 0)
- return r;
-
- /* check if encoded length matches encoded value */
- if (utf8_unichar_to_encoded_len(unichar) != len)
- return -EINVAL;
-
- /* check if value has valid range */
- if (!unichar_is_valid(unichar))
- return -EINVAL;
-
- return len;
-}
diff --git a/src/basic/utf8.h b/src/basic/utf8.h
deleted file mode 100644
index f9b9c9468b..0000000000
--- a/src/basic/utf8.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 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>
-#include <stddef.h>
-#include <stdint.h>
-#include <uchar.h>
-
-#include "macro.h"
-#include "missing.h"
-
-#define UTF8_REPLACEMENT_CHARACTER "\xef\xbf\xbd"
-#define UTF8_BYTE_ORDER_MARK "\xef\xbb\xbf"
-
-bool unichar_is_valid(char32_t c);
-
-const char *utf8_is_valid(const char *s) _pure_;
-char *ascii_is_valid(const char *s) _pure_;
-
-bool utf8_is_printable_newline(const char* str, size_t length, bool newline) _pure_;
-#define utf8_is_printable(str, length) utf8_is_printable_newline(str, length, true)
-
-char *utf8_escape_invalid(const char *s);
-char *utf8_escape_non_printable(const char *str);
-
-size_t utf8_encode_unichar(char *out_utf8, char32_t g);
-char *utf16_to_utf8(const void *s, size_t length);
-
-int utf8_encoded_valid_unichar(const char *str);
-int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar);
-
-static inline bool utf16_is_surrogate(char16_t c) {
- return (0xd800 <= c && c <= 0xdfff);
-}
-
-static inline bool utf16_is_trailing_surrogate(char16_t c) {
- return (0xdc00 <= c && c <= 0xdfff);
-}
-
-static inline char32_t utf16_surrogate_pair_to_unichar(char16_t lead, char16_t trail) {
- return ((lead - 0xd800) << 10) + (trail - 0xdc00) + 0x10000;
-}
diff --git a/src/basic/util.c b/src/basic/util.c
deleted file mode 100644
index ec7939dc83..0000000000
--- a/src/basic/util.c
+++ /dev/null
@@ -1,876 +0,0 @@
-/***
- 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 <alloca.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sched.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/prctl.h>
-#include <sys/statfs.h>
-#include <sys/sysmacros.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "alloc-util.h"
-#include "build.h"
-#include "cgroup-util.h"
-#include "def.h"
-#include "dirent-util.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "formats-util.h"
-#include "hashmap.h"
-#include "hostname-util.h"
-#include "log.h"
-#include "macro.h"
-#include "missing.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "process-util.h"
-#include "set.h"
-#include "signal-util.h"
-#include "stat-util.h"
-#include "string-util.h"
-#include "strv.h"
-#include "time-util.h"
-#include "umask-util.h"
-#include "user-util.h"
-#include "util.h"
-
-/* Put this test here for a lack of better place */
-assert_cc(EAGAIN == EWOULDBLOCK);
-
-int saved_argc = 0;
-char **saved_argv = NULL;
-static int saved_in_initrd = -1;
-
-size_t page_size(void) {
- static thread_local 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;
-}
-
-static int do_execute(char **directories, usec_t timeout, char *argv[]) {
- _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
- _cleanup_set_free_free_ Set *seen = NULL;
- char **directory;
-
- /* We fork this all off from a child process so that we can
- * somewhat cleanly make use of SIGALRM to set a time limit */
-
- (void) reset_all_signal_handlers();
- (void) reset_signal_mask();
-
- assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
-
- pids = hashmap_new(NULL);
- if (!pids)
- return log_oom();
-
- seen = set_new(&string_hash_ops);
- if (!seen)
- return log_oom();
-
- STRV_FOREACH(directory, directories) {
- _cleanup_closedir_ DIR *d;
- struct dirent *de;
-
- d = opendir(*directory);
- if (!d) {
- if (errno == ENOENT)
- continue;
-
- return log_error_errno(errno, "Failed to open directory %s: %m", *directory);
- }
-
- FOREACH_DIRENT(de, d, break) {
- _cleanup_free_ char *path = NULL;
- pid_t pid;
- int r;
-
- if (!dirent_is_file(de))
- continue;
-
- if (set_contains(seen, de->d_name)) {
- log_debug("%1$s/%2$s skipped (%2$s was already seen).", *directory, de->d_name);
- continue;
- }
-
- r = set_put_strdup(seen, de->d_name);
- if (r < 0)
- return log_oom();
-
- path = strjoin(*directory, "/", de->d_name, NULL);
- if (!path)
- return log_oom();
-
- if (null_or_empty_path(path)) {
- log_debug("%s is empty (a mask).", path);
- continue;
- }
-
- pid = fork();
- if (pid < 0) {
- log_error_errno(errno, "Failed to fork: %m");
- continue;
- } else if (pid == 0) {
- char *_argv[2];
-
- assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
-
- if (!argv) {
- _argv[0] = path;
- _argv[1] = NULL;
- argv = _argv;
- } else
- argv[0] = path;
-
- execv(path, argv);
- return log_error_errno(errno, "Failed to execute %s: %m", path);
- }
-
- log_debug("Spawned %s as " PID_FMT ".", path, pid);
-
- r = hashmap_put(pids, PID_TO_PTR(pid), path);
- if (r < 0)
- return log_oom();
- path = NULL;
- }
- }
-
- /* Abort execution of this process after the timout. We simply
- * rely on SIGALRM as default action terminating the process,
- * and turn on alarm(). */
-
- if (timeout != USEC_INFINITY)
- alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
-
- while (!hashmap_isempty(pids)) {
- _cleanup_free_ char *path = NULL;
- pid_t pid;
-
- pid = PTR_TO_PID(hashmap_first_key(pids));
- assert(pid > 0);
-
- path = hashmap_remove(pids, PID_TO_PTR(pid));
- assert(path);
-
- wait_for_terminate_and_warn(path, pid, true);
- }
-
- return 0;
-}
-
-void execute_directories(const char* const* directories, usec_t timeout, char *argv[]) {
- pid_t executor_pid;
- int r;
- char *name;
- char **dirs = (char**) directories;
-
- assert(!strv_isempty(dirs));
-
- name = basename(dirs[0]);
- assert(!isempty(name));
-
- /* Executes all binaries in the directories in parallel and waits
- * for them to finish. Optionally a timeout is applied. If a file
- * with the same name exists in more than one directory, the
- * earliest one wins. */
-
- executor_pid = fork();
- if (executor_pid < 0) {
- log_error_errno(errno, "Failed to fork: %m");
- return;
-
- } else if (executor_pid == 0) {
- r = do_execute(dirs, timeout, argv);
- _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
- }
-
- wait_for_terminate_and_warn(name, executor_pid, true);
-}
-
-bool plymouth_running(void) {
- return access("/run/plymouth/pid", F_OK) >= 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, strlen("/tmp/.X11-unix/X") + k + 1);
- if (!f)
- return -ENOMEM;
-
- c = stpcpy(f, "/tmp/.X11-unix/X");
- memcpy(c, display+1, k);
- c[k] = 0;
-
- *path = f;
-
- return 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;
-}
-
-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 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;
- }
-}
-
-int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
- bool stdout_is_tty, stderr_is_tty;
- pid_t parent_pid, agent_pid;
- sigset_t ss, saved_ss;
- unsigned n, i;
- va_list ap;
- char **l;
-
- assert(pid);
- assert(path);
-
- /* Spawns a temporary TTY agent, making sure it goes away when
- * we go away */
-
- parent_pid = getpid();
-
- /* First we temporarily block all signals, so that the new
- * child has them blocked initially. This way, we can be sure
- * that SIGTERMs are not lost we might send to the agent. */
- assert_se(sigfillset(&ss) >= 0);
- assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0);
-
- agent_pid = fork();
- if (agent_pid < 0) {
- assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
- return -errno;
- }
-
- if (agent_pid != 0) {
- assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 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);
-
- /* Make sure we actually can kill the agent, if we need to, in
- * case somebody invoked us from a shell script that trapped
- * SIGTERM or so... */
- (void) reset_all_signal_handlers();
- (void) reset_signal_mask();
-
- /* Check whether our parent died before we were able
- * to set the death signal and unblock the signals */
- 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) {
- int fd;
-
- /* 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_errno(errno, "Failed to open /dev/tty: %m");
- _exit(EXIT_FAILURE);
- }
-
- if (!stdout_is_tty && dup2(fd, STDOUT_FILENO) < 0) {
- log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
- _exit(EXIT_FAILURE);
- }
-
- if (!stderr_is_tty && dup2(fd, STDERR_FILENO) < 0) {
- log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
- _exit(EXIT_FAILURE);
- }
-
- if (fd > STDERR_FILENO)
- 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);
-}
-
-bool in_initrd(void) {
- struct statfs s;
-
- if (saved_in_initrd >= 0)
- return saved_in_initrd;
-
- /* 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 consequences due the initrd
- * emptying when transititioning to the main systemd.
- */
-
- saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
- statfs("/", &s) >= 0 &&
- is_temporary_fs(&s);
-
- return saved_in_initrd;
-}
-
-void in_initrd_force(bool value) {
- saved_in_initrd = value;
-}
-
-/* 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;
-}
-
-int on_ac_power(void) {
- bool found_offline = false, found_online = false;
- _cleanup_closedir_ DIR *d = NULL;
-
- d = opendir("/sys/class/power_supply");
- if (!d)
- return errno == ENOENT ? true : -errno;
-
- for (;;) {
- struct dirent *de;
- _cleanup_close_ int fd = -1, device = -1;
- char contents[6];
- ssize_t n;
-
- errno = 0;
- de = readdir(d);
- if (!de && errno > 0)
- return -errno;
-
- if (!de)
- break;
-
- if (hidden_or_backup_file(de->d_name))
- continue;
-
- device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (device < 0) {
- if (errno == ENOENT || errno == ENOTDIR)
- continue;
-
- return -errno;
- }
-
- fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0) {
- if (errno == ENOENT)
- continue;
-
- return -errno;
- }
-
- n = read(fd, contents, sizeof(contents));
- if (n < 0)
- return -errno;
-
- if (n != 6 || memcmp(contents, "Mains\n", 6))
- continue;
-
- safe_close(fd);
- fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0) {
- if (errno == ENOENT)
- continue;
-
- return -errno;
- }
-
- n = read(fd, contents, sizeof(contents));
- if (n < 0)
- return -errno;
-
- if (n != 2 || contents[1] != '\n')
- return -EIO;
-
- if (contents[0] == '1') {
- found_online = true;
- break;
- } else if (contents[0] == '0')
- found_offline = true;
- else
- return -EIO;
- }
-
- return found_online || !found_offline;
-}
-
-int container_get_leader(const char *machine, pid_t *pid) {
- _cleanup_free_ char *s = NULL, *class = NULL;
- const char *p;
- pid_t leader;
- int r;
-
- assert(machine);
- assert(pid);
-
- if (!machine_name_is_valid(machine))
- return -EINVAL;
-
- p = strjoina("/run/systemd/machines/", machine);
- r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
- if (r == -ENOENT)
- return -EHOSTDOWN;
- if (r < 0)
- return r;
- if (!s)
- return -EIO;
-
- if (!streq_ptr(class, "container"))
- return -EIO;
-
- r = parse_pid(s, &leader);
- if (r < 0)
- return r;
- if (leader <= 1)
- return -EIO;
-
- *pid = leader;
- return 0;
-}
-
-int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd) {
- _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1, usernsfd = -1;
- int rfd = -1;
-
- assert(pid >= 0);
-
- if (mntns_fd) {
- const char *mntns;
-
- mntns = procfs_file_alloca(pid, "ns/mnt");
- mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
- if (mntnsfd < 0)
- return -errno;
- }
-
- if (pidns_fd) {
- const char *pidns;
-
- pidns = procfs_file_alloca(pid, "ns/pid");
- pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
- if (pidnsfd < 0)
- return -errno;
- }
-
- if (netns_fd) {
- const char *netns;
-
- netns = procfs_file_alloca(pid, "ns/net");
- netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
- if (netnsfd < 0)
- return -errno;
- }
-
- if (userns_fd) {
- const char *userns;
-
- userns = procfs_file_alloca(pid, "ns/user");
- usernsfd = open(userns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
- if (usernsfd < 0 && errno != ENOENT)
- return -errno;
- }
-
- if (root_fd) {
- const char *root;
-
- root = procfs_file_alloca(pid, "root");
- rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
- if (rfd < 0)
- return -errno;
- }
-
- if (pidns_fd)
- *pidns_fd = pidnsfd;
-
- if (mntns_fd)
- *mntns_fd = mntnsfd;
-
- if (netns_fd)
- *netns_fd = netnsfd;
-
- if (userns_fd)
- *userns_fd = usernsfd;
-
- if (root_fd)
- *root_fd = rfd;
-
- pidnsfd = mntnsfd = netnsfd = usernsfd = -1;
-
- return 0;
-}
-
-int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
- if (userns_fd >= 0) {
- /* Can't setns to your own userns, since then you could
- * escalate from non-root to root in your own namespace, so
- * check if namespaces equal before attempting to enter. */
- _cleanup_free_ char *userns_fd_path = NULL;
- int r;
- if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0)
- return -ENOMEM;
-
- r = files_same(userns_fd_path, "/proc/self/ns/user");
- if (r < 0)
- return r;
- if (r)
- userns_fd = -1;
- }
-
- if (pidns_fd >= 0)
- if (setns(pidns_fd, CLONE_NEWPID) < 0)
- return -errno;
-
- if (mntns_fd >= 0)
- if (setns(mntns_fd, CLONE_NEWNS) < 0)
- return -errno;
-
- if (netns_fd >= 0)
- if (setns(netns_fd, CLONE_NEWNET) < 0)
- return -errno;
-
- if (userns_fd >= 0)
- if (setns(userns_fd, CLONE_NEWUSER) < 0)
- return -errno;
-
- if (root_fd >= 0) {
- if (fchdir(root_fd) < 0)
- return -errno;
-
- if (chroot(".") < 0)
- return -errno;
- }
-
- return reset_uid_gid();
-}
-
-uint64_t physical_memory(void) {
- _cleanup_free_ char *root = NULL, *value = NULL;
- uint64_t mem, lim;
- size_t ps;
- long sc;
-
- /* We return this as uint64_t in case we are running as 32bit process on a 64bit kernel with huge amounts of
- * memory.
- *
- * In order to support containers nicely that have a configured memory limit we'll take the minimum of the
- * physically reported amount of memory and the limit configured for the root cgroup, if there is any. */
-
- sc = sysconf(_SC_PHYS_PAGES);
- assert(sc > 0);
-
- ps = page_size();
- mem = (uint64_t) sc * (uint64_t) ps;
-
- if (cg_get_root_path(&root) < 0)
- return mem;
-
- if (cg_get_attribute("memory", root, "memory.limit_in_bytes", &value))
- return mem;
-
- if (safe_atou64(value, &lim) < 0)
- return mem;
-
- /* Make sure the limit is a multiple of our own page size */
- lim /= ps;
- lim *= ps;
-
- return MIN(mem, lim);
-}
-
-uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
- uint64_t p, m, ps, r;
-
- assert(max > 0);
-
- /* Returns the physical memory size, multiplied by v divided by max. Returns UINT64_MAX on overflow. On success
- * the result is a multiple of the page size (rounds down). */
-
- ps = page_size();
- assert(ps > 0);
-
- p = physical_memory() / ps;
- assert(p > 0);
-
- m = p * v;
- if (m / p != v)
- return UINT64_MAX;
-
- m /= max;
-
- r = m * ps;
- if (r / ps != m)
- return UINT64_MAX;
-
- return r;
-}
-
-uint64_t system_tasks_max(void) {
-
-#if SIZEOF_PID_T == 4
-#define TASKS_MAX ((uint64_t) (INT32_MAX-1))
-#elif SIZEOF_PID_T == 2
-#define TASKS_MAX ((uint64_t) (INT16_MAX-1))
-#else
-#error "Unknown pid_t size"
-#endif
-
- _cleanup_free_ char *value = NULL, *root = NULL;
- uint64_t a = TASKS_MAX, b = TASKS_MAX;
-
- /* Determine the maximum number of tasks that may run on this system. We check three sources to determine this
- * limit:
- *
- * a) the maximum value for the pid_t type
- * b) the cgroups pids_max attribute for the system
- * c) the kernel's configure maximum PID value
- *
- * And then pick the smallest of the three */
-
- if (read_one_line_file("/proc/sys/kernel/pid_max", &value) >= 0)
- (void) safe_atou64(value, &a);
-
- if (cg_get_root_path(&root) >= 0) {
- value = mfree(value);
-
- if (cg_get_attribute("pids", root, "pids.max", &value) >= 0)
- (void) safe_atou64(value, &b);
- }
-
- return MIN3(TASKS_MAX,
- a <= 0 ? TASKS_MAX : a,
- b <= 0 ? TASKS_MAX : b);
-}
-
-uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) {
- uint64_t t, m;
-
- assert(max > 0);
-
- /* Multiply the system's task value by the fraction v/max. Hence, if max==100 this calculates percentages
- * relative to the system's maximum number of tasks. Returns UINT64_MAX on overflow. */
-
- t = system_tasks_max();
- assert(t > 0);
-
- m = t * v;
- if (m / t != v) /* overflow? */
- return UINT64_MAX;
-
- return m / max;
-}
-
-int update_reboot_parameter_and_warn(const char *param) {
- int r;
-
- if (isempty(param)) {
- if (unlink("/run/systemd/reboot-param") < 0) {
- if (errno == ENOENT)
- return 0;
-
- return log_warning_errno(errno, "Failed to unlink reboot parameter file: %m");
- }
-
- return 0;
- }
-
- RUN_WITH_UMASK(0022) {
- r = write_string_file("/run/systemd/reboot-param", param, WRITE_STRING_FILE_CREATE);
- if (r < 0)
- return log_warning_errno(r, "Failed to write reboot parameter file: %m");
- }
-
- return 0;
-}
-
-int version(void) {
- puts(PACKAGE_STRING "\n"
- SYSTEMD_FEATURES);
- return 0;
-}
diff --git a/src/basic/util.h b/src/basic/util.h
deleted file mode 100644
index bb2fc318ef..0000000000
--- a/src/basic/util.h
+++ /dev/null
@@ -1,196 +0,0 @@
-#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 <alloca.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <locale.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/inotify.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <sys/sysmacros.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "formats-util.h"
-#include "macro.h"
-#include "missing.h"
-#include "time-util.h"
-
-size_t page_size(void) _pure_;
-#define PAGE_ALIGN(l) ALIGN_TO((l), page_size())
-
-static inline const char* yes_no(bool b) {
- return b ? "yes" : "no";
-}
-
-static inline const char* true_false(bool b) {
- return b ? "true" : "false";
-}
-
-static inline const char* one_zero(bool b) {
- return b ? "1" : "0";
-}
-
-static inline const char* enable_disable(bool b) {
- return b ? "enable" : "disable";
-}
-
-void execute_directories(const char* const* directories, usec_t timeout, char *argv[]);
-
-bool plymouth_running(void);
-
-bool display_is_local(const char *display) _pure_;
-int socket_from_display(const char *display, char **path);
-
-int block_get_whole_disk(dev_t d, dev_t *ret);
-
-#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))
-
-extern int saved_argc;
-extern char **saved_argv;
-
-bool kexec_loaded(void);
-
-int prot_from_flags(int flags) _const_;
-
-int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...);
-
-bool in_initrd(void);
-void in_initrd_force(bool value);
-
-void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
- int (*compar) (const void *, const void *, void *),
- void *arg);
-
-/**
- * Normal qsort requires base to be nonnull. Here were require
- * that only if nmemb > 0.
- */
-static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_fn_t compar) {
- if (nmemb <= 1)
- return;
-
- assert(base);
- qsort(base, nmemb, size, compar);
-}
-
-/**
- * Normal memcpy requires src to be nonnull. We do nothing if n is 0.
- */
-static inline void memcpy_safe(void *dst, const void *src, size_t n) {
- if (n == 0)
- return;
- assert(src);
- memcpy(dst, src, n);
-}
-
-int on_ac_power(void);
-
-#define memzero(x,l) (memset((x), 0, (l)))
-#define zero(x) (memzero(&(x), sizeof(x)))
-
-static inline void *mempset(void *s, int c, size_t n) {
- memset(s, c, n);
- return (uint8_t*)s + n;
-}
-
-static inline void _reset_errno_(int *saved_errno) {
- errno = *saved_errno;
-}
-
-#define PROTECT_ERRNO _cleanup_(_reset_errno_) __attribute__((unused)) int _saved_errno_ = errno
-
-static inline int negative_errno(void) {
- /* This helper should be used to shut up gcc if you know 'errno' is
- * negative. Instead of "return -errno;", use "return negative_errno();"
- * It will suppress bogus gcc warnings in case it assumes 'errno' might
- * be 0 and thus the caller's error-handling might not be triggered. */
- assert_return(errno > 0, -EINVAL);
- return -errno;
-}
-
-static inline unsigned u64log2(uint64_t n) {
-#if __SIZEOF_LONG_LONG__ == 8
- return (n > 1) ? (unsigned) __builtin_clzll(n) ^ 63U : 0;
-#else
-#error "Wut?"
-#endif
-}
-
-static inline unsigned u32ctz(uint32_t n) {
-#if __SIZEOF_INT__ == 4
- return __builtin_ctz(n);
-#else
-#error "Wut?"
-#endif
-}
-
-static inline unsigned log2i(int x) {
- assert(x > 0);
-
- return __SIZEOF_INT__ * 8 - __builtin_clz(x) - 1;
-}
-
-static inline unsigned log2u(unsigned x) {
- assert(x > 0);
-
- return sizeof(unsigned) * 8 - __builtin_clz(x) - 1;
-}
-
-static inline unsigned log2u_round_up(unsigned x) {
- assert(x > 0);
-
- if (x == 1)
- return 0;
-
- return log2u(x - 1) + 1;
-}
-
-int container_get_leader(const char *machine, pid_t *pid);
-
-int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd);
-int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
-
-uint64_t physical_memory(void);
-uint64_t physical_memory_scale(uint64_t v, uint64_t max);
-
-uint64_t system_tasks_max(void);
-uint64_t system_tasks_max_scale(uint64_t v, uint64_t max);
-
-int update_reboot_parameter_and_warn(const char *param);
-
-int version(void);
diff --git a/src/basic/verbs.c b/src/basic/verbs.c
deleted file mode 100644
index d9cdb38d65..0000000000
--- a/src/basic/verbs.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 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 <getopt.h>
-#include <stdbool.h>
-#include <stddef.h>
-
-#include "log.h"
-#include "macro.h"
-#include "string-util.h"
-#include "verbs.h"
-#include "virt.h"
-
-int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) {
- const Verb *verb;
- const char *name;
- unsigned i;
- int left;
-
- assert(verbs);
- assert(verbs[0].dispatch);
- assert(argc >= 0);
- assert(argv);
- assert(argc >= optind);
-
- left = argc - optind;
- name = argv[optind];
-
- for (i = 0;; i++) {
- bool found;
-
- /* At the end of the list? */
- if (!verbs[i].dispatch) {
- if (name)
- log_error("Unknown operation %s.", name);
- else
- log_error("Requires operation parameter.");
- return -EINVAL;
- }
-
- if (name)
- found = streq(name, verbs[i].verb);
- else
- found = !!(verbs[i].flags & VERB_DEFAULT);
-
- if (found) {
- verb = &verbs[i];
- break;
- }
- }
-
- assert(verb);
-
- if (!name)
- left = 1;
-
- if (verb->min_args != VERB_ANY &&
- (unsigned) left < verb->min_args) {
- log_error("Too few arguments.");
- return -EINVAL;
- }
-
- if (verb->max_args != VERB_ANY &&
- (unsigned) left > verb->max_args) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- if ((verb->flags & VERB_NOCHROOT) && running_in_chroot() > 0) {
- log_info("Running in chroot, ignoring request.");
- return 0;
- }
-
- if (name)
- return verb->dispatch(left, argv + optind, userdata);
- else {
- char* fake[2] = {
- (char*) verb->verb,
- NULL
- };
-
- return verb->dispatch(1, fake, userdata);
- }
-}
diff --git a/src/basic/verbs.h b/src/basic/verbs.h
deleted file mode 100644
index 7b5e18510f..0000000000
--- a/src/basic/verbs.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 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/>.
-***/
-
-#define VERB_ANY ((unsigned) -1)
-#define VERB_DEFAULT 1U
-#define VERB_NOCHROOT 2U
-
-typedef struct {
- const char *verb;
- unsigned min_args, max_args;
- unsigned flags;
- int (* const dispatch)(int argc, char *argv[], void *userdata);
-} Verb;
-
-int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata);
diff --git a/src/basic/virt.c b/src/basic/virt.c
deleted file mode 100644
index d8d57381ad..0000000000
--- a/src/basic/virt.c
+++ /dev/null
@@ -1,595 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2011 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 <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "alloc-util.h"
-#include "dirent-util.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "macro.h"
-#include "process-util.h"
-#include "stat-util.h"
-#include "string-table.h"
-#include "string-util.h"
-#include "virt.h"
-#include "env-util.h"
-
-static int detect_vm_cpuid(void) {
-
- /* CPUID is an x86 specific interface. */
-#if defined(__i386__) || defined(__x86_64__)
-
- static const struct {
- const char *cpuid;
- int id;
- } cpuid_vendor_table[] = {
- { "XenVMMXenVMM", VIRTUALIZATION_XEN },
- { "KVMKVMKVM", VIRTUALIZATION_KVM },
- /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
- { "VMwareVMware", VIRTUALIZATION_VMWARE },
- /* http://msdn.microsoft.com/en-us/library/ff542428.aspx */
- { "Microsoft Hv", VIRTUALIZATION_MICROSOFT },
- /* https://wiki.freebsd.org/bhyve */
- { "bhyve bhyve ", VIRTUALIZATION_BHYVE },
- };
-
- uint32_t eax, ecx;
- bool hypervisor;
-
- /* http://lwn.net/Articles/301888/ */
-
-#if defined (__i386__)
-#define REG_a "eax"
-#define REG_b "ebx"
-#elif defined (__amd64__)
-#define REG_a "rax"
-#define REG_b "rbx"
-#endif
-
- /* First detect whether there is a hypervisor */
- eax = 1;
- __asm__ __volatile__ (
- /* ebx/rbx is being used for PIC! */
- " push %%"REG_b" \n\t"
- " cpuid \n\t"
- " pop %%"REG_b" \n\t"
-
- : "=a" (eax), "=c" (ecx)
- : "0" (eax)
- );
-
- hypervisor = !!(ecx & 0x80000000U);
-
- if (hypervisor) {
- union {
- uint32_t sig32[3];
- char text[13];
- } sig = {};
- unsigned j;
-
- /* There is a hypervisor, see what it is */
- eax = 0x40000000U;
- __asm__ __volatile__ (
- /* ebx/rbx is being used for PIC! */
- " push %%"REG_b" \n\t"
- " cpuid \n\t"
- " mov %%ebx, %1 \n\t"
- " pop %%"REG_b" \n\t"
-
- : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
- : "0" (eax)
- );
-
- log_debug("Virtualization found, CPUID=%s", sig.text);
-
- for (j = 0; j < ELEMENTSOF(cpuid_vendor_table); j ++)
- if (streq(sig.text, cpuid_vendor_table[j].cpuid))
- return cpuid_vendor_table[j].id;
-
- return VIRTUALIZATION_VM_OTHER;
- }
-#endif
- log_debug("No virtualization found in CPUID");
-
- return VIRTUALIZATION_NONE;
-}
-
-static int detect_vm_device_tree(void) {
-#if defined(__arm__) || defined(__aarch64__) || defined(__powerpc__) || defined(__powerpc64__)
- _cleanup_free_ char *hvtype = NULL;
- int r;
-
- r = read_one_line_file("/proc/device-tree/hypervisor/compatible", &hvtype);
- if (r == -ENOENT) {
- _cleanup_closedir_ DIR *dir = NULL;
- struct dirent *dent;
-
- dir = opendir("/proc/device-tree");
- if (!dir) {
- if (errno == ENOENT) {
- log_debug_errno(errno, "/proc/device-tree: %m");
- return VIRTUALIZATION_NONE;
- }
- return -errno;
- }
-
- FOREACH_DIRENT(dent, dir, return -errno)
- if (strstr(dent->d_name, "fw-cfg")) {
- log_debug("Virtualization QEMU: \"fw-cfg\" present in /proc/device-tree/%s", dent->d_name);
- return VIRTUALIZATION_QEMU;
- }
-
- log_debug("No virtualization found in /proc/device-tree/*");
- return VIRTUALIZATION_NONE;
- } else if (r < 0)
- return r;
-
- log_debug("Virtualization %s found in /proc/device-tree/hypervisor/compatible", hvtype);
- if (streq(hvtype, "linux,kvm"))
- return VIRTUALIZATION_KVM;
- else if (strstr(hvtype, "xen"))
- return VIRTUALIZATION_XEN;
- else
- return VIRTUALIZATION_VM_OTHER;
-#else
- log_debug("This platform does not support /proc/device-tree");
- return VIRTUALIZATION_NONE;
-#endif
-}
-
-static int detect_vm_dmi(void) {
-#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
-
- static const char *const dmi_vendors[] = {
- "/sys/class/dmi/id/product_name", /* Test this before sys_vendor to detect KVM over QEMU */
- "/sys/class/dmi/id/sys_vendor",
- "/sys/class/dmi/id/board_vendor",
- "/sys/class/dmi/id/bios_vendor"
- };
-
- static const struct {
- const char *vendor;
- int id;
- } dmi_vendor_table[] = {
- { "KVM", VIRTUALIZATION_KVM },
- { "QEMU", VIRTUALIZATION_QEMU },
- /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
- { "VMware", VIRTUALIZATION_VMWARE },
- { "VMW", VIRTUALIZATION_VMWARE },
- { "innotek GmbH", VIRTUALIZATION_ORACLE },
- { "Xen", VIRTUALIZATION_XEN },
- { "Bochs", VIRTUALIZATION_BOCHS },
- { "Parallels", VIRTUALIZATION_PARALLELS },
- /* https://wiki.freebsd.org/bhyve */
- { "BHYVE", VIRTUALIZATION_BHYVE },
- };
- unsigned i;
- int r;
-
- for (i = 0; i < ELEMENTSOF(dmi_vendors); i++) {
- _cleanup_free_ char *s = NULL;
- unsigned j;
-
- r = read_one_line_file(dmi_vendors[i], &s);
- if (r < 0) {
- if (r == -ENOENT)
- continue;
-
- return r;
- }
-
-
-
- for (j = 0; j < ELEMENTSOF(dmi_vendor_table); j++)
- if (startswith(s, dmi_vendor_table[j].vendor)) {
- log_debug("Virtualization %s found in DMI (%s)", s, dmi_vendors[i]);
- return dmi_vendor_table[j].id;
- }
- }
-#endif
-
- log_debug("No virtualization found in DMI");
-
- return VIRTUALIZATION_NONE;
-}
-
-static int detect_vm_xen(void) {
- /* Check for Dom0 will be executed later in detect_vm_xen_dom0
- Thats why we dont check the content of /proc/xen/capabilities here. */
- if (access("/proc/xen/capabilities", F_OK) < 0) {
- log_debug("Virtualization XEN not found, /proc/xen/capabilities does not exist");
- return VIRTUALIZATION_NONE;
- }
-
- log_debug("Virtualization XEN found (/proc/xen/capabilities exists)");
- return VIRTUALIZATION_XEN;
-
-}
-
-static bool detect_vm_xen_dom0(void) {
- _cleanup_free_ char *domcap = NULL;
- char *cap, *i;
- int r;
-
- r = read_one_line_file("/proc/xen/capabilities", &domcap);
- if (r == -ENOENT) {
- log_debug("Virtualization XEN not found, /proc/xen/capabilities does not exist");
- return false;
- }
- if (r < 0)
- return r;
-
- i = domcap;
- while ((cap = strsep(&i, ",")))
- if (streq(cap, "control_d"))
- break;
- if (!cap) {
- log_debug("Virtualization XEN DomU found (/proc/xen/capabilites)");
- return false;
- }
-
- log_debug("Virtualization XEN Dom0 ignored (/proc/xen/capabilities)");
- return true;
-}
-
-static int detect_vm_hypervisor(void) {
- _cleanup_free_ char *hvtype = NULL;
- int r;
-
- r = read_one_line_file("/sys/hypervisor/type", &hvtype);
- if (r == -ENOENT)
- return VIRTUALIZATION_NONE;
- if (r < 0)
- return r;
-
- log_debug("Virtualization %s found in /sys/hypervisor/type", hvtype);
-
- if (streq(hvtype, "xen"))
- return VIRTUALIZATION_XEN;
- else
- return VIRTUALIZATION_VM_OTHER;
-}
-
-static int detect_vm_uml(void) {
- _cleanup_free_ char *cpuinfo_contents = NULL;
- int r;
-
- /* Detect User-Mode Linux by reading /proc/cpuinfo */
- r = read_full_file("/proc/cpuinfo", &cpuinfo_contents, NULL);
- if (r < 0)
- return r;
-
- if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n")) {
- log_debug("UML virtualization found in /proc/cpuinfo");
- return VIRTUALIZATION_UML;
- }
-
- log_debug("No virtualization found in /proc/cpuinfo.");
- return VIRTUALIZATION_NONE;
-}
-
-static int detect_vm_zvm(void) {
-
-#if defined(__s390__)
- _cleanup_free_ char *t = NULL;
- int r;
-
- r = get_proc_field("/proc/sysinfo", "VM00 Control Program", WHITESPACE, &t);
- if (r == -ENOENT)
- return VIRTUALIZATION_NONE;
- if (r < 0)
- return r;
-
- log_debug("Virtualization %s found in /proc/sysinfo", t);
- if (streq(t, "z/VM"))
- return VIRTUALIZATION_ZVM;
- else
- return VIRTUALIZATION_KVM;
-#else
- log_debug("This platform does not support /proc/sysinfo");
- return VIRTUALIZATION_NONE;
-#endif
-}
-
-/* Returns a short identifier for the various VM implementations */
-int detect_vm(void) {
- static thread_local int cached_found = _VIRTUALIZATION_INVALID;
- int r;
-
- if (cached_found >= 0)
- return cached_found;
-
- /* We have to use the correct order here:
- * Some virtualization technologies do use KVM hypervisor but are
- * expected to be detected as something else. So detect DMI first.
- *
- * An example is Virtualbox since version 5.0, which uses KVM backend.
- * Detection via DMI works corretly, the CPU ID would find KVM
- * only. */
- r = detect_vm_dmi();
- if (r < 0)
- return r;
- if (r != VIRTUALIZATION_NONE)
- goto finish;
-
- r = detect_vm_cpuid();
- if (r < 0)
- return r;
- if (r != VIRTUALIZATION_NONE)
- goto finish;
-
- /* x86 xen will most likely be detected by cpuid. If not (most likely
- * because we're not an x86 guest), then we should try the xen capabilities
- * file next. If that's not found, then we check for the high-level
- * hypervisor sysfs file:
- *
- * https://bugs.freedesktop.org/show_bug.cgi?id=77271 */
-
- r = detect_vm_xen();
- if (r < 0)
- return r;
- if (r != VIRTUALIZATION_NONE)
- goto finish;
-
- r = detect_vm_hypervisor();
- if (r < 0)
- return r;
- if (r != VIRTUALIZATION_NONE)
- goto finish;
-
- r = detect_vm_device_tree();
- if (r < 0)
- return r;
- if (r != VIRTUALIZATION_NONE)
- goto finish;
-
- r = detect_vm_uml();
- if (r < 0)
- return r;
- if (r != VIRTUALIZATION_NONE)
- goto finish;
-
- r = detect_vm_zvm();
- if (r < 0)
- return r;
-
-finish:
- /* x86 xen Dom0 is detected as XEN in hypervisor and maybe others.
- * In order to detect the Dom0 as not virtualization we need to
- * double-check it */
- if (r == VIRTUALIZATION_XEN && detect_vm_xen_dom0())
- r = VIRTUALIZATION_NONE;
-
- cached_found = r;
- log_debug("Found VM virtualization %s", virtualization_to_string(r));
- return r;
-}
-
-int detect_container(void) {
-
- static const struct {
- const char *value;
- int id;
- } value_table[] = {
- { "lxc", VIRTUALIZATION_LXC },
- { "lxc-libvirt", VIRTUALIZATION_LXC_LIBVIRT },
- { "systemd-nspawn", VIRTUALIZATION_SYSTEMD_NSPAWN },
- { "docker", VIRTUALIZATION_DOCKER },
- { "rkt", VIRTUALIZATION_RKT },
- };
-
- static thread_local int cached_found = _VIRTUALIZATION_INVALID;
- _cleanup_free_ char *m = NULL;
- const char *e = NULL;
- unsigned j;
- int r;
-
- if (cached_found >= 0)
- return cached_found;
-
- /* /proc/vz exists in container and outside of the container,
- * /proc/bc only outside of the container. */
- if (access("/proc/vz", F_OK) >= 0 &&
- access("/proc/bc", F_OK) < 0) {
- r = VIRTUALIZATION_OPENVZ;
- goto finish;
- }
-
- if (getpid() == 1) {
- /* If we are PID 1 we can just check our own
- * environment variable */
-
- e = getenv("container");
- if (isempty(e)) {
- r = VIRTUALIZATION_NONE;
- goto finish;
- }
- } else {
-
- /* Otherwise, PID 1 dropped this information into a
- * file in /run. This is better than accessing
- * /proc/1/environ, since we don't need CAP_SYS_PTRACE
- * for that. */
-
- r = read_one_line_file("/run/systemd/container", &m);
- if (r == -ENOENT) {
-
- /* Fallback for cases where PID 1 was not
- * systemd (for example, cases where
- * init=/bin/sh is used. */
-
- r = getenv_for_pid(1, "container", &m);
- if (r <= 0) {
-
- /* If that didn't work, give up,
- * assume no container manager.
- *
- * Note: This means we still cannot
- * detect containers if init=/bin/sh
- * is passed but privileges dropped,
- * as /proc/1/environ is only readable
- * with privileges. */
-
- r = VIRTUALIZATION_NONE;
- goto finish;
- }
- }
- if (r < 0)
- return r;
-
- e = m;
- }
-
- for (j = 0; j < ELEMENTSOF(value_table); j++)
- if (streq(e, value_table[j].value)) {
- r = value_table[j].id;
- goto finish;
- }
-
- r = VIRTUALIZATION_CONTAINER_OTHER;
-
-finish:
- log_debug("Found container virtualization %s", virtualization_to_string(r));
- cached_found = r;
- return r;
-}
-
-int detect_virtualization(void) {
- int r;
-
- r = detect_container();
- if (r == 0)
- r = detect_vm();
-
- return r;
-}
-
-static int userns_has_mapping(const char *name) {
- _cleanup_fclose_ FILE *f = NULL;
- _cleanup_free_ char *buf = NULL;
- size_t n_allocated = 0;
- ssize_t n;
- uint32_t a, b, c;
- int r;
-
- f = fopen(name, "re");
- if (!f) {
- log_debug_errno(errno, "Failed to open %s: %m", name);
- return errno == ENOENT ? false : -errno;
- }
-
- n = getline(&buf, &n_allocated, f);
- if (n < 0) {
- if (feof(f)) {
- log_debug("%s is empty, we're in an uninitialized user namespace", name);
- return true;
- }
-
- return log_debug_errno(errno, "Failed to read %s: %m", name);
- }
-
- r = sscanf(buf, "%"PRIu32" %"PRIu32" %"PRIu32, &a, &b, &c);
- if (r < 3)
- return log_debug_errno(errno, "Failed to parse %s: %m", name);
-
- if (a == 0 && b == 0 && c == UINT32_MAX) {
- /* The kernel calls mappings_overlap() and does not allow overlaps */
- log_debug("%s has a full 1:1 mapping", name);
- return false;
- }
-
- /* Anything else implies that we are in a user namespace */
- log_debug("Mapping found in %s, we're in a user namespace", name);
- return true;
-}
-
-int running_in_userns(void) {
- _cleanup_free_ char *line = NULL;
- int r;
-
- r = userns_has_mapping("/proc/self/uid_map");
- if (r != 0)
- return r;
-
- r = userns_has_mapping("/proc/self/gid_map");
- if (r != 0)
- return r;
-
- /* "setgroups" file was added in kernel v3.18-rc6-15-g9cc46516dd. It is also
- * possible to compile a kernel without CONFIG_USER_NS, in which case "setgroups"
- * also does not exist. We cannot distinguish those two cases, so assume that
- * we're running on a stripped-down recent kernel, rather than on an old one,
- * and if the file is not found, return false.
- */
- r = read_one_line_file("/proc/self/setgroups", &line);
- if (r < 0) {
- log_debug_errno(r, "/proc/self/setgroups: %m");
- return r == -ENOENT ? false : r;
- }
-
- truncate_nl(line);
- r = streq(line, "deny");
- /* See user_namespaces(7) for a description of this "setgroups" contents. */
- log_debug("/proc/self/setgroups contains \"%s\", %s user namespace", line, r ? "in" : "not in");
- return r;
-}
-
-int running_in_chroot(void) {
- int ret;
-
- if (getenv_bool("SYSTEMD_IGNORE_CHROOT") > 0)
- return 0;
-
- ret = files_same("/proc/1/root", "/");
- if (ret < 0)
- return ret;
-
- return ret == 0;
-}
-
-static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
- [VIRTUALIZATION_NONE] = "none",
- [VIRTUALIZATION_KVM] = "kvm",
- [VIRTUALIZATION_QEMU] = "qemu",
- [VIRTUALIZATION_BOCHS] = "bochs",
- [VIRTUALIZATION_XEN] = "xen",
- [VIRTUALIZATION_UML] = "uml",
- [VIRTUALIZATION_VMWARE] = "vmware",
- [VIRTUALIZATION_ORACLE] = "oracle",
- [VIRTUALIZATION_MICROSOFT] = "microsoft",
- [VIRTUALIZATION_ZVM] = "zvm",
- [VIRTUALIZATION_PARALLELS] = "parallels",
- [VIRTUALIZATION_BHYVE] = "bhyve",
- [VIRTUALIZATION_VM_OTHER] = "vm-other",
-
- [VIRTUALIZATION_SYSTEMD_NSPAWN] = "systemd-nspawn",
- [VIRTUALIZATION_LXC_LIBVIRT] = "lxc-libvirt",
- [VIRTUALIZATION_LXC] = "lxc",
- [VIRTUALIZATION_OPENVZ] = "openvz",
- [VIRTUALIZATION_DOCKER] = "docker",
- [VIRTUALIZATION_RKT] = "rkt",
- [VIRTUALIZATION_CONTAINER_OTHER] = "container-other",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(virtualization, int);
diff --git a/src/basic/virt.h b/src/basic/virt.h
deleted file mode 100644
index 7d15169112..0000000000
--- a/src/basic/virt.h
+++ /dev/null
@@ -1,74 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2011 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 "macro.h"
-
-enum {
- VIRTUALIZATION_NONE = 0,
-
- VIRTUALIZATION_VM_FIRST,
- VIRTUALIZATION_KVM = VIRTUALIZATION_VM_FIRST,
- VIRTUALIZATION_QEMU,
- VIRTUALIZATION_BOCHS,
- VIRTUALIZATION_XEN,
- VIRTUALIZATION_UML,
- VIRTUALIZATION_VMWARE,
- VIRTUALIZATION_ORACLE,
- VIRTUALIZATION_MICROSOFT,
- VIRTUALIZATION_ZVM,
- VIRTUALIZATION_PARALLELS,
- VIRTUALIZATION_BHYVE,
- VIRTUALIZATION_VM_OTHER,
- VIRTUALIZATION_VM_LAST = VIRTUALIZATION_VM_OTHER,
-
- VIRTUALIZATION_CONTAINER_FIRST,
- VIRTUALIZATION_SYSTEMD_NSPAWN = VIRTUALIZATION_CONTAINER_FIRST,
- VIRTUALIZATION_LXC_LIBVIRT,
- VIRTUALIZATION_LXC,
- VIRTUALIZATION_OPENVZ,
- VIRTUALIZATION_DOCKER,
- VIRTUALIZATION_RKT,
- VIRTUALIZATION_CONTAINER_OTHER,
- VIRTUALIZATION_CONTAINER_LAST = VIRTUALIZATION_CONTAINER_OTHER,
-
- _VIRTUALIZATION_MAX,
- _VIRTUALIZATION_INVALID = -1
-};
-
-static inline bool VIRTUALIZATION_IS_VM(int x) {
- return x >= VIRTUALIZATION_VM_FIRST && x <= VIRTUALIZATION_VM_LAST;
-}
-
-static inline bool VIRTUALIZATION_IS_CONTAINER(int x) {
- return x >= VIRTUALIZATION_CONTAINER_FIRST && x <= VIRTUALIZATION_CONTAINER_LAST;
-}
-
-int detect_vm(void);
-int detect_container(void);
-int detect_virtualization(void);
-
-int running_in_userns(void);
-int running_in_chroot(void);
-
-const char *virtualization_to_string(int v) _const_;
-int virtualization_from_string(const char *s) _pure_;
diff --git a/src/basic/web-util.c b/src/basic/web-util.c
deleted file mode 100644
index 595688ed93..0000000000
--- a/src/basic/web-util.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/***
- 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 "string-util.h"
-#include "utf8.h"
-#include "web-util.h"
-
-bool http_etag_is_valid(const char *etag) {
- if (isempty(etag))
- return false;
-
- if (!endswith(etag, "\""))
- return false;
-
- if (!startswith(etag, "\"") && !startswith(etag, "W/\""))
- return false;
-
- return true;
-}
-
-bool http_url_is_valid(const char *url) {
- const char *p;
-
- if (isempty(url))
- return false;
-
- p = startswith(url, "http://");
- if (!p)
- p = startswith(url, "https://");
- if (!p)
- return false;
-
- if (isempty(p))
- return false;
-
- return ascii_is_valid(p);
-}
-
-bool documentation_url_is_valid(const char *url) {
- const char *p;
-
- if (isempty(url))
- return false;
-
- if (http_url_is_valid(url))
- return true;
-
- p = startswith(url, "file:/");
- if (!p)
- p = startswith(url, "info:");
- if (!p)
- p = startswith(url, "man:");
-
- if (isempty(p))
- return false;
-
- return ascii_is_valid(p);
-}
diff --git a/src/basic/web-util.h b/src/basic/web-util.h
deleted file mode 100644
index e6bb6b53f5..0000000000
--- a/src/basic/web-util.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#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 "macro.h"
-
-bool http_url_is_valid(const char *url) _pure_;
-
-bool documentation_url_is_valid(const char *url) _pure_;
-
-bool http_etag_is_valid(const char *etag);
diff --git a/src/basic/xattr-util.c b/src/basic/xattr-util.c
deleted file mode 100644
index 8256899eda..0000000000
--- a/src/basic/xattr-util.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/***
- 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 <fcntl.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/xattr.h>
-
-#include "alloc-util.h"
-#include "fd-util.h"
-#include "macro.h"
-#include "sparse-endian.h"
-#include "stdio-util.h"
-#include "time-util.h"
-#include "xattr-util.h"
-
-int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink) {
- char *v;
- size_t l;
- ssize_t n;
-
- assert(path);
- assert(name);
- assert(value);
-
- for (l = 100; ; l = (size_t) n + 1) {
- v = new0(char, l);
- if (!v)
- return -ENOMEM;
-
- if (allow_symlink)
- n = lgetxattr(path, name, v, l);
- else
- n = getxattr(path, name, v, l);
-
- if (n >= 0 && (size_t) n < l) {
- *value = v;
- return n;
- }
-
- free(v);
-
- if (n < 0 && errno != ERANGE)
- return -errno;
-
- if (allow_symlink)
- n = lgetxattr(path, name, NULL, 0);
- else
- n = getxattr(path, name, NULL, 0);
- if (n < 0)
- return -errno;
- }
-}
-
-int fgetxattr_malloc(int fd, const char *name, char **value) {
- char *v;
- size_t l;
- ssize_t n;
-
- assert(fd >= 0);
- assert(name);
- assert(value);
-
- for (l = 100; ; l = (size_t) n + 1) {
- v = new0(char, l);
- if (!v)
- return -ENOMEM;
-
- n = fgetxattr(fd, name, v, l);
-
- if (n >= 0 && (size_t) n < l) {
- *value = v;
- return n;
- }
-
- free(v);
-
- if (n < 0 && errno != ERANGE)
- return -errno;
-
- n = fgetxattr(fd, name, NULL, 0);
- if (n < 0)
- return -errno;
- }
-}
-
-ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags) {
- char fn[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
- _cleanup_close_ int fd = -1;
- ssize_t l;
-
- /* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */
-
- fd = openat(dirfd, filename, O_CLOEXEC|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
- if (fd < 0)
- return -errno;
-
- xsprintf(fn, "/proc/self/fd/%i", fd);
-
- l = getxattr(fn, attribute, value, size);
- if (l < 0)
- return -errno;
-
- return l;
-}
-
-static int parse_crtime(le64_t le, usec_t *usec) {
- uint64_t u;
-
- assert(usec);
-
- u = le64toh(le);
- if (u == 0 || u == (uint64_t) -1)
- return -EIO;
-
- *usec = (usec_t) u;
- return 0;
-}
-
-int fd_getcrtime(int fd, usec_t *usec) {
- le64_t le;
- ssize_t n;
-
- assert(fd >= 0);
- assert(usec);
-
- /* Until Linux gets a real concept of birthtime/creation time,
- * let's fake one with xattrs */
-
- n = fgetxattr(fd, "user.crtime_usec", &le, sizeof(le));
- if (n < 0)
- return -errno;
- if (n != sizeof(le))
- return -EIO;
-
- return parse_crtime(le, usec);
-}
-
-int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags) {
- le64_t le;
- ssize_t n;
-
- n = fgetxattrat_fake(dirfd, name, "user.crtime_usec", &le, sizeof(le), flags);
- if (n < 0)
- return -errno;
- if (n != sizeof(le))
- return -EIO;
-
- return parse_crtime(le, usec);
-}
-
-int path_getcrtime(const char *p, usec_t *usec) {
- le64_t le;
- ssize_t n;
-
- assert(p);
- assert(usec);
-
- n = getxattr(p, "user.crtime_usec", &le, sizeof(le));
- if (n < 0)
- return -errno;
- if (n != sizeof(le))
- return -EIO;
-
- return parse_crtime(le, usec);
-}
-
-int fd_setcrtime(int fd, usec_t usec) {
- le64_t le;
-
- assert(fd >= 0);
-
- if (usec <= 0)
- usec = now(CLOCK_REALTIME);
-
- le = htole64((uint64_t) usec);
- if (fsetxattr(fd, "user.crtime_usec", &le, sizeof(le), 0) < 0)
- return -errno;
-
- return 0;
-}
diff --git a/src/basic/xattr-util.h b/src/basic/xattr-util.h
deleted file mode 100644
index 6fa097bf7e..0000000000
--- a/src/basic/xattr-util.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#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 <stddef.h>
-#include <sys/types.h>
-
-#include "time-util.h"
-
-int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink);
-int fgetxattr_malloc(int fd, const char *name, char **value);
-
-ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags);
-
-int fd_setcrtime(int fd, usec_t usec);
-
-int fd_getcrtime(int fd, usec_t *usec);
-int path_getcrtime(const char *p, usec_t *usec);
-int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags);
diff --git a/src/basic/xml.c b/src/basic/xml.c
deleted file mode 100644
index 1dbeac7324..0000000000
--- a/src/basic/xml.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 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 <stddef.h>
-#include <string.h>
-
-#include "macro.h"
-#include "string-util.h"
-#include "xml.h"
-
-enum {
- STATE_NULL,
- STATE_TEXT,
- STATE_TAG,
- STATE_ATTRIBUTE,
-};
-
-static void inc_lines(unsigned *line, const char *s, size_t n) {
- const char *p = s;
-
- if (!line)
- return;
-
- for (;;) {
- const char *f;
-
- f = memchr(p, '\n', n);
- if (!f)
- return;
-
- n -= (f - p) + 1;
- p = f + 1;
- (*line)++;
- }
-}
-
-/* We don't actually do real XML here. We only read a simplistic
- * subset, that is a bit less strict that XML and lacks all the more
- * complex features, like entities, or namespaces. However, we do
- * support some HTML5-like simplifications */
-
-int xml_tokenize(const char **p, char **name, void **state, unsigned *line) {
- const char *c, *e, *b;
- char *ret;
- int t;
-
- assert(p);
- assert(*p);
- assert(name);
- assert(state);
-
- t = PTR_TO_INT(*state);
- c = *p;
-
- if (t == STATE_NULL) {
- if (line)
- *line = 1;
- t = STATE_TEXT;
- }
-
- for (;;) {
- if (*c == 0)
- return XML_END;
-
- switch (t) {
-
- case STATE_TEXT: {
- int x;
-
- e = strchrnul(c, '<');
- if (e > c) {
- /* More text... */
- ret = strndup(c, e - c);
- if (!ret)
- return -ENOMEM;
-
- inc_lines(line, c, e - c);
-
- *name = ret;
- *p = e;
- *state = INT_TO_PTR(STATE_TEXT);
-
- return XML_TEXT;
- }
-
- assert(*e == '<');
- b = c + 1;
-
- if (startswith(b, "!--")) {
- /* A comment */
- e = strstr(b + 3, "-->");
- if (!e)
- return -EINVAL;
-
- inc_lines(line, b, e + 3 - b);
-
- c = e + 3;
- continue;
- }
-
- if (*b == '?') {
- /* Processing instruction */
-
- e = strstr(b + 1, "?>");
- if (!e)
- return -EINVAL;
-
- inc_lines(line, b, e + 2 - b);
-
- c = e + 2;
- continue;
- }
-
- if (*b == '!') {
- /* DTD */
-
- e = strchr(b + 1, '>');
- if (!e)
- return -EINVAL;
-
- inc_lines(line, b, e + 1 - b);
-
- c = e + 1;
- continue;
- }
-
- if (*b == '/') {
- /* A closing tag */
- x = XML_TAG_CLOSE;
- b++;
- } else
- x = XML_TAG_OPEN;
-
- e = strpbrk(b, WHITESPACE "/>");
- if (!e)
- return -EINVAL;
-
- ret = strndup(b, e - b);
- if (!ret)
- return -ENOMEM;
-
- *name = ret;
- *p = e;
- *state = INT_TO_PTR(STATE_TAG);
-
- return x;
- }
-
- case STATE_TAG:
-
- b = c + strspn(c, WHITESPACE);
- if (*b == 0)
- return -EINVAL;
-
- inc_lines(line, c, b - c);
-
- e = b + strcspn(b, WHITESPACE "=/>");
- if (e > b) {
- /* An attribute */
-
- ret = strndup(b, e - b);
- if (!ret)
- return -ENOMEM;
-
- *name = ret;
- *p = e;
- *state = INT_TO_PTR(STATE_ATTRIBUTE);
-
- return XML_ATTRIBUTE_NAME;
- }
-
- if (startswith(b, "/>")) {
- /* An empty tag */
-
- *name = NULL; /* For empty tags we return a NULL name, the caller must be prepared for that */
- *p = b + 2;
- *state = INT_TO_PTR(STATE_TEXT);
-
- return XML_TAG_CLOSE_EMPTY;
- }
-
- if (*b != '>')
- return -EINVAL;
-
- c = b + 1;
- t = STATE_TEXT;
- continue;
-
- case STATE_ATTRIBUTE:
-
- if (*c == '=') {
- c++;
-
- if (*c == '\'' || *c == '\"') {
- /* Tag with a quoted value */
-
- e = strchr(c+1, *c);
- if (!e)
- return -EINVAL;
-
- inc_lines(line, c, e - c);
-
- ret = strndup(c+1, e - c - 1);
- if (!ret)
- return -ENOMEM;
-
- *name = ret;
- *p = e + 1;
- *state = INT_TO_PTR(STATE_TAG);
-
- return XML_ATTRIBUTE_VALUE;
-
- }
-
- /* Tag with a value without quotes */
-
- b = strpbrk(c, WHITESPACE ">");
- if (!b)
- b = c;
-
- ret = strndup(c, b - c);
- if (!ret)
- return -ENOMEM;
-
- *name = ret;
- *p = b;
- *state = INT_TO_PTR(STATE_TAG);
- return XML_ATTRIBUTE_VALUE;
- }
-
- t = STATE_TAG;
- continue;
- }
-
- }
-
- assert_not_reached("Bad state");
-}
diff --git a/src/basic/xml.h b/src/basic/xml.h
deleted file mode 100644
index 41cb69f0dc..0000000000
--- a/src/basic/xml.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 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/>.
-***/
-
-enum {
- XML_END,
- XML_TEXT,
- XML_TAG_OPEN,
- XML_TAG_CLOSE,
- XML_TAG_CLOSE_EMPTY,
- XML_ATTRIBUTE_NAME,
- XML_ATTRIBUTE_VALUE,
-};
-
-int xml_tokenize(const char **p, char **name, void **state, unsigned *line);