chiark / gitweb /
[2/5] Apply missing fixes from upstream
authorSven Eden <yamakuzure@gmx.net>
Wed, 29 Mar 2017 08:05:50 +0000 (10:05 +0200)
committerSven Eden <yamakuzure@gmx.net>
Wed, 29 Mar 2017 08:48:11 +0000 (10:48 +0200)
16 files changed:
src/basic/selinux-util.c
src/basic/selinux-util.h
src/basic/siphash24.c
src/basic/siphash24.h
src/basic/smack-util.c
src/basic/smack-util.h
src/basic/strv.c
src/basic/strv.h
src/basic/terminal-util.c
src/basic/terminal-util.h
src/basic/unit-name.c
src/basic/unit-name.h
src/basic/util.c
src/basic/util.h
src/basic/virt.c
src/basic/virt.h

index cea80b6..239900b 100644 (file)
@@ -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
 
index 559b0d6..caac8df 100644 (file)
   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);
 
index 308e423..fa94f80 100644 (file)
    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);
 }
index c107bdd..6c5cd98 100644 (file)
@@ -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]);
index 9e221d6..5f570ff 100644 (file)
@@ -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;
index b3aa55e..e756dc8 100644 (file)
@@ -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,
index dab34d8..d4a1b80 100644 (file)
@@ -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;
+}
index 682bb3f..5ab17ac 100644 (file)
@@ -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);
index 8e101c6..8f63695 100644 (file)
@@ -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) {
index 7fddb29..41a7a72 100644 (file)
 #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);
index de16835..d7a6927 100644 (file)
@@ -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",
index e07f791..c23ccc8 100644 (file)
 
 #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_;
index 6063b1b..97a07b9 100644 (file)
   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
index 2fde428..f55480a 100644 (file)
 ***/
 
 #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);
index 1f9843b..8e398e5 100644 (file)
 #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);
index 0f39098..d63e028 100644 (file)
   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_;