summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSven Eden <yamakuzure@gmx.net>2017-03-29 10:05:50 +0200
committerSven Eden <yamakuzure@gmx.net>2017-03-29 10:48:11 +0200
commit64b485bf89b90042c9a624633b038ef417b0325e (patch)
tree729aa69d958c20522ea9623083f87b8ffbb75a95 /src
parent3cd22db822df747636dcf30ebb8ec5d16bb71880 (diff)
[2/5] Apply missing fixes from upstream
Diffstat (limited to 'src')
-rw-r--r--src/basic/selinux-util.c10
-rw-r--r--src/basic/selinux-util.h3
-rw-r--r--src/basic/siphash24.c181
-rw-r--r--src/basic/siphash24.h4
-rw-r--r--src/basic/smack-util.c3
-rw-r--r--src/basic/smack-util.h3
-rw-r--r--src/basic/strv.c166
-rw-r--r--src/basic/strv.h9
-rw-r--r--src/basic/terminal-util.c31
-rw-r--r--src/basic/terminal-util.h46
-rw-r--r--src/basic/unit-name.c164
-rw-r--r--src/basic/unit-name.h227
-rw-r--r--src/basic/util.c501
-rw-r--r--src/basic/util.h84
-rw-r--r--src/basic/virt.c383
-rw-r--r--src/basic/virt.h46
16 files changed, 1268 insertions, 593 deletions
diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c
index cea80b678..239900b79 100644
--- a/src/basic/selinux-util.c
+++ b/src/basic/selinux-util.c
@@ -303,14 +303,20 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
return r;
}
-void mac_selinux_free(char *label) {
+char* mac_selinux_free(char *label) {
#ifdef HAVE_SELINUX
+ if (!label)
+ return NULL;
+
if (!mac_selinux_use())
- return;
+ return NULL;
+
freecon((security_context_t) label);
#endif
+
+ return NULL;
}
#endif // 0
diff --git a/src/basic/selinux-util.h b/src/basic/selinux-util.h
index 559b0d6df..caac8dfb7 100644
--- a/src/basic/selinux-util.h
+++ b/src/basic/selinux-util.h
@@ -21,10 +21,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
#include <sys/socket.h>
#include <stdbool.h>
+#include "macro.h"
+
bool mac_selinux_use(void);
// UNNEEDED void mac_selinux_retest(void);
diff --git a/src/basic/siphash24.c b/src/basic/siphash24.c
index 308e4230c..fa94f80ae 100644
--- a/src/basic/siphash24.c
+++ b/src/basic/siphash24.c
@@ -13,50 +13,48 @@
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 <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include "siphash24.h"
-
-typedef uint64_t u64;
-typedef uint32_t u32;
-typedef uint8_t u8;
+#include "sparse-endian.h"
-#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
+#include "siphash24.h"
+#include "util.h"
-#define U32TO8_LE(p, v) \
- (p)[0] = (u8)((v) ); (p)[1] = (u8)((v) >> 8); \
- (p)[2] = (u8)((v) >> 16); (p)[3] = (u8)((v) >> 24);
+static inline uint64_t rotate_left(uint64_t x, uint8_t b) {
+ assert(b < 64);
-#define U64TO8_LE(p, v) \
- U32TO8_LE((p), (u32)((v) )); \
- U32TO8_LE((p) + 4, (u32)((v) >> 32));
+ return (x << b) | (x >> (64 - b));
+}
-#define U8TO64_LE(p) \
- (((u64)((p)[0]) ) | \
- ((u64)((p)[1]) << 8) | \
- ((u64)((p)[2]) << 16) | \
- ((u64)((p)[3]) << 24) | \
- ((u64)((p)[4]) << 32) | \
- ((u64)((p)[5]) << 40) | \
- ((u64)((p)[6]) << 48) | \
- ((u64)((p)[7]) << 56))
+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);
+}
-#define SIPROUND(state) \
- do { \
- (state)->v0 += (state)->v1; (state)->v1=ROTL((state)->v1,13); (state)->v1 ^= (state)->v0; (state)->v0=ROTL((state)->v0,32); \
- (state)->v2 += (state)->v3; (state)->v3=ROTL((state)->v3,16); (state)->v3 ^= (state)->v2; \
- (state)->v0 += (state)->v3; (state)->v3=ROTL((state)->v3,21); (state)->v3 ^= (state)->v0; \
- (state)->v2 += (state)->v1; (state)->v1=ROTL((state)->v1,17); (state)->v1 ^= (state)->v2; (state)->v2=ROTL((state)->v2,32); \
- } while(0)
+void siphash24_init(struct siphash *state, const uint8_t k[16]) {
+ uint64_t k0, k1;
-void siphash_init(struct siphash *state, const uint8_t k[16]) {
- u64 k0, k1;
+ assert(state);
+ assert(k);
- k0 = U8TO64_LE( k );
- k1 = U8TO64_LE( k + 8 );
+ k0 = le64toh(*(le64_t*) k);
+ k1 = le64toh(*(le64_t*) (k + 8));
/* "somepseudorandomlygeneratedbytes" */
state->v0 = 0x736f6d6570736575ULL ^ k0;
@@ -68,10 +66,13 @@ void siphash_init(struct siphash *state, const uint8_t k[16]) {
}
void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
- u64 m;
- const u8 *in = _in;
- const u8 *end = in + inlen;
- int left = state->inlen & 7;
+ uint64_t m;
+ const uint8_t *in = _in;
+ const uint8_t *end = in + inlen;
+ unsigned left = state->inlen & 7;
+
+ assert(in);
+ assert(state);
/* update total length */
state->inlen += inlen;
@@ -79,42 +80,41 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
/* if padding exists, fill it out */
if (left > 0) {
for ( ; in < end && left < 8; in ++, left ++ )
- state->padding |= ( ( u64 )*in ) << (left * 8);
+ 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( "(%3d) v0 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v0 >> 32 ), ( u32 )state->v0 );
- printf( "(%3d) v1 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v1 >> 32 ), ( u32 )state->v1 );
- printf( "(%3d) v2 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v2 >> 32 ), ( u32 )state->v2 );
- printf( "(%3d) v3 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v3 >> 32 ), ( u32 )state->v3 );
- printf( "(%3d) compress padding %08x %08x\n", ( int )state->inlen, ( u32 )( state->padding >> 32 ), ( u32 )state->padding );
+ 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);
+ sipround(state);
+ sipround(state);
state->v0 ^= state->padding;
state->padding = 0;
}
- end -= ( state->inlen % sizeof (u64) );
+ end -= ( state->inlen % sizeof (uint64_t) );
- for ( ; in < end; in += 8 )
- {
- m = U8TO64_LE( in );
+ for ( ; in < end; in += 8 ) {
+ m = le64toh(*(le64_t*) in);
#ifdef DEBUG
- printf( "(%3d) v0 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v0 >> 32 ), ( u32 )state->v0 );
- printf( "(%3d) v1 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v1 >> 32 ), ( u32 )state->v1 );
- printf( "(%3d) v2 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v2 >> 32 ), ( u32 )state->v2 );
- printf( "(%3d) v3 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v3 >> 32 ), ( u32 )state->v3 );
- printf( "(%3d) compress %08x %08x\n", ( int )state->inlen, ( u32 )( m >> 32 ), ( u32 )m );
+ 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);
+ sipround(state);
+ sipround(state);
state->v0 ^= m;
}
@@ -122,66 +122,61 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
switch( left )
{
- case 7: state->padding |= ( ( u64 )in[ 6] ) << 48;
+ case 7: state->padding |= ((uint64_t) in[6]) << 48;
- case 6: state->padding |= ( ( u64 )in[ 5] ) << 40;
+ case 6: state->padding |= ((uint64_t) in[5]) << 40;
- case 5: state->padding |= ( ( u64 )in[ 4] ) << 32;
+ case 5: state->padding |= ((uint64_t) in[4]) << 32;
- case 4: state->padding |= ( ( u64 )in[ 3] ) << 24;
+ case 4: state->padding |= ((uint64_t) in[3]) << 24;
- case 3: state->padding |= ( ( u64 )in[ 2] ) << 16;
+ case 3: state->padding |= ((uint64_t) in[2]) << 16;
- case 2: state->padding |= ( ( u64 )in[ 1] ) << 8;
+ case 2: state->padding |= ((uint64_t) in[1]) << 8;
- case 1: state->padding |= ( ( u64 )in[ 0] ); break;
+ case 1: state->padding |= ((uint64_t) in[0]); break;
case 0: break;
}
}
-uint64_t siphash24_finalize(struct siphash *state) {
- u64 b;
+void siphash24_finalize(uint8_t out[8], struct siphash *state) {
+ uint64_t b;
- b = state->padding | (( ( u64 )state->inlen ) << 56);
+ b = state->padding | (( ( uint64_t )state->inlen ) << 56);
#ifdef DEBUG
- printf( "(%3d) v0 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v0 >> 32 ), ( u32 )state->v0 );
- printf( "(%3d) v1 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v1 >> 32 ), ( u32 )state->v1 );
- printf( "(%3d) v2 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v2 >> 32 ), ( u32 )state->v2 );
- printf( "(%3d) v3 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v3 >> 32 ), ( u32 )state->v3 );
- printf( "(%3d) padding %08x %08x\n", ( int )state->inlen, ( u32 )( state->padding >> 32 ), ( u32 )state->padding );
+ 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);
+ sipround(state);
+ sipround(state);
state->v0 ^= b;
#ifdef DEBUG
- printf( "(%3d) v0 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v0 >> 32 ), ( u32 )state->v0 );
- printf( "(%3d) v1 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v1 >> 32 ), ( u32 )state->v1 );
- printf( "(%3d) v2 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v2 >> 32 ), ( u32 )state->v2 );
- printf( "(%3d) v3 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v3 >> 32 ), ( u32 )state->v3 );
+ printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
+ printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
+ printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
+ printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
#endif
state->v2 ^= 0xff;
- SIPROUND(state);
- SIPROUND(state);
- SIPROUND(state);
- SIPROUND(state);
- return state->v0 ^ state->v1 ^ state->v2 ^ state->v3;
+ sipround(state);
+ sipround(state);
+ sipround(state);
+ sipround(state);
+
+ *(le64_t*)out = htole64(state->v0 ^ state->v1 ^ state->v2 ^ state->v3);
}
/* SipHash-2-4 */
-void siphash24(uint8_t out[8], const void *_in, size_t inlen, const uint8_t k[16])
-{
+void siphash24(uint8_t out[8], const void *_in, size_t inlen, const uint8_t k[16]) {
struct siphash state;
- u64 b;
-
- siphash_init(&state, k);
+ siphash24_init(&state, k);
siphash24_compress(_in, inlen, &state);
-
- b = siphash24_finalize(&state);
-
- U64TO8_LE( out, b );
+ siphash24_finalize(out, &state);
}
diff --git a/src/basic/siphash24.h b/src/basic/siphash24.h
index c107bdd21..6c5cd98ee 100644
--- a/src/basic/siphash24.h
+++ b/src/basic/siphash24.h
@@ -12,8 +12,8 @@ struct siphash {
size_t inlen;
};
-void siphash_init(struct siphash *state, const uint8_t k[16]);
+void siphash24_init(struct siphash *state, const uint8_t k[16]);
void siphash24_compress(const void *in, size_t inlen, struct siphash *state);
-uint64_t siphash24_finalize(struct siphash *state);
+void siphash24_finalize(uint8_t out[8], struct siphash *state);
void siphash24(uint8_t out[8], 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
index 9e221d6ea..5f570ff02 100644
--- a/src/basic/smack-util.c
+++ b/src/basic/smack-util.c
@@ -29,9 +29,6 @@
#include "fileio.h"
#include "smack-util.h"
-#define SMACK_FLOOR_LABEL "_"
-#define SMACK_STAR_LABEL "*"
-
#ifdef HAVE_SMACK
bool mac_smack_use(void) {
static int cached_use = -1;
diff --git a/src/basic/smack-util.h b/src/basic/smack-util.h
index b3aa55eb8..e756dc8c2 100644
--- a/src/basic/smack-util.h
+++ b/src/basic/smack-util.h
@@ -27,6 +27,9 @@
#include "macro.h"
+#define SMACK_FLOOR_LABEL "_"
+#define SMACK_STAR_LABEL "*"
+
typedef enum SmackAttr {
SMACK_ATTR_ACCESS = 0,
SMACK_ATTR_EXEC = 1,
diff --git a/src/basic/strv.c b/src/basic/strv.c
index dab34d8e7..d4a1b80d0 100644
--- a/src/basic/strv.c
+++ b/src/basic/strv.c
@@ -188,17 +188,48 @@ char **strv_new(const char *x, ...) {
return r;
}
-int strv_extend_strv(char ***a, char **b) {
- int r;
- char **s;
+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) {
- r = strv_extend(a, *s);
- if (r < 0)
- return r;
+
+ if (filter_duplicates && strv_contains(t, *s))
+ continue;
+
+ t[p+i] = strdup(*s);
+ if (!t[p+i])
+ goto rollback;
+
+ i++;
+ t[p+i] = NULL;
}
- return 0;
+ assert(i <= q);
+
+ return (int) i;
+
+rollback:
+ for (j = 0; j < i; j++)
+ free(t[p + j]);
+
+ t[p] = NULL;
+ return -ENOMEM;
}
/// UNNEEDED by elogind
@@ -275,16 +306,15 @@ char **strv_split_newlines(const char *s) {
if (n <= 0)
return l;
- if (isempty(l[n-1])) {
+ 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) {
- size_t n = 0, allocated = 0;
_cleanup_strv_free_ char **l = NULL;
+ size_t n = 0, allocated = 0;
int r;
assert(t);
@@ -296,9 +326,8 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract
r = extract_first_word(&s, &word, separators, flags);
if (r < 0)
return r;
- if (r == 0) {
+ if (r == 0)
break;
- }
if (!GREEDY_REALLOC(l, allocated, n + 2))
return -ENOMEM;
@@ -309,13 +338,16 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract
l[n] = NULL;
}
- if (!l)
+ if (!l) {
l = new0(char*, 1);
+ if (!l)
+ return -ENOMEM;
+ }
*t = l;
l = NULL;
- return 0;
+ return (int) n;
}
#endif // 0
@@ -632,6 +664,41 @@ char **strv_split_nulstr(const char *s) {
return r;
}
+int strv_make_nulstr(char **l, char **p, size_t *q) {
+ 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 + 1))
+ return -ENOMEM;
+
+ memcpy(m + n, *i, z + 1);
+ n += z + 1;
+ }
+
+ if (!m) {
+ m = new0(char, 1);
+ if (!m)
+ return -ENOMEM;
+ n = 0;
+ }
+
+ *p = m;
+ *q = n;
+
+ m = NULL;
+
+ return 0;
+}
+
/// UNNEEDED by elogind
#if 0
bool strv_overlap(char **a, char **b) {
@@ -660,8 +727,12 @@ char **strv_sort(char **l) {
}
bool strv_equal(char **a, char **b) {
- if (!a || !b)
- return a == 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))
@@ -740,3 +811,66 @@ bool strv_fnmatch(char* const* patterns, const char *s, int flags) {
return false;
}
+
+char ***strv_free_free(char ***l) {
+ char ***i;
+
+ if (!l)
+ return NULL;
+
+ for (i = l; *i; i++)
+ strv_free(*i);
+
+ free(l);
+ return NULL;
+}
+
+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 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;
+}
diff --git a/src/basic/strv.h b/src/basic/strv.h
index 682bb3f75..5ab17acc9 100644
--- a/src/basic/strv.h
+++ b/src/basic/strv.h
@@ -40,7 +40,7 @@ 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);
+int strv_extend_strv(char ***a, char **b, bool filter_duplicates);
// UNNEEDED int strv_extend_strv_concat(char ***a, char **b, const char *suffix);
int strv_extend(char ***l, const char *value);
// UNNEEDED int strv_extendf(char ***l, const char *format, ...) _printf_(2,0);
@@ -80,6 +80,7 @@ char *strv_join(char **l, const char *separator);
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);
// UNNEEDED bool strv_overlap(char **a, char **b) _pure_;
@@ -154,3 +155,9 @@ static inline bool strv_fnmatch_or_empty(char* const* patterns, const char *s, i
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);
diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c
index 8e101c60a..8f63695cf 100644
--- a/src/basic/terminal-util.c
+++ b/src/basic/terminal-util.c
@@ -48,7 +48,7 @@ int chvt(int vt) {
if (fd < 0)
return -errno;
- if (vt < 0) {
+ if (vt <= 0) {
int tiocl[2] = {
TIOCL_GETKMSGREDIRECT,
0
@@ -141,14 +141,14 @@ int ask_char(char *ret, const char *replies, const char *text, ...) {
bool need_nl = true;
if (on_tty())
- fputs(ANSI_HIGHLIGHT_ON, stdout);
+ fputs(ANSI_HIGHLIGHT, stdout);
va_start(ap, text);
vprintf(text, ap);
va_end(ap);
if (on_tty())
- fputs(ANSI_HIGHLIGHT_OFF, stdout);
+ fputs(ANSI_NORMAL, stdout);
fflush(stdout);
@@ -185,14 +185,14 @@ int ask_string(char **ret, const char *text, ...) {
va_list ap;
if (on_tty())
- fputs(ANSI_HIGHLIGHT_ON, stdout);
+ fputs(ANSI_HIGHLIGHT, stdout);
va_start(ap, text);
vprintf(text, ap);
va_end(ap);
if (on_tty())
- fputs(ANSI_HIGHLIGHT_OFF, stdout);
+ fputs(ANSI_NORMAL, stdout);
fflush(stdout);
@@ -613,27 +613,6 @@ int vt_disallocate(const char *name) {
return 0;
}
-void warn_melody(void) {
- _cleanup_close_ int fd = -1;
-
- fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0)
- return;
-
- /* Yeah, this is synchronous. Kinda sucks. But well... */
-
- (void) ioctl(fd, KIOCSOUND, (int)(1193180/440));
- usleep(125*USEC_PER_MSEC);
-
- (void) ioctl(fd, KIOCSOUND, (int)(1193180/220));
- usleep(125*USEC_PER_MSEC);
-
- (void) ioctl(fd, KIOCSOUND, (int)(1193180/220));
- usleep(125*USEC_PER_MSEC);
-
- (void) ioctl(fd, KIOCSOUND, 0);
-}
-
/// UNNEEDED by elogind
#if 0
int make_console_stdio(void) {
diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h
index 7fddb2959..41a7a725e 100644
--- a/src/basic/terminal-util.h
+++ b/src/basic/terminal-util.h
@@ -26,16 +26,22 @@
#include "macro.h"
#include "time-util.h"
-#define ANSI_HIGHLIGHT_ON "\x1B[1;39m"
-#define ANSI_RED_ON "\x1B[31m"
-#define ANSI_HIGHLIGHT_RED_ON "\x1B[1;31m"
-#define ANSI_GREEN_ON "\x1B[32m"
-#define ANSI_HIGHLIGHT_GREEN_ON "\x1B[1;32m"
-#define ANSI_HIGHLIGHT_YELLOW_ON "\x1B[1;33m"
-#define ANSI_HIGHLIGHT_BLUE_ON "\x1B[1;34m"
-#define ANSI_HIGHLIGHT_OFF "\x1B[0m"
+#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_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);
@@ -61,8 +67,6 @@ bool tty_is_console(const char *tty) _pure_;
int vtnr_from_tty(const char *tty);
// UNNEEDED const char *default_term_for_tty(const char *tty);
-void warn_melody(void);
-
int make_stdio(int fd);
int make_null_stdio(void);
// UNNEEDED int make_console_stdio(void);
@@ -78,28 +82,36 @@ unsigned lines(void);
bool on_tty(void);
+static inline const char *ansi_underline(void) {
+ return on_tty() ? ANSI_UNDERLINE : "";
+}
+
static inline const char *ansi_highlight(void) {
- return on_tty() ? ANSI_HIGHLIGHT_ON : "";
+ return on_tty() ? ANSI_HIGHLIGHT : "";
+}
+
+static inline const char *ansi_highlight_underline(void) {
+ return on_tty() ? ANSI_HIGHLIGHT_UNDERLINE : "";
}
static inline const char *ansi_highlight_red(void) {
- return on_tty() ? ANSI_HIGHLIGHT_RED_ON : "";
+ return on_tty() ? ANSI_HIGHLIGHT_RED : "";
}
static inline const char *ansi_highlight_green(void) {
- return on_tty() ? ANSI_HIGHLIGHT_GREEN_ON : "";
+ return on_tty() ? ANSI_HIGHLIGHT_GREEN : "";
}
static inline const char *ansi_highlight_yellow(void) {
- return on_tty() ? ANSI_HIGHLIGHT_YELLOW_ON : "";
+ return on_tty() ? ANSI_HIGHLIGHT_YELLOW : "";
}
static inline const char *ansi_highlight_blue(void) {
- return on_tty() ? ANSI_HIGHLIGHT_BLUE_ON : "";
+ return on_tty() ? ANSI_HIGHLIGHT_BLUE : "";
}
-static inline const char *ansi_highlight_off(void) {
- return on_tty() ? ANSI_HIGHLIGHT_OFF : "";
+static inline const char *ansi_normal(void) {
+ return on_tty() ? ANSI_NORMAL : "";
}
int get_ctty_devnr(pid_t pid, dev_t *d);
diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c
index de1683536..d7a6927ef 100644
--- a/src/basic/unit-name.c
+++ b/src/basic/unit-name.c
@@ -847,6 +847,170 @@ static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
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 snapshot_state_table[_SNAPSHOT_STATE_MAX] = {
+ [SNAPSHOT_DEAD] = "dead",
+ [SNAPSHOT_ACTIVE] = "active"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(snapshot_state, SnapshotState);
+
+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_REQUIRES_OVERRIDABLE] = "RequiresOverridable",
diff --git a/src/basic/unit-name.h b/src/basic/unit-name.h
index e07f7917b..c23ccc803 100644
--- a/src/basic/unit-name.h
+++ b/src/basic/unit-name.h
@@ -27,11 +27,7 @@
#define UNIT_NAME_MAX 256
-typedef enum UnitType UnitType;
-// UNNEEDED typedef enum UnitLoadState UnitLoadState;
-// UNNNEEDED typedef enum UnitDependency UnitDependency;
-
-enum UnitType {
+typedef enum UnitType {
UNIT_SERVICE = 0,
UNIT_SOCKET,
UNIT_BUSNAME,
@@ -47,11 +43,11 @@ enum UnitType {
UNIT_SCOPE,
_UNIT_TYPE_MAX,
_UNIT_TYPE_INVALID = -1
-};
+} UnitType;
/// UNNEEDED by elogind
#if 0
-enum UnitLoadState {
+typedef enum UnitLoadState {
UNIT_STUB = 0,
UNIT_LOADED,
UNIT_NOT_FOUND,
@@ -60,9 +56,176 @@ enum UnitLoadState {
UNIT_MASKED,
_UNIT_LOAD_STATE_MAX,
_UNIT_LOAD_STATE_INVALID = -1
-};
-
-enum UnitDependency {
+} 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 SnapshotState {
+ SNAPSHOT_DEAD,
+ SNAPSHOT_ACTIVE,
+ _SNAPSHOT_STATE_MAX,
+ _SNAPSHOT_STATE_INVALID = -1
+} SnapshotState;
+
+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_REQUIRES_OVERRIDABLE,
@@ -109,7 +272,7 @@ enum UnitDependency {
_UNIT_DEPENDENCY_MAX,
_UNIT_DEPENDENCY_INVALID = -1
-};
+} UnitDependency;
#endif // 0
typedef enum UnitNameFlags {
@@ -185,5 +348,47 @@ UnitType unit_type_from_string(const char *s) _pure_;
// UNNEEDED const char *unit_load_state_to_string(UnitLoadState i) _const_;
// UNNEEDED UnitLoadState unit_load_state_from_string(const char *s) _pure_;
+// UNNEEDED const char *unit_active_state_to_string(UnitActiveState i) _const_;
+// UNNEEDED UnitActiveState unit_active_state_from_string(const char *s) _pure_;
+
+// UNNEEDED const char* automount_state_to_string(AutomountState i) _const_;
+// UNNEEDED AutomountState automount_state_from_string(const char *s) _pure_;
+
+// UNNEEDED const char* busname_state_to_string(BusNameState i) _const_;
+// UNNEEDED BusNameState busname_state_from_string(const char *s) _pure_;
+
+// UNNEEDED const char* device_state_to_string(DeviceState i) _const_;
+// UNNEEDED DeviceState device_state_from_string(const char *s) _pure_;
+
+// UNNEEDED const char* mount_state_to_string(MountState i) _const_;
+// UNNEEDED MountState mount_state_from_string(const char *s) _pure_;
+
+// UNNEEDED const char* path_state_to_string(PathState i) _const_;
+// UNNEEDED PathState path_state_from_string(const char *s) _pure_;
+
+// UNNEEDED const char* scope_state_to_string(ScopeState i) _const_;
+// UNNEEDED ScopeState scope_state_from_string(const char *s) _pure_;
+
+// UNNEEDED const char* service_state_to_string(ServiceState i) _const_;
+// UNNEEDED ServiceState service_state_from_string(const char *s) _pure_;
+
+// UNNEEDED const char* slice_state_to_string(SliceState i) _const_;
+// UNNEEDED SliceState slice_state_from_string(const char *s) _pure_;
+
+// UNNEEDED const char* snapshot_state_to_string(SnapshotState i) _const_;
+// UNNEEDED SnapshotState snapshot_state_from_string(const char *s) _pure_;
+
+// UNNEEDED const char* socket_state_to_string(SocketState i) _const_;
+// UNNEEDED SocketState socket_state_from_string(const char *s) _pure_;
+
+// UNNEEDED const char* swap_state_to_string(SwapState i) _const_;
+// UNNEEDED SwapState swap_state_from_string(const char *s) _pure_;
+
+// UNNEEDED const char* target_state_to_string(TargetState i) _const_;
+// UNNEEDED TargetState target_state_from_string(const char *s) _pure_;
+
+// UNNEEDED const char *timer_state_to_string(TimerState i) _const_;
+// UNNEEDED TimerState timer_state_from_string(const char *s) _pure_;
+
// UNNEEDED const char *unit_dependency_to_string(UnitDependency i) _const_;
// UNNEEDED UnitDependency unit_dependency_from_string(const char *s) _pure_;
diff --git a/src/basic/util.c b/src/basic/util.c
index 6063b1beb..97a07b93c 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -19,82 +19,85 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-// #include <string.h>
-// #include <unistd.h>
-#include <errno.h>
-// #include <stdlib.h>
-// #include <signal.h>
-// #include <libintl.h>
-// #include <stdio.h>
-// #include <syslog.h>
-// #include <sched.h>
-// #include <sys/resource.h>
-// #include <linux/sched.h>
-// #include <sys/types.h>
-// #include <sys/stat.h>
-// #include <fcntl.h>
-// #include <dirent.h>
-// #include <sys/ioctl.h>
-// #include <stdarg.h>
-#include <poll.h>
-// #include <ctype.h>
-#include <sys/prctl.h>
-// #include <sys/utsname.h>
-#include <pwd.h>
-#include <netinet/ip.h>
-// #include <sys/wait.h>
-// #include <sys/time.h>
-// #include <glob.h>
-#include <grp.h>
-// #include <sys/mman.h>
-// #include <sys/vfs.h>
-// #include <sys/mount.h>
-#include <linux/magic.h>
-// #include <limits.h>
-#include <langinfo.h>
-// #include <locale.h>
-// #include <sys/personality.h>
-#include <sys/xattr.h>
-// #include <sys/statvfs.h>
-// #include <sys/file.h>
-#include <linux/fs.h>
+//#include <ctype.h>
+//#include <dirent.h>
+//#include <errno.h>
+//#include <fcntl.h>
+//#include <glob.h>
+#include <grp.h>
+#include <langinfo.h>
+//#include <libintl.h>
+//#include <limits.h>
+#include <linux/magic.h>
+//#include <linux/sched.h>
+//#include <locale.h>
+#include <netinet/ip.h>
+#include <poll.h>
+#include <pwd.h>
+#include <sched.h>
+//#include <signal.h>
+//#include <stdarg.h>
+//#include <stdio.h>
+//#include <stdlib.h>
+//#include <string.h>
+//#include <sys/file.h>
+//#include <sys/ioctl.h>
+//#include <sys/mman.h>
+//#include <sys/mount.h>
+//#include <sys/personality.h>
+#include <sys/prctl.h>
+//#include <sys/resource.h>
+//#include <sys/stat.h>
+//#include <sys/statvfs.h>
+//#include <sys/time.h>
+//#include <sys/types.h>
+//#include <sys/utsname.h>
+//#include <sys/vfs.h>
+//#include <sys/wait.h>
+#include <sys/xattr.h>
+//#include <syslog.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
+ * 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
#ifdef HAVE_SYS_AUXV_H
#include <sys/auxv.h>
#endif
-#include "config.h"
-#include "macro.h"
-#include "util.h"
-// #include "ioprio.h"
-// #include "missing.h"
-// #include "log.h"
-#include "strv.h"
-#include "mkdir.h"
-#include "path-util.h"
-// #include "exit-status.h"
-#include "hashmap.h"
-#include "set.h"
-// #include "env-util.h"
-#include "fileio.h"
-// #include "device-nodes.h"
-#include "utf8.h"
-#include "gunicode.h"
-#include "virt.h"
-// #include "def.h"
-#include "sparse-endian.h"
-// #include "formats-util.h"
-#include "process-util.h"
-#include "random-util.h"
-// #include "terminal-util.h"
-#include "hostname-util.h"
-#include "signal-util.h"
+/* We include linux/fs.h as last of the system headers, as it
+ * otherwise conflicts with sys/mount.h. Yay, Linux is great! */
+//#include <linux/fs.h>
+
+#include "build.h"
+//#include "def.h"
+//#include "device-nodes.h"
+//#include "env-util.h"
+//#include "exit-status.h"
+#include "fileio.h"
+//#include "formats-util.h"
+#include "gunicode.h"
+#include "hashmap.h"
+#include "hostname-util.h"
+//#include "ioprio.h"
+//#include "log.h"
+//#include "macro.h"
+//#include "missing.h"
+#include "mkdir.h"
+#include "path-util.h"
+#include "process-util.h"
+#include "random-util.h"
+#include "signal-util.h"
+#include "sparse-endian.h"
+#include "strv.h"
+//#include "terminal-util.h"
+#include "utf8.h"
+#include "util.h"
+#include "virt.h"
+#include "set.h"
/* Put this test here for a lack of better place */
assert_cc(EAGAIN == EWOULDBLOCK);
@@ -328,6 +331,44 @@ void close_many(const int fds[], unsigned n_fd) {
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 unlink_noerrno(const char *path) {
PROTECT_ERRNO;
int r;
@@ -2218,7 +2259,7 @@ int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
return 0;
}
-int parse_size(const char *t, off_t base, off_t *size) {
+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
@@ -2246,8 +2287,8 @@ int parse_size(const char *t, off_t base, off_t *size) {
{ "G", 1024ULL*1024ULL*1024ULL },
{ "M", 1024ULL*1024ULL },
{ "K", 1024ULL },
- { "B", 1 },
- { "", 1 },
+ { "B", 1ULL },
+ { "", 1ULL },
};
static const struct table si[] = {
@@ -2257,8 +2298,8 @@ int parse_size(const char *t, off_t base, off_t *size) {
{ "G", 1000ULL*1000ULL*1000ULL },
{ "M", 1000ULL*1000ULL },
{ "K", 1000ULL },
- { "B", 1 },
- { "", 1 },
+ { "B", 1ULL },
+ { "", 1ULL },
};
const struct table *table;
@@ -2280,33 +2321,32 @@ int parse_size(const char *t, off_t base, off_t *size) {
p = t;
do {
- long long l;
- unsigned long long l2;
+ unsigned long long l, tmp;
double frac = 0;
char *e;
unsigned i;
- errno = 0;
- l = strtoll(p, &e, 10);
+ p += strspn(p, WHITESPACE);
+ if (*p == '-')
+ return -ERANGE;
+ errno = 0;
+ l = strtoull(p, &e, 10);
if (errno > 0)
return -errno;
-
- if (l < 0)
- return -ERANGE;
-
if (e == p)
return -EINVAL;
if (*e == '.') {
e++;
+
+ /* strtoull() itself would accept space/+/- */
if (*e >= '0' && *e <= '9') {
+ unsigned long long l2;
char *e2;
- /* strotoull itself would accept space/+/- */
l2 = strtoull(e, &e2, 10);
-
- if (errno == ERANGE)
+ if (errno > 0)
return -errno;
/* Ignore failure. E.g. 10.M is valid */
@@ -2319,26 +2359,26 @@ int parse_size(const char *t, off_t base, off_t *size) {
e += strspn(e, WHITESPACE);
for (i = start_pos; i < n_entries; i++)
- if (startswith(e, table[i].suffix)) {
- unsigned long long tmp;
- if ((unsigned long long) l + (frac > 0) > ULLONG_MAX / table[i].factor)
+ 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) (off_t) r != r)
+ if ((unsigned long long) (uint64_t) r != r)
return -ERANGE;
p = e + strlen(table[i].suffix);
start_pos = i + 1;
- break;
- }
-
- if (i >= n_entries)
- return -EINVAL;
} while (*p);
@@ -2538,33 +2578,6 @@ int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
return 0;
}
-cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
- cpu_set_t *r;
- unsigned n = 1024;
-
- /* Allocates the cpuset in the right size */
-
- for (;;) {
- if (!(r = CPU_ALLOC(n)))
- return NULL;
-
- if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), r) >= 0) {
- CPU_ZERO_S(CPU_ALLOC_SIZE(n), r);
-
- if (ncpus)
- *ncpus = n;
-
- return r;
- }
-
- CPU_FREE(r);
-
- if (errno != EINVAL)
- return NULL;
-
- n *= 2;
- }
-}
#endif // 0
int files_same(const char *filea, const char *fileb) {
@@ -3698,7 +3711,6 @@ static const char *const ioprio_class_table[] = {
};
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
-#endif // 0
static const char *const sigchld_code_table[] = {
[CLD_EXITED] = "exited",
@@ -3735,6 +3747,7 @@ static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = {
};
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0));
+#endif // 0
static const char *const log_level_table[] = {
[LOG_EMERG] = "emerg",
@@ -3749,6 +3762,8 @@ static const char *const log_level_table[] = {
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG);
+/// UNNEEDED by elogind
+#if 0
static const char* const sched_policy_table[] = {
[SCHED_OTHER] = "other",
[SCHED_BATCH] = "batch",
@@ -3758,6 +3773,7 @@ static const char* const sched_policy_table[] = {
};
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
+#endif // 0
static const char* const rlimit_table[_RLIMIT_MAX] = {
[RLIMIT_CPU] = "LimitCPU",
@@ -3780,6 +3796,8 @@ static const char* const rlimit_table[_RLIMIT_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
+/// UNNEEDED by elogind
+#if 0
static const char* const ip_tos_table[] = {
[IPTOS_LOWDELAY] = "low-delay",
[IPTOS_THROUGHPUT] = "throughput",
@@ -3801,8 +3819,6 @@ bool kexec_loaded(void) {
return loaded;
}
-/// UNNEEDED by elogind
-#if 0
int prot_from_flags(int flags) {
switch (flags & O_ACCMODE) {
@@ -3821,38 +3837,38 @@ int prot_from_flags(int flags) {
}
}
-char *format_bytes(char *buf, size_t l, off_t t) {
+char *format_bytes(char *buf, size_t l, uint64_t t) {
unsigned i;
static const struct {
const char *suffix;
- off_t factor;
+ uint64_t factor;
} table[] = {
- { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
- { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
- { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
- { "G", 1024ULL*1024ULL*1024ULL },
- { "M", 1024ULL*1024ULL },
- { "K", 1024ULL },
+ { "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 == (off_t) -1)
+ if (t == (uint64_t) -1)
return NULL;
for (i = 0; i < ELEMENTSOF(table); i++) {
if (t >= table[i].factor) {
snprintf(buf, l,
- "%llu.%llu%s",
- (unsigned long long) (t / table[i].factor),
- (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
+ "%" 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, "%lluB", (unsigned long long) t);
+ snprintf(buf, l, "%" PRIu64 "B", t);
finish:
buf[l-1] = 0;
@@ -4899,7 +4915,7 @@ int shall_restore_state(void) {
int proc_cmdline(char **ret) {
assert(ret);
- if (detect_container(NULL) > 0)
+ if (detect_container() > 0)
return get_process_cmdline(1, 0, false, ret);
else
return read_one_line_file("/proc/cmdline", ret);
@@ -5297,6 +5313,19 @@ unsigned long personality_from_string(const char *p) {
if (streq(p, "x86"))
return PER_LINUX;
+
+#elif defined(__s390x__)
+
+ if (streq(p, "s390"))
+ return PER_LINUX32;
+
+ if (streq(p, "s390x"))
+ return PER_LINUX;
+
+#elif defined(__s390__)
+
+ if (streq(p, "s390"))
+ return PER_LINUX;
#endif
return PERSONALITY_INVALID;
@@ -5316,6 +5345,20 @@ const char* personality_to_string(unsigned long p) {
if (p == PER_LINUX)
return "x86";
+
+#elif defined(__s390x__)
+
+ if (p == PER_LINUX)
+ return "s390x";
+
+ if (p == PER_LINUX32)
+ return "s390";
+
+#elif defined(__s390__)
+
+ if (p == PER_LINUX)
+ return "s390";
+
#endif
return NULL;
@@ -5383,15 +5426,13 @@ int update_reboot_param_file(const char *param) {
int r = 0;
if (param) {
-
r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE);
if (r < 0)
- log_error("Failed to write reboot param to "
- REBOOT_PARAM_FILE": %s", strerror(-r));
+ return log_error_errno(r, "Failed to write reboot param to "REBOOT_PARAM_FILE": %m");
} else
- unlink(REBOOT_PARAM_FILE);
+ (void) unlink(REBOOT_PARAM_FILE);
- return r;
+ return 0;
}
int umount_recursive(const char *prefix, int flags) {
@@ -6034,6 +6075,7 @@ int extract_first_word_and_warn(
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. */
@@ -6043,16 +6085,16 @@ int extract_first_word_and_warn(
save = *p;
r = extract_first_word(p, ret, separators, flags);
if (r < 0 && !(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)
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Unbalanced quoting in command line, ignoring: \"%s\"", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Unbalanced quoting in command line, ignoring: \"%s\"", rvalue);
else
- log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
- "Invalid escape sequences in command line: \"%s\"", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid escape sequences in command line: \"%s\"", rvalue);
}
+
return r;
}
@@ -6169,15 +6211,6 @@ int ptsname_malloc(int fd, char **ret) {
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 };
- 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;
siginfo_t si;
pid_t child;
int r;
@@ -6211,15 +6244,7 @@ int openpt_in_namespace(pid_t pid, int flags) {
if (unlockpt(master) < 0)
_exit(EXIT_FAILURE);
- 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), &master, sizeof(int));
-
- mh.msg_controllen = cmsg->cmsg_len;
-
- if (sendmsg(pair[1], &mh, MSG_NOSIGNAL) < 0)
+ if (send_one_fd(pair[1], master, 0) < 0)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
@@ -6233,40 +6258,24 @@ int openpt_in_namespace(pid_t pid, int flags) {
if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
return -EIO;
- if (recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC) < 0)
- return -errno;
-
- CMSG_FOREACH(cmsg, &mh)
- if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
- int *fds;
- unsigned n_fds;
-
- fds = (int*) CMSG_DATA(cmsg);
- n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
-
- if (n_fds != 1) {
- close_many(fds, n_fds);
- return -EIO;
- }
-
- return fds[0];
- }
-
- return -EIO;
+ return receive_one_fd(pair[0], 0);
}
#endif // 0
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_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOATIME|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
+ fd = openat(dirfd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
if (fd < 0)
return -errno;
- l = fgetxattr(fd, attribute, value, size);
+ xsprintf(fn, "/proc/self/fd/%i", fd);
+
+ l = getxattr(fn, attribute, value, size);
if (l < 0)
return -errno;
@@ -6415,7 +6424,6 @@ int same_fd(int a, int b) {
return fa == fb;
}
-#endif // 0
int chattr_fd(int fd, unsigned value, unsigned mask) {
unsigned old_attr, new_attr;
@@ -6451,8 +6459,6 @@ int chattr_fd(int fd, unsigned value, unsigned mask) {
return 1;
}
-/// UNNEEDED by elogind
-#if 0
int chattr_path(const char *p, unsigned value, unsigned mask) {
_cleanup_close_ int fd = -1;
@@ -6467,7 +6473,6 @@ int chattr_path(const char *p, unsigned value, unsigned mask) {
return chattr_fd(fd, value, mask);
}
-#endif // 0
int read_attr_fd(int fd, unsigned *ret) {
struct stat st;
@@ -6486,8 +6491,6 @@ int read_attr_fd(int fd, unsigned *ret) {
return 0;
}
-/// UNNEEDED by elogind
-#if 0
int read_attr_path(const char *p, unsigned *ret) {
_cleanup_close_ int fd = -1;
@@ -6870,3 +6873,115 @@ int fgetxattr_malloc(int fd, const char *name, char **value) {
return -errno;
}
}
+
+int send_one_fd(int transport_fd, int 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;
+
+ 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;
+}
+
+/// UNNEEDED by elogind
+#if 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);
+}
+
+void nop_signal_handler(int sig) {
+ /* nothing here */
+}
+#endif // 0
+
+int version(void) {
+ puts(PACKAGE_STRING "\n"
+ SYSTEMD_FEATURES);
+ return 0;
+}
+
+/// UNNEEDED by elogind
+#if 0
+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;
+}
+#endif // 0
diff --git a/src/basic/util.h b/src/basic/util.h
index 2fde42821..f55480abe 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -22,31 +22,30 @@
***/
#include <alloca.h>
+#include <dirent.h>
#include <fcntl.h>
#include <inttypes.h>
-#include <time.h>
+#include <limits.h>
+#include <locale.h>
+#include <mntent.h>
#include <stdarg.h>
#include <stdbool.h>
-#include <stdlib.h>
+#include <stddef.h>
#include <stdio.h>
-#include <sched.h>
-#include <limits.h>
-#include <sys/types.h>
+#include <stdlib.h>
+#include <sys/inotify.h>
#include <sys/socket.h>
#include <sys/stat.h>
-#include <dirent.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <locale.h>
-#include <mntent.h>
-#include <sys/inotify.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"
-#include "formats-util.h"
/* What is interpreted as whitespace? */
#define WHITESPACE " \t\n\r"
@@ -150,7 +149,11 @@ void safe_close_pair(int p[]);
void close_many(const int fds[], unsigned n_fd);
-int parse_size(const char *t, off_t base, off_t *size);
+int fclose_nointr(FILE *f);
+FILE* safe_fclose(FILE *f);
+DIR* safe_closedir(DIR *f);
+
+int parse_size(const char *t, uint64_t base, uint64_t *size);
int parse_boolean(const char *v) _pure_;
int parse_pid(const char *s, pid_t* ret_pid);
@@ -158,7 +161,10 @@ int parse_uid(const char *s, uid_t* ret_uid);
#define parse_gid(s, ret_gid) parse_uid(s, ret_gid)
bool uid_is_valid(uid_t uid);
-#define gid_is_valid(gid) uid_is_valid(gid)
+
+static inline bool gid_is_valid(gid_t gid) {
+ return uid_is_valid((uid_t) gid);
+}
int safe_atou(const char *s, unsigned *ret_u);
int safe_atoi(const char *s, int *ret_i);
@@ -365,12 +371,9 @@ int fd_is_temporary_fs(int fd);
int pipe_eof(int fd);
-DEFINE_TRIVIAL_CLEANUP_FUNC(cpu_set_t*, CPU_FREE);
-#define _cleanup_cpu_free_ _cleanup_(CPU_FREEp)
-
-// UNNEEDED cpu_set_t* cpu_set_malloc(unsigned *ncpus);
-
-#define xsprintf(buf, fmt, ...) assert_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf))
+#define xsprintf(buf, fmt, ...) \
+ assert_message_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf), \
+ "xsprintf: " #buf "[] must be big enough")
int files_same(const char *filea, const char *fileb);
@@ -449,28 +452,28 @@ static inline bool _pure_ in_charset(const char *s, const char* charset) {
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_;
+// UNNEEDED const char *sigchld_code_to_string(int i) _const_;
+// UNNEEDED int sigchld_code_from_string(const char *s) _pure_;
-int log_facility_unshifted_to_string_alloc(int i, char **s);
-int log_facility_unshifted_from_string(const char *s);
+// UNNEEDED int log_facility_unshifted_to_string_alloc(int i, char **s);
+// UNNEEDED int log_facility_unshifted_from_string(const char *s);
int log_level_to_string_alloc(int i, char **s);
int log_level_from_string(const char *s);
-int sched_policy_to_string_alloc(int i, char **s);
-int sched_policy_from_string(const char *s);
+// UNNEEDED int sched_policy_to_string_alloc(int i, char **s);
+// UNNEEDED int sched_policy_from_string(const char *s);
const char *rlimit_to_string(int i) _const_;
int rlimit_from_string(const char *s) _pure_;
-int ip_tos_to_string_alloc(int i, char **s);
-int ip_tos_from_string(const char *s);
+// UNNEEDED int ip_tos_to_string_alloc(int i, char **s);
+// UNNEEDED int ip_tos_from_string(const char *s);
extern int saved_argc;
extern char **saved_argv;
-bool kexec_loaded(void);
+// UNNEEDED bool kexec_loaded(void);
// UNNEEDED int prot_from_flags(int flags) _const_;
@@ -513,7 +516,10 @@ static inline void close_pairp(int (*p)[2]) {
safe_close_pair(*p);
}
-DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, fclose);
+static inline void fclosep(FILE **f) {
+ safe_fclose(*f);
+}
+
DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, pclose);
DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent);
@@ -870,11 +876,6 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
// UNNEEDED 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);
// UNNEEDED int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) _sentinel_;
-static inline void free_and_replace(char **s, char *v) {
- free(*s);
- *s = v;
-}
-
int free_and_strdup(char **p, const char *s);
#define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1)
@@ -908,10 +909,10 @@ int fd_getcrtime(int fd, usec_t *usec);
// UNNEEDED int same_fd(int a, int b);
-int chattr_fd(int fd, unsigned value, unsigned mask);
+// UNNEEDED int chattr_fd(int fd, unsigned value, unsigned mask);
// UNNEEDED int chattr_path(const char *p, unsigned value, unsigned mask);
-int read_attr_fd(int fd, unsigned *ret);
+// UNNEEDED int read_attr_fd(int fd, unsigned *ret);
// UNNEEDED int read_attr_path(const char *p, unsigned *ret);
#define RLIMIT_MAKE_CONST(lim) ((struct rlimit) { lim, lim })
@@ -938,3 +939,12 @@ int reset_uid_gid(void);
int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink);
int fgetxattr_malloc(int fd, const char *name, char **value);
+
+int send_one_fd(int transport_fd, int fd, int flags);
+// UNNEEDED int receive_one_fd(int transport_fd, int flags);
+
+// UNNEEDED void nop_signal_handler(int sig);
+
+int version(void);
+
+// UNNEEDED bool fdname_is_valid(const char *s);
diff --git a/src/basic/virt.c b/src/basic/virt.c
index 1f9843bab..8e398e506 100644
--- a/src/basic/virt.c
+++ b/src/basic/virt.c
@@ -28,25 +28,24 @@
#include "virt.h"
#include "fileio.h"
-static int detect_vm_cpuid(const char **_id) {
+static int detect_vm_cpuid(void) {
/* Both CPUID and DMI are x86 specific interfaces... */
#if defined(__i386__) || defined(__x86_64__)
- static const char cpuid_vendor_table[] =
- "XenVMMXenVMM\0" "xen\0"
- "KVMKVMKVM\0" "kvm\0"
+ 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\0" "vmware\0"
+ { "VMwareVMware", VIRTUALIZATION_VMWARE },
/* http://msdn.microsoft.com/en-us/library/ff542428.aspx */
- "Microsoft Hv\0" "microsoft\0";
+ { "Microsoft Hv", VIRTUALIZATION_MICROSOFT },
+ };
uint32_t eax, ecx;
- union {
- uint32_t sig32[3];
- char text[13];
- } sig = {};
- const char *j, *k;
bool hypervisor;
/* http://lwn.net/Articles/301888/ */
@@ -74,6 +73,11 @@ static int detect_vm_cpuid(const char **_id) {
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;
@@ -88,57 +92,54 @@ static int detect_vm_cpuid(const char **_id) {
: "0" (eax)
);
- NULSTR_FOREACH_PAIR(j, k, cpuid_vendor_table)
- if (streq(sig.text, j)) {
- *_id = k;
- return 1;
- }
+ for (j = 0; j < ELEMENTSOF(cpuid_vendor_table); j ++)
+ if (streq(sig.text, cpuid_vendor_table[j].cpuid))
+ return cpuid_vendor_table[j].id;
- *_id = "other";
- return 0;
+ return VIRTUALIZATION_VM_OTHER;
}
#endif
- return 0;
+ return VIRTUALIZATION_NONE;
}
-static int detect_vm_devicetree(const char **_id) {
+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 >= 0) {
- if (streq(hvtype, "linux,kvm")) {
- *_id = "kvm";
- return 1;
- } else if (strstr(hvtype, "xen")) {
- *_id = "xen";
- return 1;
- }
- } else if (r == -ENOENT) {
+ if (r == -ENOENT) {
_cleanup_closedir_ DIR *dir = NULL;
struct dirent *dent;
dir = opendir("/proc/device-tree");
if (!dir) {
if (errno == ENOENT)
- return 0;
+ return VIRTUALIZATION_NONE;
return -errno;
}
- FOREACH_DIRENT(dent, dir, return -errno) {
- if (strstr(dent->d_name, "fw-cfg")) {
- *_id = "qemu";
- return 1;
- }
- }
- }
+ FOREACH_DIRENT(dent, dir, return -errno)
+ if (strstr(dent->d_name, "fw-cfg"))
+ return VIRTUALIZATION_QEMU;
+
+ return VIRTUALIZATION_NONE;
+ } else if (r < 0)
+ return r;
+
+ if (streq(hvtype, "linux,kvm"))
+ return VIRTUALIZATION_KVM;
+ else if (strstr(hvtype, "xen"))
+ return VIRTUALIZATION_XEN;
+ else
+ return VIRTUALIZATION_VM_OTHER;
+#else
+ return VIRTUALIZATION_NONE;
#endif
- return 0;
}
-static int detect_vm_dmi(const char **_id) {
+static int detect_vm_dmi(void) {
/* Both CPUID and DMI are x86 specific interfaces... */
#if defined(__i386__) || defined(__x86_64__)
@@ -149,188 +150,195 @@ static int detect_vm_dmi(const char **_id) {
"/sys/class/dmi/id/bios_vendor"
};
- static const char dmi_vendor_table[] =
- "QEMU\0" "qemu\0"
+ static const struct {
+ const char *vendor;
+ int id;
+ } dmi_vendor_table[] = {
+ { "QEMU", VIRTUALIZATION_QEMU },
/* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
- "VMware\0" "vmware\0"
- "VMW\0" "vmware\0"
- "innotek GmbH\0" "oracle\0"
- "Xen\0" "xen\0"
- "Bochs\0" "bochs\0"
- "Parallels\0" "parallels\0";
+ { "VMware", VIRTUALIZATION_VMWARE },
+ { "VMW", VIRTUALIZATION_VMWARE },
+ { "innotek GmbH", VIRTUALIZATION_ORACLE },
+ { "Xen", VIRTUALIZATION_XEN },
+ { "Bochs", VIRTUALIZATION_BOCHS },
+ { "Parallels", VIRTUALIZATION_PARALLELS },
+ };
unsigned i;
+ int r;
for (i = 0; i < ELEMENTSOF(dmi_vendors); i++) {
_cleanup_free_ char *s = NULL;
- const char *j, *k;
- int r;
+ unsigned j;
r = read_one_line_file(dmi_vendors[i], &s);
if (r < 0) {
- if (r != -ENOENT)
- return r;
-
+ if (r == -ENOENT)
continue;
- }
- NULSTR_FOREACH_PAIR(j, k, dmi_vendor_table)
- if (startswith(s, j)) {
- *_id = k;
- return 1;
+ return r;
}
+
+ for (j = 0; j < ELEMENTSOF(dmi_vendor_table); j++)
+ if (startswith(s, dmi_vendor_table[j].vendor))
+ return dmi_vendor_table[j].id;
}
#endif
- return 0;
+ return VIRTUALIZATION_NONE;
}
-/* Returns a short identifier for the various VM implementations */
-int detect_vm(const char **id) {
- _cleanup_free_ char *domcap = NULL, *cpuinfo_contents = NULL;
- static thread_local int cached_found = -1;
- static thread_local const char *cached_id = NULL;
- const char *_id = NULL, *_id_cpuid = NULL;
+static int detect_vm_xen(void) {
+ _cleanup_free_ char *domcap = NULL;
+ char *cap, *i;
int r;
- if (_likely_(cached_found >= 0)) {
-
- if (id)
- *id = cached_id;
-
- return cached_found;
- }
-
- /* Try xen capabilities file first, if not found try high-level hypervisor sysfs file:
- *
- * https://bugs.freedesktop.org/show_bug.cgi?id=77271 */
r = read_one_line_file("/proc/xen/capabilities", &domcap);
- if (r >= 0) {
- char *cap, *i = domcap;
+ if (r == -ENOENT)
+ return VIRTUALIZATION_NONE;
+ i = domcap;
while ((cap = strsep(&i, ",")))
if (streq(cap, "control_d"))
break;
- if (!cap) {
- _id = "xen";
- r = 1;
+ return cap ? VIRTUALIZATION_NONE : VIRTUALIZATION_XEN;
}
- goto finish;
-
- } else if (r == -ENOENT) {
+static int detect_vm_hypervisor(void) {
_cleanup_free_ char *hvtype = NULL;
+ int r;
r = read_one_line_file("/sys/hypervisor/type", &hvtype);
- if (r >= 0) {
- if (streq(hvtype, "xen")) {
- _id = "xen";
- r = 1;
- goto finish;
- }
- } else if (r != -ENOENT)
- return r;
- } else
+ if (r == -ENOENT)
+ return VIRTUALIZATION_NONE;
+ if (r < 0)
return r;
- /* this will set _id to "other" and return 0 for unknown hypervisors */
- r = detect_vm_cpuid(&_id);
+ if (streq(hvtype, "xen"))
+ return VIRTUALIZATION_XEN;
+ else
+ return VIRTUALIZATION_VM_OTHER;
+}
- /* finish when found a known hypervisor other than kvm */
- if (r < 0 || (r > 0 && !streq(_id, "kvm")))
- goto finish;
+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"))
+ return VIRTUALIZATION_UML;
- _id_cpuid = _id;
+ return VIRTUALIZATION_NONE;
+}
- r = detect_vm_dmi(&_id);
+static int detect_vm_zvm(void) {
- /* kvm with and without Virtualbox */
- /* Parallels exports KVMKVMKVM leaf */
- if (streq_ptr(_id_cpuid, "kvm")) {
- if (r > 0 && (streq(_id, "oracle") || streq(_id, "parallels")))
- goto finish;
+#if defined(__s390__)
+ _cleanup_free_ char *t = NULL;
+ int r;
- _id = _id_cpuid;
- r = 1;
- goto finish;
+ r = get_proc_field("/proc/sysinfo", "VM00 Control Program", WHITESPACE, &t);
+ if (r == -ENOENT)
+ return VIRTUALIZATION_NONE;
+ if (r < 0)
+ return r;
+
+ if (streq(t, "z/VM"))
+ return VIRTUALIZATION_ZVM;
+ else
+ return VIRTUALIZATION_KVM;
+#else
+ return VIRTUALIZATION_NONE;
+#endif
}
- /* information from dmi */
- if (r != 0)
- goto finish;
+/* Returns a short identifier for the various VM implementations */
+int detect_vm(void) {
+ static thread_local int cached_found = _VIRTUALIZATION_INVALID;
+ int r;
- r = detect_vm_devicetree(&_id);
- if (r != 0)
+ if (cached_found >= 0)
+ return cached_found;
+
+ /* Try xen capabilities file first, if not found try
+ * 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;
- if (_id) {
- /* "other" */
- r = 1;
+ r = detect_vm_dmi();
+ if (r < 0)
+ return r;
+ if (r != VIRTUALIZATION_NONE)
goto finish;
- }
- /* Detect User-Mode Linux by reading /proc/cpuinfo */
- r = read_full_file("/proc/cpuinfo", &cpuinfo_contents, NULL);
+ r = detect_vm_cpuid();
if (r < 0)
return r;
- if (strstr(cpuinfo_contents, "\nvendor_id\t: User Mode Linux\n")) {
- _id = "uml";
- r = 1;
+ if (r != VIRTUALIZATION_NONE)
goto finish;
- }
-#if defined(__s390__)
- {
- _cleanup_free_ char *t = NULL;
+ r = detect_vm_hypervisor();
+ if (r < 0)
+ return r;
+ if (r != VIRTUALIZATION_NONE)
+ goto finish;
- r = get_status_field("/proc/sysinfo", "VM00 Control Program:", &t);
- if (r >= 0) {
- if (streq(t, "z/VM"))
- _id = "zvm";
- else
- _id = "kvm";
- r = 1;
+ 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;
- }
- }
-#endif
- r = 0;
+ r = detect_vm_zvm();
+ if (r < 0)
+ return r;
finish:
cached_found = r;
-
- cached_id = _id;
- if (id)
- *id = _id;
-
return r;
}
-int detect_container(const char **id) {
+int detect_container(void) {
- static thread_local int cached_found = -1;
- static thread_local const char *cached_id = NULL;
+ 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 },
+ };
+ static thread_local int cached_found = _VIRTUALIZATION_INVALID;
_cleanup_free_ char *m = NULL;
- const char *_id = NULL, *e = NULL;
+ const char *e = NULL;
+ unsigned j;
int r;
- if (_likely_(cached_found >= 0)) {
-
- if (id)
- *id = cached_id;
-
+ 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) {
- _id = "openvz";
- r = 1;
+ r = VIRTUALIZATION_OPENVZ;
goto finish;
}
@@ -340,7 +348,7 @@ int detect_container(const char **id) {
e = getenv("container");
if (isempty(e)) {
- r = 0;
+ r = VIRTUALIZATION_NONE;
goto finish;
}
} else {
@@ -369,7 +377,7 @@ int detect_container(const char **id) {
* as /proc/1/environ is only readable
* with privileges. */
- r = 0;
+ r = VIRTUALIZATION_NONE;
goto finish;
}
}
@@ -379,49 +387,52 @@ int detect_container(const char **id) {
e = m;
}
- /* We only recognize a selected few here, since we want to
- * enforce a redacted namespace */
- if (streq(e, "lxc"))
- _id ="lxc";
- else if (streq(e, "lxc-libvirt"))
- _id = "lxc-libvirt";
- else if (streq(e, "systemd-nspawn"))
- _id = "systemd-nspawn";
- else if (streq(e, "docker"))
- _id = "docker";
- else
- _id = "other";
+ for (j = 0; j < ELEMENTSOF(value_table); j++)
+ if (streq(e, value_table[j].value)) {
+ r = value_table[j].id;
+ goto finish;
+ }
- r = 1;
+ r = VIRTUALIZATION_NONE;
finish:
cached_found = r;
-
- cached_id = _id;
- if (id)
- *id = _id;
-
return r;
}
/// UNNEEDED by elogind
#if 0
-/* Returns a short identifier for the various VM/container implementations */
-int detect_virtualization(const char **id) {
+int detect_virtualization(void) {
int r;
- r = detect_container(id);
- if (r < 0)
- return r;
- if (r > 0)
- return VIRTUALIZATION_CONTAINER;
-
- r = detect_vm(id);
- if (r < 0)
+ r = detect_container();
+ if (r != 0)
return r;
- if (r > 0)
- return VIRTUALIZATION_VM;
- return VIRTUALIZATION_NONE;
+ return detect_vm();
}
#endif // 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_VM_OTHER] = "vm-other",
+
+ [VIRTUALIZATION_SYSTEMD_NSPAWN] = "systemd-nspawn",
+ [VIRTUALIZATION_LXC_LIBVIRT] = "lxc-libvirt",
+ [VIRTUALIZATION_LXC] = "lxc",
+ [VIRTUALIZATION_OPENVZ] = "openvz",
+ [VIRTUALIZATION_DOCKER] = "docker",
+ [VIRTUALIZATION_CONTAINER_OTHER] = "container-other",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(virtualization, int);
diff --git a/src/basic/virt.h b/src/basic/virt.h
index 0f390981d..d63e028a2 100644
--- a/src/basic/virt.h
+++ b/src/basic/virt.h
@@ -21,15 +21,51 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-int detect_vm(const char **id);
-int detect_container(const char **id);
+#include <stdbool.h>
+
+#include "macro.h"
enum {
VIRTUALIZATION_NONE = 0,
- VIRTUALIZATION_VM,
- VIRTUALIZATION_CONTAINER,
+
+ 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_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_CONTAINER_OTHER,
+ VIRTUALIZATION_CONTAINER_LAST = VIRTUALIZATION_CONTAINER_OTHER,
+
_VIRTUALIZATION_MAX,
_VIRTUALIZATION_INVALID = -1
};
-// UNNEEDED int detect_virtualization(const char **id);
+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);
+// UNNEEDED int detect_virtualization(void);
+
+const char *virtualization_to_string(int v) _const_;
+int virtualization_from_string(const char *s) _pure_;