summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ask-password/ask-password.c11
-rw-r--r--src/basic/c-rbtree.c5
-rw-r--r--src/basic/clock-util.c11
-rw-r--r--src/basic/clock-util.h2
-rw-r--r--src/basic/copy.c63
-rw-r--r--src/basic/fileio.c6
-rw-r--r--src/basic/formats-util.h2
-rw-r--r--src/basic/hashmap.c14
-rw-r--r--src/basic/hostname-util.c4
-rw-r--r--src/basic/log.h1
-rw-r--r--src/basic/macro.h13
-rw-r--r--src/basic/missing.h216
-rw-r--r--src/basic/missing_syscall.h310
-rw-r--r--src/basic/mount-util.c4
-rw-r--r--src/basic/selinux-util.c34
-rw-r--r--src/basic/selinux-util.h2
-rw-r--r--src/basic/set.h3
-rw-r--r--src/basic/socket-label.c34
-rw-r--r--src/basic/time-util.c7
-rw-r--r--src/basic/util.h1
-rw-r--r--src/basic/xattr-util.c2
-rw-r--r--src/core/dbus-manager.c2
-rw-r--r--src/core/device.c2
-rw-r--r--src/core/execute.c2
-rw-r--r--src/core/failure-action.c6
-rw-r--r--src/core/job.c26
-rw-r--r--src/core/load-fragment.c14
-rw-r--r--src/core/main.c21
-rw-r--r--src/core/mount.c26
-rw-r--r--src/core/selinux-setup.c2
-rw-r--r--src/core/smack-setup.c2
-rw-r--r--src/core/transaction.c9
-rw-r--r--src/core/umount.c1
-rw-r--r--src/firstboot/firstboot.c12
-rw-r--r--src/fstab-generator/fstab-generator.c4
-rw-r--r--src/hostname/hostnamed.c2
-rw-r--r--src/journal/compress.c5
-rw-r--r--src/journal/sd-journal.c3
-rw-r--r--src/journal/test-compress-benchmark.c2
-rw-r--r--src/libsystemd-network/dhcp-identifier.c2
-rw-r--r--src/libsystemd-network/dhcp-identifier.h41
-rw-r--r--src/libsystemd-network/dhcp6-protocol.h7
-rw-r--r--src/libsystemd-network/lldp-neighbor.c7
-rw-r--r--src/libsystemd-network/network-internal.c28
-rw-r--r--src/libsystemd-network/network-internal.h4
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c50
-rw-r--r--src/libsystemd-network/sd-dhcp-lease.c2
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c49
-rw-r--r--src/libsystemd-network/sd-lldp.c17
-rw-r--r--src/libsystemd/sd-bus/bus-message.c15
-rw-r--r--src/libsystemd/sd-bus/sd-bus.c5
-rw-r--r--src/libsystemd/sd-netlink/netlink-message.c5
-rw-r--r--src/libsystemd/sd-path/sd-path.c9
-rw-r--r--src/libudev/libudev.h1
-rw-r--r--src/locale/localed.c2
-rw-r--r--src/login/70-uaccess.rules3
-rw-r--r--src/login/logind.c2
-rw-r--r--src/network/networkctl.c6
-rw-r--r--src/network/networkd-conf.c133
-rw-r--r--src/network/networkd-conf.h32
-rw-r--r--src/network/networkd-dhcp4.c8
-rw-r--r--src/network/networkd-dhcp6.c10
-rw-r--r--src/network/networkd-gperf.gperf18
-rw-r--r--src/network/networkd-link.c18
-rw-r--r--src/network/networkd-manager.c2
-rw-r--r--src/network/networkd-network-gperf.gperf1
-rw-r--r--src/network/networkd-network.c5
-rw-r--r--src/network/networkd-network.h2
-rw-r--r--src/network/networkd.c5
-rw-r--r--src/network/networkd.h5
-rw-r--r--src/nspawn/nspawn-cgroup.c4
-rw-r--r--src/nspawn/nspawn.c14
-rw-r--r--src/resolve/resolve-tool.c20
-rw-r--r--src/resolve/resolved-dns-query.c5
-rw-r--r--src/resolve/resolved-dns-transaction.c62
-rw-r--r--src/resolve/resolved-dns-transaction.h6
-rw-r--r--src/resolve/resolved-dns-zone.c5
-rw-r--r--src/resolve/resolved.c2
-rw-r--r--src/run/run.c4
-rw-r--r--src/shared/acpi-fpdt.c6
-rw-r--r--src/shared/machine-pool.c8
-rw-r--r--src/shared/ptyfwd.c5
-rw-r--r--src/stdio-bridge/stdio-bridge.c7
-rw-r--r--src/systemctl/systemctl.c108
-rw-r--r--src/systemd/_sd-common.h2
-rw-r--r--src/systemd/sd-bus-protocol.h2
-rw-r--r--src/systemd/sd-bus-vtable.h2
-rw-r--r--src/systemd/sd-bus.h4
-rw-r--r--src/systemd/sd-device.h1
-rw-r--r--src/systemd/sd-dhcp-client.h4
-rw-r--r--src/systemd/sd-dhcp6-client.h7
-rw-r--r--src/systemd/sd-event.h6
-rw-r--r--src/systemd/sd-id128.h4
-rw-r--r--src/systemd/sd-journal.h2
-rw-r--r--src/sysusers/sysusers.c2
-rw-r--r--src/test/test-alloc-util.c55
-rw-r--r--src/test/test-boot-timestamps.c51
-rw-r--r--src/test/test-clock.c96
-rw-r--r--src/test/test-conf-parser.c9
-rw-r--r--src/test/test-copy.c61
-rw-r--r--src/test/test-cpu-set-util.c143
-rw-r--r--src/test/test-daemon.c10
-rw-r--r--src/test/test-escape.c114
-rw-r--r--src/test/test-fd-util.c103
-rw-r--r--src/test/test-fileio.c133
-rw-r--r--src/test/test-fs-util.c91
-rw-r--r--src/test/test-fstab-util.c37
-rw-r--r--src/test/test-glob-util.c50
-rw-r--r--src/test/test-hexdecoct.c387
-rw-r--r--src/test/test-io-util.c69
-rw-r--r--src/test/test-ipcrm.c11
-rw-r--r--src/test/test-libudev.c267
-rw-r--r--src/test/test-loopback.c4
-rw-r--r--src/test/test-path-util.c46
-rw-r--r--src/test/test-proc-cmdline.c52
-rw-r--r--src/test/test-selinux.c122
-rw-r--r--src/test/test-signal-util.c18
-rw-r--r--src/test/test-sizeof.c53
-rw-r--r--src/test/test-stat-util.c68
-rw-r--r--src/test/test-string-util.c265
-rw-r--r--src/test/test-strv.c21
-rw-r--r--src/test/test-udev.c2
-rw-r--r--src/test/test-user-util.c27
-rw-r--r--src/test/test-util.c1441
-rw-r--r--src/test/test-web-util.c39
-rw-r--r--src/test/test-xattr-util.c69
-rw-r--r--src/timedate/timedated.c48
-rw-r--r--src/timesync/timesyncd.c2
-rw-r--r--src/tmpfiles/tmpfiles.c11
-rw-r--r--src/udev/udev.h1
-rw-r--r--src/udev/udevadm.c2
-rw-r--r--src/udev/udevd.c2
-rw-r--r--src/update-done/update-done.c2
-rw-r--r--src/user-sessions/user-sessions.c2
134 files changed, 3460 insertions, 2196 deletions
diff --git a/src/ask-password/ask-password.c b/src/ask-password/ask-password.c
index adc9286612..6d53dd982c 100644
--- a/src/ask-password/ask-password.c
+++ b/src/ask-password/ask-password.c
@@ -34,6 +34,7 @@ static const char *arg_keyname = NULL;
static char *arg_message = NULL;
static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC;
static bool arg_multiple = false;
+static bool arg_no_output = false;
static AskPasswordFlags arg_flags = ASK_PASSWORD_PUSH_CACHE;
static void help(void) {
@@ -48,6 +49,7 @@ static void help(void) {
" --no-tty Ask question via agent even on TTY\n"
" --accept-cached Accept cached passwords\n"
" --multiple List multiple passwords if available\n"
+ " --no-output Do not print password to standard output\n"
, program_invocation_short_name);
}
@@ -62,6 +64,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_MULTIPLE,
ARG_ID,
ARG_KEYNAME,
+ ARG_NO_OUTPUT,
};
static const struct option options[] = {
@@ -74,6 +77,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "multiple", no_argument, NULL, ARG_MULTIPLE },
{ "id", required_argument, NULL, ARG_ID },
{ "keyname", required_argument, NULL, ARG_KEYNAME },
+ { "no-output", no_argument, NULL, ARG_NO_OUTPUT },
{}
};
@@ -125,6 +129,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_keyname = optarg;
break;
+ case ARG_NO_OUTPUT:
+ arg_no_output = true;
+ break;
+
case '?':
return -EINVAL;
@@ -166,7 +174,8 @@ int main(int argc, char *argv[]) {
}
STRV_FOREACH(p, l) {
- puts(*p);
+ if (!arg_no_output)
+ puts(*p);
if (!arg_multiple)
break;
diff --git a/src/basic/c-rbtree.c b/src/basic/c-rbtree.c
index 914d7e5229..cf5a7242df 100644
--- a/src/basic/c-rbtree.c
+++ b/src/basic/c-rbtree.c
@@ -195,11 +195,6 @@ static inline void c_rbnode_set_parent_and_color(CRBNode *n, CRBNode *p, unsigne
n->__parent_and_color = (CRBNode*)((unsigned long)p | c);
}
-/* same as c_rbnode_set_parent_and_color(), but keeps the current parent */
-static inline void c_rbnode_set_color(CRBNode *n, unsigned long c) {
- c_rbnode_set_parent_and_color(n, c_rbnode_parent(n), c);
-}
-
/* same as c_rbnode_set_parent_and_color(), but keeps the current color */
static inline void c_rbnode_set_parent(CRBNode *n, CRBNode *p) {
c_rbnode_set_parent_and_color(n, p, c_rbnode_color(n));
diff --git a/src/basic/clock-util.c b/src/basic/clock-util.c
index 507e757ff0..7fe8d35ea5 100644
--- a/src/basic/clock-util.c
+++ b/src/basic/clock-util.c
@@ -69,9 +69,12 @@ int clock_set_hwclock(const struct tm *tm) {
return 0;
}
-int clock_is_localtime(void) {
+int clock_is_localtime(const char* adjtime_path) {
_cleanup_fclose_ FILE *f;
+ if (adjtime_path == NULL)
+ adjtime_path = "/etc/adjtime";
+
/*
* The third line of adjtime is "UTC" or "LOCAL" or nothing.
* # /etc/adjtime
@@ -79,7 +82,7 @@ int clock_is_localtime(void) {
* 0
* UTC
*/
- f = fopen("/etc/adjtime", "re");
+ f = fopen(adjtime_path, "re");
if (f) {
char line[LINE_MAX];
bool b;
@@ -88,7 +91,8 @@ int clock_is_localtime(void) {
fgets(line, sizeof(line), f) &&
fgets(line, sizeof(line), f);
if (!b)
- return -EIO;
+ /* less than three lines -> default to UTC */
+ return 0;
truncate_nl(line);
return streq(line, "LOCAL");
@@ -96,6 +100,7 @@ int clock_is_localtime(void) {
} else if (errno != ENOENT)
return -errno;
+ /* adjtime not present -> default to UTC */
return 0;
}
diff --git a/src/basic/clock-util.h b/src/basic/clock-util.h
index f471f2abcf..8830cd2f38 100644
--- a/src/basic/clock-util.h
+++ b/src/basic/clock-util.h
@@ -21,7 +21,7 @@
#include <time.h>
-int clock_is_localtime(void);
+int clock_is_localtime(const char* adjtime_path);
int clock_set_timezone(int *min);
int clock_reset_timewarp(void);
int clock_get_hwclock(struct tm *tm);
diff --git a/src/basic/copy.c b/src/basic/copy.c
index 519b412941..41dc8ca79a 100644
--- a/src/basic/copy.c
+++ b/src/basic/copy.c
@@ -40,17 +40,38 @@
#include "fs-util.h"
#include "io-util.h"
#include "macro.h"
+#include "missing.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
#include "umask-util.h"
#include "xattr-util.h"
-#define COPY_BUFFER_SIZE (16*1024)
+#define COPY_BUFFER_SIZE (16*1024u)
+
+static ssize_t try_copy_file_range(int fd_in, loff_t *off_in,
+ int fd_out, loff_t *off_out,
+ size_t len,
+ unsigned int flags) {
+ static int have = -1;
+ ssize_t r;
+
+ if (have == false)
+ return -ENOSYS;
+
+ r = copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
+ if (_unlikely_(have < 0))
+ have = r >= 0 || errno != ENOSYS;
+ if (r >= 0)
+ return r;
+ else
+ return -errno;
+}
int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
- bool try_sendfile = true, try_splice = true;
+ bool try_cfr = true, try_sendfile = true, try_splice = true;
int r;
+ size_t m = SSIZE_MAX; /* that the maximum that sendfile and c_f_r accept */
assert(fdf >= 0);
assert(fdt >= 0);
@@ -67,11 +88,9 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
}
for (;;) {
- size_t m = COPY_BUFFER_SIZE;
ssize_t n;
if (max_bytes != (uint64_t) -1) {
-
if (max_bytes <= 0)
return 1; /* return > 0 if we hit the max_bytes limit */
@@ -79,44 +98,59 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
m = (size_t) max_bytes;
}
+ /* First try copy_file_range(), unless we already tried */
+ if (try_cfr) {
+ n = try_copy_file_range(fdf, NULL, fdt, NULL, m, 0u);
+ if (n < 0) {
+ if (!IN_SET(n, -EINVAL, -ENOSYS, -EXDEV))
+ return n;
+
+ try_cfr = false;
+ /* use fallback below */
+ } else if (n == 0) /* EOF */
+ break;
+ else
+ /* Success! */
+ goto next;
+ }
+
/* First try sendfile(), unless we already tried */
if (try_sendfile) {
-
n = sendfile(fdt, fdf, NULL, m);
if (n < 0) {
- if (errno != EINVAL && errno != ENOSYS)
+ if (!IN_SET(errno, EINVAL, ENOSYS))
return -errno;
try_sendfile = false;
/* use fallback below */
} else if (n == 0) /* EOF */
break;
- else if (n > 0)
+ else
/* Success! */
goto next;
}
- /* The try splice, unless we already tried */
+ /* Then try splice, unless we already tried */
if (try_splice) {
n = splice(fdf, NULL, fdt, NULL, m, 0);
if (n < 0) {
- if (errno != EINVAL && errno != ENOSYS)
+ if (!IN_SET(errno, EINVAL, ENOSYS))
return -errno;
try_splice = false;
/* use fallback below */
} else if (n == 0) /* EOF */
break;
- else if (n > 0)
+ else
/* Success! */
goto next;
}
/* As a fallback just copy bits by hand */
{
- uint8_t buf[m];
+ uint8_t buf[MIN(m, COPY_BUFFER_SIZE)];
- n = read(fdf, buf, m);
+ n = read(fdf, buf, sizeof buf);
if (n < 0)
return -errno;
if (n == 0) /* EOF */
@@ -132,6 +166,11 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
assert(max_bytes >= (uint64_t) n);
max_bytes -= n;
}
+ /* sendfile accepts at most SSIZE_MAX-offset bytes to copy,
+ * so reduce our maximum by the amount we already copied,
+ * but don't go below our copy buffer size, unless we are
+ * close the the limit of bytes we are allowed to copy. */
+ m = MAX(MIN(COPY_BUFFER_SIZE, max_bytes), m - n);
}
return 0; /* return 0 if we hit EOF earlier than the size limit */
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index 2c454e8ea2..69590941e5 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -588,7 +588,7 @@ static int parse_env_file_push(
va_list aq, *ap = userdata;
if (!utf8_is_valid(key)) {
- _cleanup_free_ char *p;
+ _cleanup_free_ char *p = NULL;
p = utf8_escape_invalid(key);
log_error("%s:%u: invalid UTF-8 in key '%s', ignoring.", strna(filename), line, p);
@@ -596,7 +596,7 @@ static int parse_env_file_push(
}
if (value && !utf8_is_valid(value)) {
- _cleanup_free_ char *p;
+ _cleanup_free_ char *p = NULL;
p = utf8_escape_invalid(value);
log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename), line, key, p);
@@ -1069,7 +1069,7 @@ int fflush_and_check(FILE *f) {
/* This is much like like mkostemp() but is subject to umask(). */
int mkostemp_safe(char *pattern, int flags) {
- _cleanup_umask_ mode_t u;
+ _cleanup_umask_ mode_t u = 0;
int fd;
assert(pattern);
diff --git a/src/basic/formats-util.h b/src/basic/formats-util.h
index ce516b117d..9b4e8e98fa 100644
--- a/src/basic/formats-util.h
+++ b/src/basic/formats-util.h
@@ -49,7 +49,7 @@
#if SIZEOF_TIME_T == 8
# define PRI_TIME PRIi64
#elif SIZEOF_TIME_T == 4
-# define PRI_TIME PRIu32
+# define PRI_TIME "li"
#else
# error Unknown time_t size
#endif
diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c
index 6f1a049d47..85b8d812b3 100644
--- a/src/basic/hashmap.c
+++ b/src/basic/hashmap.c
@@ -176,7 +176,7 @@ enum HashmapType {
};
struct _packed_ indirect_storage {
- char *storage; /* where buckets and DIBs are stored */
+ void *storage; /* where buckets and DIBs are stored */
uint8_t hash_key[HASH_KEY_SIZE]; /* hash key; changes during resize */
unsigned n_entries; /* number of stored entries */
@@ -193,7 +193,7 @@ struct direct_storage {
/* This gives us 39 bytes on 64bit, or 35 bytes on 32bit.
* That's room for 4 set_entries + 4 DIB bytes + 3 unused bytes on 64bit,
* or 7 set_entries + 7 DIB bytes + 0 unused bytes on 32bit. */
- char storage[sizeof(struct indirect_storage)];
+ uint8_t storage[sizeof(struct indirect_storage)];
};
#define DIRECT_BUCKETS(entry_t) \
@@ -302,7 +302,7 @@ static void n_entries_dec(HashmapBase *h) {
h->n_direct_entries--;
}
-static char *storage_ptr(HashmapBase *h) {
+static void *storage_ptr(HashmapBase *h) {
return h->has_indirect ? h->indirect.storage
: h->direct.storage;
}
@@ -347,7 +347,7 @@ static void get_hash_key(uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok) {
static struct hashmap_base_entry *bucket_at(HashmapBase *h, unsigned idx) {
return (struct hashmap_base_entry*)
- (storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size);
+ ((uint8_t*) storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size);
}
static struct plain_hashmap_entry *plain_bucket_at(Hashmap *h, unsigned idx) {
@@ -381,7 +381,7 @@ static struct hashmap_base_entry *bucket_at_virtual(HashmapBase *h, struct swap_
static dib_raw_t *dib_raw_ptr(HashmapBase *h) {
return (dib_raw_t*)
- (storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h));
+ ((uint8_t*) storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h));
}
static unsigned bucket_distance(HashmapBase *h, unsigned idx, unsigned from) {
@@ -1028,7 +1028,7 @@ static int hashmap_base_put_boldly(HashmapBase *h, unsigned idx,
*/
static int resize_buckets(HashmapBase *h, unsigned entries_add) {
struct swap_entries swap;
- char *new_storage;
+ void *new_storage;
dib_raw_t *old_dibs, *new_dibs;
const struct hashmap_type_info *hi;
unsigned idx, optimal_idx;
@@ -1095,7 +1095,7 @@ static int resize_buckets(HashmapBase *h, unsigned entries_add) {
h->indirect.n_buckets = (1U << new_shift) /
(hi->entry_size + sizeof(dib_raw_t));
- old_dibs = (dib_raw_t*)(new_storage + hi->entry_size * old_n_buckets);
+ old_dibs = (dib_raw_t*)((uint8_t*) new_storage + hi->entry_size * old_n_buckets);
new_dibs = dib_raw_ptr(h);
/*
diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c
index 3cd2f2c872..5a7ee87a20 100644
--- a/src/basic/hostname-util.c
+++ b/src/basic/hostname-util.c
@@ -150,6 +150,8 @@ char* hostname_cleanup(char *s) {
assert(s);
+ strshorten(s, HOST_NAME_MAX);
+
for (p = s, d = s, dot = true; *p; p++) {
if (*p == '.') {
if (dot)
@@ -169,8 +171,6 @@ char* hostname_cleanup(char *s) {
else
*d = 0;
- strshorten(s, HOST_NAME_MAX);
-
return s;
}
diff --git a/src/basic/log.h b/src/basic/log.h
index f9fb1742a1..b6356228d9 100644
--- a/src/basic/log.h
+++ b/src/basic/log.h
@@ -246,5 +246,4 @@ int log_syntax_internal(
log_syntax_internal(unit, _level, config_file, config_line, 0, __FILE__, __LINE__, __func__, \
"String is not UTF-8 clean, ignoring assignment: %s", strna(_p)); \
} \
- -EINVAL; \
})
diff --git a/src/basic/macro.h b/src/basic/macro.h
index ddf0968d1b..e41aa4260f 100644
--- a/src/basic/macro.h
+++ b/src/basic/macro.h
@@ -23,10 +23,15 @@
#include <inttypes.h>
#include <stdbool.h>
#include <sys/param.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#define _printf_(a,b) __attribute__ ((format (printf, a, b)))
-#define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__)))
+#ifdef __clang__
+# define _alloc_(...)
+#else
+# define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__)))
+#endif
#define _sentinel_ __attribute__ ((sentinel))
#define _unused_ __attribute__ ((unused))
#define _destructor_ __attribute__ ((destructor))
@@ -361,6 +366,12 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
_found; \
})
+#define SWAP_TWO(x, y) do { \
+ typeof(x) _t = (x); \
+ (x) = (y); \
+ (y) = (_t); \
+ } while (false)
+
/* Define C11 thread_local attribute even on older gcc compiler
* version */
#ifndef thread_local
diff --git a/src/basic/missing.h b/src/basic/missing.h
index 417604aa64..034e334e66 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -135,84 +135,6 @@
#define SOL_SCTP 132
#endif
-#if !HAVE_DECL_PIVOT_ROOT
-static inline int pivot_root(const char *new_root, const char *put_old) {
- return syscall(SYS_pivot_root, new_root, put_old);
-}
-#endif
-
-#ifndef __NR_memfd_create
-# if defined __x86_64__
-# define __NR_memfd_create 319
-# elif defined __arm__
-# define __NR_memfd_create 385
-# elif defined __aarch64__
-# define __NR_memfd_create 279
-# elif defined __s390__
-# define __NR_memfd_create 350
-# elif defined _MIPS_SIM
-# if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __NR_memfd_create 4354
-# endif
-# if _MIPS_SIM == _MIPS_SIM_NABI32
-# define __NR_memfd_create 6318
-# endif
-# if _MIPS_SIM == _MIPS_SIM_ABI64
-# define __NR_memfd_create 5314
-# endif
-# elif defined __i386__
-# define __NR_memfd_create 356
-# else
-# warning "__NR_memfd_create unknown for your architecture"
-# define __NR_memfd_create 0xffffffff
-# endif
-#endif
-
-#if !HAVE_DECL_MEMFD_CREATE
-static inline int memfd_create(const char *name, unsigned int flags) {
- return syscall(__NR_memfd_create, name, flags);
-}
-#endif
-
-#ifndef __NR_getrandom
-# if defined __x86_64__
-# define __NR_getrandom 318
-# elif defined(__i386__)
-# define __NR_getrandom 355
-# elif defined(__arm__)
-# define __NR_getrandom 384
-# elif defined(__aarch64__)
-# define __NR_getrandom 278
-# elif defined(__ia64__)
-# define __NR_getrandom 1339
-# elif defined(__m68k__)
-# define __NR_getrandom 352
-# elif defined(__s390x__)
-# define __NR_getrandom 349
-# elif defined(__powerpc__)
-# define __NR_getrandom 359
-# elif defined _MIPS_SIM
-# if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __NR_getrandom 4353
-# endif
-# if _MIPS_SIM == _MIPS_SIM_NABI32
-# define __NR_getrandom 6317
-# endif
-# if _MIPS_SIM == _MIPS_SIM_ABI64
-# define __NR_getrandom 5313
-# endif
-# else
-# warning "__NR_getrandom unknown for your architecture"
-# define __NR_getrandom 0xffffffff
-# endif
-#endif
-
-#if !HAVE_DECL_GETRANDOM
-static inline int getrandom(void *buffer, size_t count, unsigned flags) {
- return syscall(__NR_getrandom, buffer, count, flags);
-}
-#endif
-
#ifndef GRND_NONBLOCK
#define GRND_NONBLOCK 0x0001
#endif
@@ -527,12 +449,6 @@ struct btrfs_ioctl_quota_ctl_args {
#define MS_PRIVATE (1 << 18)
#endif
-#if !HAVE_DECL_GETTID
-static inline pid_t gettid(void) {
- return (pid_t) syscall(SYS_gettid);
-}
-#endif
-
#ifndef SCM_SECURITY
#define SCM_SECURITY 0x03
#endif
@@ -561,32 +477,6 @@ static inline pid_t gettid(void) {
#define MAX_HANDLE_SZ 128
#endif
-#ifndef __NR_name_to_handle_at
-# if defined(__x86_64__)
-# define __NR_name_to_handle_at 303
-# elif defined(__i386__)
-# define __NR_name_to_handle_at 341
-# elif defined(__arm__)
-# define __NR_name_to_handle_at 370
-# elif defined(__powerpc__)
-# define __NR_name_to_handle_at 345
-# else
-# error "__NR_name_to_handle_at is not defined"
-# endif
-#endif
-
-#if !HAVE_DECL_NAME_TO_HANDLE_AT
-struct file_handle {
- unsigned int handle_bytes;
- int handle_type;
- unsigned char f_handle[0];
-};
-
-static inline int name_to_handle_at(int fd, const char *name, struct file_handle *handle, int *mnt_id, int flags) {
- return syscall(__NR_name_to_handle_at, fd, name, handle, mnt_id, flags);
-}
-#endif
-
#ifndef HAVE_SECURE_GETENV
# ifdef HAVE___SECURE_GETENV
# define secure_getenv __secure_getenv
@@ -635,22 +525,6 @@ static inline int name_to_handle_at(int fd, const char *name, struct file_handle
#endif
-#ifndef __NR_setns
-# if defined(__x86_64__)
-# define __NR_setns 308
-# elif defined(__i386__)
-# define __NR_setns 346
-# else
-# error "__NR_setns is not defined"
-# endif
-#endif
-
-#if !HAVE_DECL_SETNS
-static inline int setns(int fd, int nstype) {
- return syscall(__NR_setns, fd, nstype);
-}
-#endif
-
#if !HAVE_DECL_LO_FLAGS_PARTSCAN
#define LO_FLAGS_PARTSCAN 8
#endif
@@ -1018,69 +892,10 @@ static inline int setns(int fd, int nstype) {
#define CAP_AUDIT_READ 37
#endif
-static inline int raw_clone(unsigned long flags, void *child_stack) {
-#if defined(__s390__) || defined(__CRIS__)
- /* On s390 and cris the order of the first and second arguments
- * of the raw clone() system call is reversed. */
- return (int) syscall(__NR_clone, child_stack, flags);
-#else
- return (int) syscall(__NR_clone, flags, child_stack);
-#endif
-}
-
-static inline pid_t raw_getpid(void) {
-#if defined(__alpha__)
- return (pid_t) syscall(__NR_getxpid);
-#else
- return (pid_t) syscall(__NR_getpid);
-#endif
-}
-
-#if !HAVE_DECL_RENAMEAT2
-
-#ifndef __NR_renameat2
-# if defined __x86_64__
-# define __NR_renameat2 316
-# elif defined __arm__
-# define __NR_renameat2 382
-# elif defined _MIPS_SIM
-# if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __NR_renameat2 4351
-# endif
-# if _MIPS_SIM == _MIPS_SIM_NABI32
-# define __NR_renameat2 6315
-# endif
-# if _MIPS_SIM == _MIPS_SIM_ABI64
-# define __NR_renameat2 5311
-# endif
-# elif defined __i386__
-# define __NR_renameat2 353
-# else
-# warning "__NR_renameat2 unknown for your architecture"
-# define __NR_renameat2 0xffffffff
-# endif
-#endif
-
-static inline int renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) {
- return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags);
-}
-#endif
-
#ifndef RENAME_NOREPLACE
#define RENAME_NOREPLACE (1 << 0)
#endif
-#if !HAVE_DECL_KCMP
-static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) {
-#if defined(__NR_kcmp)
- return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-#endif
-
#ifndef KCMP_FILE
#define KCMP_FILE 0
#endif
@@ -1097,35 +912,6 @@ static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, uns
typedef int32_t key_serial_t;
#endif
-#if !HAVE_DECL_KEYCTL
-static inline long keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4,unsigned long arg5) {
-#if defined(__NR_keyctl)
- return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-static inline key_serial_t add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) {
-#if defined (__NR_add_key)
- return syscall(__NR_add_key, type, description, payload, plen, ringid);
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-static inline key_serial_t request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) {
-#if defined (__NR_request_key)
- return syscall(__NR_request_key, type, description, callout_info, destringid);
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-#endif
-
#ifndef KEYCTL_READ
#define KEYCTL_READ 11
#endif
@@ -1177,3 +963,5 @@ static inline key_serial_t request_key(const char *type, const char *description
#endif
#endif
+
+#include "missing_syscall.h"
diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h
new file mode 100644
index 0000000000..d502d3b9ca
--- /dev/null
+++ b/src/basic/missing_syscall.h
@@ -0,0 +1,310 @@
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+ Copyright 2016 Zbigniew Jędrzejewski-Szmek
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+/* Missing glibc definitions to access certain kernel APIs */
+
+#if !HAVE_DECL_PIVOT_ROOT
+static inline int pivot_root(const char *new_root, const char *put_old) {
+ return syscall(SYS_pivot_root, new_root, put_old);
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_MEMFD_CREATE
+# ifndef __NR_memfd_create
+# if defined __x86_64__
+# define __NR_memfd_create 319
+# elif defined __arm__
+# define __NR_memfd_create 385
+# elif defined __aarch64__
+# define __NR_memfd_create 279
+# elif defined __s390__
+# define __NR_memfd_create 350
+# elif defined _MIPS_SIM
+# if _MIPS_SIM == _MIPS_SIM_ABI32
+# define __NR_memfd_create 4354
+# endif
+# if _MIPS_SIM == _MIPS_SIM_NABI32
+# define __NR_memfd_create 6318
+# endif
+# if _MIPS_SIM == _MIPS_SIM_ABI64
+# define __NR_memfd_create 5314
+# endif
+# elif defined __i386__
+# define __NR_memfd_create 356
+# else
+# warning "__NR_memfd_create unknown for your architecture"
+# endif
+# endif
+
+static inline int memfd_create(const char *name, unsigned int flags) {
+# ifdef __NR_memfd_create
+ return syscall(__NR_memfd_create, name, flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_GETRANDOM
+# ifndef __NR_getrandom
+# if defined __x86_64__
+# define __NR_getrandom 318
+# elif defined(__i386__)
+# define __NR_getrandom 355
+# elif defined(__arm__)
+# define __NR_getrandom 384
+# elif defined(__aarch64__)
+# define __NR_getrandom 278
+# elif defined(__ia64__)
+# define __NR_getrandom 1339
+# elif defined(__m68k__)
+# define __NR_getrandom 352
+# elif defined(__s390x__)
+# define __NR_getrandom 349
+# elif defined(__powerpc__)
+# define __NR_getrandom 359
+# elif defined _MIPS_SIM
+# if _MIPS_SIM == _MIPS_SIM_ABI32
+# define __NR_getrandom 4353
+# endif
+# if _MIPS_SIM == _MIPS_SIM_NABI32
+# define __NR_getrandom 6317
+# endif
+# if _MIPS_SIM == _MIPS_SIM_ABI64
+# define __NR_getrandom 5313
+# endif
+# else
+# warning "__NR_getrandom unknown for your architecture"
+# endif
+# endif
+
+static inline int getrandom(void *buffer, size_t count, unsigned flags) {
+# ifdef __NR_getrandom
+ return syscall(__NR_getrandom, buffer, count, flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_GETTID
+static inline pid_t gettid(void) {
+ return (pid_t) syscall(SYS_gettid);
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_NAME_TO_HANDLE_AT
+# ifndef __NR_name_to_handle_at
+# if defined(__x86_64__)
+# define __NR_name_to_handle_at 303
+# elif defined(__i386__)
+# define __NR_name_to_handle_at 341
+# elif defined(__arm__)
+# define __NR_name_to_handle_at 370
+# elif defined(__powerpc__)
+# define __NR_name_to_handle_at 345
+# else
+# error "__NR_name_to_handle_at is not defined"
+# endif
+# endif
+
+struct file_handle {
+ unsigned int handle_bytes;
+ int handle_type;
+ unsigned char f_handle[0];
+};
+
+static inline int name_to_handle_at(int fd, const char *name, struct file_handle *handle, int *mnt_id, int flags) {
+# ifdef __NR_name_to_handle_at
+ return syscall(__NR_name_to_handle_at, fd, name, handle, mnt_id, flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_SETNS
+# ifndef __NR_setns
+# if defined(__x86_64__)
+# define __NR_setns 308
+# elif defined(__i386__)
+# define __NR_setns 346
+# else
+# error "__NR_setns is not defined"
+# endif
+# endif
+
+static inline int setns(int fd, int nstype) {
+# ifdef __NR_setns
+ return syscall(__NR_setns, fd, nstype);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+static inline int raw_clone(unsigned long flags, void *child_stack) {
+#if defined(__s390__) || defined(__CRIS__)
+ /* On s390 and cris the order of the first and second arguments
+ * of the raw clone() system call is reversed. */
+ return (int) syscall(__NR_clone, child_stack, flags);
+#else
+ return (int) syscall(__NR_clone, flags, child_stack);
+#endif
+}
+
+/* ======================================================================= */
+
+static inline pid_t raw_getpid(void) {
+#if defined(__alpha__)
+ return (pid_t) syscall(__NR_getxpid);
+#else
+ return (pid_t) syscall(__NR_getpid);
+#endif
+}
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_RENAMEAT2
+# ifndef __NR_renameat2
+# if defined __x86_64__
+# define __NR_renameat2 316
+# elif defined __arm__
+# define __NR_renameat2 382
+# elif defined _MIPS_SIM
+# if _MIPS_SIM == _MIPS_SIM_ABI32
+# define __NR_renameat2 4351
+# endif
+# if _MIPS_SIM == _MIPS_SIM_NABI32
+# define __NR_renameat2 6315
+# endif
+# if _MIPS_SIM == _MIPS_SIM_ABI64
+# define __NR_renameat2 5311
+# endif
+# elif defined __i386__
+# define __NR_renameat2 353
+# else
+# warning "__NR_renameat2 unknown for your architecture"
+# endif
+# endif
+
+static inline int renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) {
+# ifdef __NR_renameat2
+ return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_KCMP
+static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) {
+# ifdef __NR_kcmp
+ return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_KEYCTL
+static inline long keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4,unsigned long arg5) {
+# ifdef __NR_keyctl
+ return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+
+static inline key_serial_t add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) {
+# ifdef __NR_add_key
+ return syscall(__NR_add_key, type, description, payload, plen, ringid);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+
+static inline key_serial_t request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) {
+# ifdef __NR_request_key
+ return syscall(__NR_request_key, type, description, callout_info, destringid);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_DECL_COPY_FILE_RANGE
+# ifndef __NR_copy_file_range
+# if defined(__x86_64__)
+# define __NR_copy_file_range 326
+# elif defined(__i386__)
+# define __NR_copy_file_range 377
+# elif defined __s390__
+# define __NR_copy_file_range 375
+# elif defined __arm__
+# define __NR_copy_file_range 391
+# elif defined __aarch64__
+# define __NR_copy_file_range 285
+# else
+# warning "__NR_copy_file_range not defined for your architecture"
+# endif
+# endif
+
+static inline ssize_t copy_file_range(int fd_in, loff_t *off_in,
+ int fd_out, loff_t *off_out,
+ size_t len,
+ unsigned int flags) {
+# ifdef __NR_copy_file_range
+ return syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+#endif
diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c
index 33f2ee96d8..5faa2eba05 100644
--- a/src/basic/mount-util.c
+++ b/src/basic/mount-util.c
@@ -47,7 +47,7 @@ static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id
if ((flags & AT_EMPTY_PATH) && isempty(filename))
xsprintf(path, "/proc/self/fdinfo/%i", fd);
else {
- subfd = openat(fd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
+ subfd = openat(fd, filename, O_CLOEXEC|O_PATH);
if (subfd < 0)
return -errno;
@@ -230,7 +230,7 @@ int path_is_mount_point(const char *t, int flags) {
if (!parent)
return -ENOMEM;
- fd = openat(AT_FDCWD, parent, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_PATH);
+ fd = openat(AT_FDCWD, parent, O_DIRECTORY|O_CLOEXEC|O_PATH);
if (fd < 0)
return -errno;
diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c
index 6c63b9d652..10c2f39369 100644
--- a/src/basic/selinux-util.c
+++ b/src/basic/selinux-util.c
@@ -80,31 +80,23 @@ void mac_selinux_retest(void) {
#endif
}
-int mac_selinux_init(const char *prefix) {
+int mac_selinux_init(void) {
int r = 0;
#ifdef HAVE_SELINUX
usec_t before_timestamp, after_timestamp;
struct mallinfo before_mallinfo, after_mallinfo;
- if (!mac_selinux_use())
+ if (label_hnd)
return 0;
- if (label_hnd)
+ if (!mac_selinux_use())
return 0;
before_mallinfo = mallinfo();
before_timestamp = now(CLOCK_MONOTONIC);
- if (prefix) {
- struct selinux_opt options[] = {
- { .type = SELABEL_OPT_SUBSET, .value = prefix },
- };
-
- label_hnd = selabel_open(SELABEL_CTX_FILE, options, ELEMENTSOF(options));
- } else
- label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
-
+ label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
if (!label_hnd) {
log_enforcing("Failed to initialize SELinux context: %m");
r = security_getenforce() == 1 ? -errno : 0;
@@ -160,7 +152,7 @@ int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
return 0;
if (r >= 0) {
- r = lsetfilecon(path, fcon);
+ r = lsetfilecon_raw(path, fcon);
/* If the FS doesn't support labels, then exit without warning */
if (r < 0 && errno == EOPNOTSUPP)
@@ -225,7 +217,7 @@ int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
return -errno;
sclass = string_to_security_class("process");
- r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label);
+ r = security_compute_create_raw(mycon, fcon, sclass, (security_context_t *) label);
if (r < 0)
return -errno;
#endif
@@ -270,7 +262,7 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
if (r < 0)
return -errno;
- r = getpeercon(socket_fd, &peercon);
+ r = getpeercon_raw(socket_fd, &peercon);
if (r < 0)
return -errno;
@@ -304,7 +296,7 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
return -ENOMEM;
sclass = string_to_security_class("process");
- r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label);
+ r = security_compute_create_raw(mycon, fcon, sclass, (security_context_t *) label);
if (r < 0)
return -errno;
#endif
@@ -358,7 +350,7 @@ int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
log_enforcing("Failed to determine SELinux security context for %s: %m", path);
} else {
- if (setfscreatecon(filecon) >= 0)
+ if (setfscreatecon_raw(filecon) >= 0)
return 0; /* Success! */
log_enforcing("Failed to set SELinux security context %s for %s: %m", filecon, path);
@@ -379,7 +371,7 @@ void mac_selinux_create_file_clear(void) {
if (!mac_selinux_use())
return;
- setfscreatecon(NULL);
+ setfscreatecon_raw(NULL);
#endif
}
@@ -410,7 +402,7 @@ void mac_selinux_create_socket_clear(void) {
if (!mac_selinux_use())
return;
- setsockcreatecon(NULL);
+ setsockcreatecon_raw(NULL);
#endif
}
@@ -469,7 +461,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
return -errno;
} else {
- if (setfscreatecon(fcon) < 0) {
+ if (setfscreatecon_raw(fcon) < 0) {
log_enforcing("Failed to set SELinux security context %s for %s: %m", fcon, path);
if (security_getenforce() > 0)
return -errno;
@@ -480,7 +472,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
r = bind(fd, addr, addrlen) < 0 ? -errno : 0;
if (context_changed)
- setfscreatecon(NULL);
+ setfscreatecon_raw(NULL);
return r;
diff --git a/src/basic/selinux-util.h b/src/basic/selinux-util.h
index 27e8edb41b..ce6bc8e44c 100644
--- a/src/basic/selinux-util.h
+++ b/src/basic/selinux-util.h
@@ -29,7 +29,7 @@ bool mac_selinux_use(void);
bool mac_selinux_have(void);
void mac_selinux_retest(void);
-int mac_selinux_init(const char *prefix);
+int mac_selinux_init(void);
void mac_selinux_finish(void);
int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
diff --git a/src/basic/set.h b/src/basic/set.h
index 2bff5062da..e0d9dd001c 100644
--- a/src/basic/set.h
+++ b/src/basic/set.h
@@ -126,6 +126,9 @@ int set_put_strdupv(Set *s, char **l);
#define SET_FOREACH(e, s, i) \
for ((i) = ITERATOR_FIRST; set_iterate((s), &(i), (void**)&(e)); )
+#define SET_FOREACH_MOVE(e, d, s) \
+ for (; ({ e = set_first(s); assert_se(!e || set_move_one(d, s, e) >= 0); e; }); )
+
DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free);
diff --git a/src/basic/socket-label.c b/src/basic/socket-label.c
index 35e9573aa4..6d1dc83874 100644
--- a/src/basic/socket-label.c
+++ b/src/basic/socket-label.c
@@ -23,7 +23,6 @@
#include <stddef.h>
#include <string.h>
#include <sys/socket.h>
-#include <sys/stat.h>
#include <sys/un.h>
#include <unistd.h>
@@ -35,6 +34,7 @@
#include "mkdir.h"
#include "selinux-util.h"
#include "socket-util.h"
+#include "umask-util.h"
int socket_address_listen(
const SocketAddress *a,
@@ -112,28 +112,24 @@ int socket_address_listen(
return -errno;
if (socket_address_family(a) == AF_UNIX && a->sockaddr.un.sun_path[0] != 0) {
- mode_t old_mask;
-
/* Create parents */
- mkdir_parents_label(a->sockaddr.un.sun_path, directory_mode);
+ (void) mkdir_parents_label(a->sockaddr.un.sun_path, directory_mode);
/* Enforce the right access mode for the socket */
- old_mask = umask(~ socket_mode);
-
- r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size);
-
- if (r < 0 && errno == EADDRINUSE) {
- /* Unlink and try again */
- unlink(a->sockaddr.un.sun_path);
- r = bind(fd, &a->sockaddr.sa, a->size);
+ RUN_WITH_UMASK(~socket_mode) {
+ r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size);
+ if (r == -EADDRINUSE) {
+ /* Unlink and try again */
+ unlink(a->sockaddr.un.sun_path);
+ if (bind(fd, &a->sockaddr.sa, a->size) < 0)
+ return -errno;
+ } else if (r < 0)
+ return r;
}
-
- umask(old_mask);
- } else
- r = bind(fd, &a->sockaddr.sa, a->size);
-
- if (r < 0)
- return -errno;
+ } else {
+ if (bind(fd, &a->sockaddr.sa, a->size) < 0)
+ return -errno;
+ }
if (socket_address_can_accept(a))
if (listen(fd, backlog) < 0)
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
index 7ca764abeb..c16460a198 100644
--- a/src/basic/time-util.c
+++ b/src/basic/time-util.c
@@ -47,12 +47,15 @@ static clockid_t map_clock_id(clockid_t c) {
/* Some more exotic archs (s390, ppc, …) lack the "ALARM" flavour of the clocks. Thus, clock_gettime() will
* fail for them. Since they are essentially the same as their non-ALARM pendants (their only difference is
* when timers are set on them), let's just map them accordingly. This way, we can get the correct time even on
- * those archs. */
+ * those archs.
+ *
+ * Also, older kernels don't support CLOCK_BOOTTIME: fall back to CLOCK_MONOTONIC. */
switch (c) {
+ case CLOCK_BOOTTIME:
case CLOCK_BOOTTIME_ALARM:
- return CLOCK_BOOTTIME;
+ return clock_boottime_or_monotonic ();
case CLOCK_REALTIME_ALARM:
return CLOCK_REALTIME;
diff --git a/src/basic/util.h b/src/basic/util.h
index e095254b57..286db05159 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -36,6 +36,7 @@
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/statfs.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
diff --git a/src/basic/xattr-util.c b/src/basic/xattr-util.c
index 8d7f14f382..8256899eda 100644
--- a/src/basic/xattr-util.c
+++ b/src/basic/xattr-util.c
@@ -110,7 +110,7 @@ ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute,
/* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */
- fd = openat(dirfd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
+ fd = openat(dirfd, filename, O_CLOEXEC|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
if (fd < 0)
return -errno;
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index f939196397..00372b92b4 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -139,7 +139,7 @@ static int property_get_tainted(
if (access("/proc/cgroups", F_OK) < 0)
e = stpcpy(e, "cgroups-missing:");
- if (clock_is_localtime() > 0)
+ if (clock_is_localtime(NULL) > 0)
e = stpcpy(e, "local-hwclock:");
/* remove the last ':' */
diff --git a/src/core/device.c b/src/core/device.c
index d201dc5e4b..28e4039da2 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -318,7 +318,7 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
* the GC to have garbaged it. That's desired since the device
* unit may have a dependency on the mount unit which was
* added during the loading of the later. */
- if (u && DEVICE(u)->state == DEVICE_PLUGGED) {
+ if (dev && u && DEVICE(u)->state == DEVICE_PLUGGED) {
/* This unit is in plugged state: we're sure it's
* attached to a device. */
if (!path_equal(DEVICE(u)->sysfs, sysfs)) {
diff --git a/src/core/execute.c b/src/core/execute.c
index 0c311ec330..ac2ac39892 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1882,7 +1882,7 @@ static int exec_child(
* also to the context secure_bits so that we don't try to
* drop the bit away next. */
- secure_bits |= 1<<SECURE_KEEP_CAPS;
+ secure_bits |= 1<<SECURE_KEEP_CAPS;
}
}
diff --git a/src/core/failure-action.c b/src/core/failure-action.c
index 39f5519ca1..bb2bc3f399 100644
--- a/src/core/failure-action.c
+++ b/src/core/failure-action.c
@@ -62,7 +62,8 @@ int failure_action(
log_and_status(m, "Rebooting as result of failure.");
update_reboot_param_file(reboot_arg);
- (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE, NULL);
+ (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET,
+ JOB_REPLACE_IRREVERSIBLY, NULL);
break;
@@ -89,7 +90,8 @@ int failure_action(
case FAILURE_ACTION_POWEROFF:
log_and_status(m, "Powering off as result of failure.");
- (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE, NULL);
+ (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET,
+ JOB_REPLACE_IRREVERSIBLY, NULL);
break;
case FAILURE_ACTION_POWEROFF_FORCE:
diff --git a/src/core/job.c b/src/core/job.c
index 012cf72d1f..719cb0a3e5 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -690,17 +690,20 @@ _pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobR
}
static void job_print_status_message(Unit *u, JobType t, JobResult result) {
- static const char* const job_result_status_table[_JOB_RESULT_MAX] = {
- [JOB_DONE] = ANSI_GREEN " OK " ANSI_NORMAL,
- [JOB_TIMEOUT] = ANSI_HIGHLIGHT_RED " TIME " ANSI_NORMAL,
- [JOB_FAILED] = ANSI_HIGHLIGHT_RED "FAILED" ANSI_NORMAL,
- [JOB_DEPENDENCY] = ANSI_HIGHLIGHT_YELLOW "DEPEND" ANSI_NORMAL,
- [JOB_SKIPPED] = ANSI_HIGHLIGHT " INFO " ANSI_NORMAL,
- [JOB_ASSERT] = ANSI_HIGHLIGHT_YELLOW "ASSERT" ANSI_NORMAL,
- [JOB_UNSUPPORTED] = ANSI_HIGHLIGHT_YELLOW "UNSUPP" ANSI_NORMAL,
+ static struct {
+ const char *color, *word;
+ } const statuses[_JOB_RESULT_MAX] = {
+ [JOB_DONE] = {ANSI_GREEN, " OK "},
+ [JOB_TIMEOUT] = {ANSI_HIGHLIGHT_RED, " TIME "},
+ [JOB_FAILED] = {ANSI_HIGHLIGHT_RED, "FAILED"},
+ [JOB_DEPENDENCY] = {ANSI_HIGHLIGHT_YELLOW, "DEPEND"},
+ [JOB_SKIPPED] = {ANSI_HIGHLIGHT, " INFO "},
+ [JOB_ASSERT] = {ANSI_HIGHLIGHT_YELLOW, "ASSERT"},
+ [JOB_UNSUPPORTED] = {ANSI_HIGHLIGHT_YELLOW, "UNSUPP"},
};
const char *format;
+ const char *status;
assert(u);
assert(t >= 0);
@@ -714,11 +717,16 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) {
if (!format)
return;
+ if (log_get_show_color())
+ status = strjoina(statuses[result].color, statuses[result].word, ANSI_NORMAL);
+ else
+ status = statuses[result].word;
+
if (result != JOB_DONE)
manager_flip_auto_status(u->manager, true);
DISABLE_WARNING_FORMAT_NONLITERAL;
- unit_status_printf(u, job_result_status_table[result], format);
+ unit_status_printf(u, status, format);
REENABLE_WARNING;
if (t == JOB_START && result == JOB_FAILED) {
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index e1bfdccbca..d078924c5b 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -3507,7 +3507,19 @@ static int merge_by_names(Unit **u, Set *names, const char *id) {
* ours? Then let's try it the other way
* round */
- other = manager_get_unit((*u)->manager, k);
+ /* If the symlink name we are looking at is unit template, then
+ we must search for instance of this template */
+ if (unit_name_is_valid(k, UNIT_NAME_TEMPLATE)) {
+ _cleanup_free_ char *instance = NULL;
+
+ r = unit_name_replace_instance(k, (*u)->instance, &instance);
+ if (r < 0)
+ return r;
+
+ other = manager_get_unit((*u)->manager, instance);
+ } else
+ other = manager_get_unit((*u)->manager, k);
+
free(k);
if (other) {
diff --git a/src/core/main.c b/src/core/main.c
index b4e96fd6f4..78701805ea 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1218,10 +1218,15 @@ static int status_welcome(void) {
if (r < 0 && r != -ENOENT)
log_warning_errno(r, "Failed to read os-release file: %m");
- return status_printf(NULL, false, false,
- "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
- isempty(ansi_color) ? "1" : ansi_color,
- isempty(pretty_name) ? "Linux" : pretty_name);
+ if (log_get_show_color())
+ return status_printf(NULL, false, false,
+ "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
+ isempty(ansi_color) ? "1" : ansi_color,
+ isempty(pretty_name) ? "Linux" : pretty_name);
+ else
+ return status_printf(NULL, false, false,
+ "\nWelcome to %s!\n",
+ isempty(pretty_name) ? "Linux" : pretty_name);
}
static int write_container_id(void) {
@@ -1369,13 +1374,13 @@ int main(int argc, char *argv[]) {
dual_timestamp_get(&security_finish_timestamp);
}
- if (mac_selinux_init(NULL) < 0) {
+ if (mac_selinux_init() < 0) {
error_message = "Failed to initialize SELinux policy";
goto finish;
}
if (!skip_setup) {
- if (clock_is_localtime() > 0) {
+ if (clock_is_localtime(NULL) > 0) {
int min;
/*
@@ -1435,9 +1440,7 @@ int main(int argc, char *argv[]) {
/* clear the kernel timestamp,
* because we are in a container */
- kernel_timestamp.monotonic = 0ULL;
- kernel_timestamp.realtime = 0ULL;
-
+ kernel_timestamp = DUAL_TIMESTAMP_NULL;
} else {
/* Running as user instance */
arg_running_as = MANAGER_USER;
diff --git a/src/core/mount.c b/src/core/mount.c
index 93d2bd595c..0fd880df5d 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -104,6 +104,14 @@ static bool mount_is_auto(const MountParameters *p) {
return !fstab_test_option(p->options, "noauto\0");
}
+static bool mount_is_automount(const MountParameters *p) {
+ assert(p);
+
+ return fstab_test_option(p->options,
+ "comment=systemd.automount\0"
+ "x-systemd.automount\0");
+}
+
static bool needs_quota(const MountParameters *p) {
assert(p);
@@ -328,7 +336,8 @@ static int mount_add_device_links(Mount *m) {
if (path_equal(m->where, "/"))
return 0;
- if (mount_is_auto(p) && UNIT(m)->manager->running_as == MANAGER_SYSTEM)
+ if (mount_is_auto(p) && !mount_is_automount(p) &&
+ UNIT(m)->manager->running_as == MANAGER_SYSTEM)
device_wants_mount = true;
r = unit_add_node_link(UNIT(m), p->what, device_wants_mount, m->from_fragment ? UNIT_BINDS_TO : UNIT_REQUIRES);
@@ -369,7 +378,8 @@ static bool should_umount(Mount *m) {
MountParameters *p;
if (path_equal(m->where, "/") ||
- path_equal(m->where, "/usr"))
+ path_equal(m->where, "/usr") ||
+ path_startswith(m->where, "/run/initramfs"))
return false;
p = get_mount_parameters(m);
@@ -393,13 +403,15 @@ static int mount_add_default_dependencies(Mount *m) {
if (UNIT(m)->manager->running_as != MANAGER_SYSTEM)
return 0;
- /* We do not add any default dependencies to / and /usr, since
- * they are guaranteed to stay mounted the whole time, since
- * our system is on it. Also, don't bother with anything
- * mounted below virtual file systems, it's also going to be
- * virtual, and hence not worth the effort. */
+ /* We do not add any default dependencies to /, /usr or
+ * /run/initramfs/, since they are guaranteed to stay
+ * mounted the whole time, since our system is on it.
+ * Also, don't bother with anything mounted below virtual
+ * file systems, it's also going to be virtual, and hence
+ * not worth the effort. */
if (path_equal(m->where, "/") ||
path_equal(m->where, "/usr") ||
+ path_startswith(m->where, "/run/initramfs") ||
path_startswith(m->where, "/proc") ||
path_startswith(m->where, "/sys") ||
path_startswith(m->where, "/dev"))
diff --git a/src/core/selinux-setup.c b/src/core/selinux-setup.c
index 9a115a4387..4072df58e6 100644
--- a/src/core/selinux-setup.c
+++ b/src/core/selinux-setup.c
@@ -88,7 +88,7 @@ int mac_selinux_setup(bool *loaded_policy) {
log_open();
log_error("Failed to compute init label, ignoring.");
} else {
- r = setcon(label);
+ r = setcon_raw(label);
log_open();
if (r < 0)
diff --git a/src/core/smack-setup.c b/src/core/smack-setup.c
index 0c26e85460..5a6d11cfa1 100644
--- a/src/core/smack-setup.c
+++ b/src/core/smack-setup.c
@@ -261,7 +261,7 @@ static int write_netlabel_rules(const char* srcdir) {
}
}
- return r;
+ return r;
}
#endif
diff --git a/src/core/transaction.c b/src/core/transaction.c
index b28fc76785..c894001cf9 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -391,6 +391,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
if (delete) {
+ const char *status;
/* logging for j not k here here to provide consistent narrative */
log_unit_warning(j->unit,
"Breaking ordering cycle by deleting job %s/%s",
@@ -399,7 +400,13 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
"Job %s/%s deleted to break ordering cycle starting with %s/%s",
delete->unit->id, job_type_to_string(delete->type),
j->unit->id, job_type_to_string(j->type));
- unit_status_printf(delete->unit, ANSI_HIGHLIGHT_RED " SKIP " ANSI_NORMAL,
+
+ if (log_get_show_color())
+ status = ANSI_HIGHLIGHT_RED " SKIP " ANSI_NORMAL;
+ else
+ status = " SKIP ";
+
+ unit_status_printf(delete->unit, status,
"Ordering cycle found, skipping %s");
transaction_delete_unit(tr, delete->unit);
return -EAGAIN;
diff --git a/src/core/umount.c b/src/core/umount.c
index b953fcc152..c21a2be54e 100644
--- a/src/core/umount.c
+++ b/src/core/umount.c
@@ -412,6 +412,7 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
#ifndef HAVE_SPLIT_USR
|| path_equal(m->path, "/usr")
#endif
+ || path_startswith(m->path, "/run/initramfs")
)
continue;
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index 7790ab865d..435e3805c4 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -245,7 +245,7 @@ static int process_locale(void) {
int r;
etc_localeconf = prefix_roota(arg_root, "/etc/locale.conf");
- if (faccessat(AT_FDCWD, etc_localeconf, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (laccess(etc_localeconf, F_OK) >= 0)
return 0;
if (arg_copy_locale && arg_root) {
@@ -319,7 +319,7 @@ static int process_timezone(void) {
int r;
etc_localtime = prefix_roota(arg_root, "/etc/localtime");
- if (faccessat(AT_FDCWD, etc_localtime, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (laccess(etc_localtime, F_OK) >= 0)
return 0;
if (arg_copy_timezone && arg_root) {
@@ -399,7 +399,7 @@ static int process_hostname(void) {
int r;
etc_hostname = prefix_roota(arg_root, "/etc/hostname");
- if (faccessat(AT_FDCWD, etc_hostname, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (laccess(etc_hostname, F_OK) >= 0)
return 0;
r = prompt_hostname();
@@ -424,7 +424,7 @@ static int process_machine_id(void) {
int r;
etc_machine_id = prefix_roota(arg_root, "/etc/machine-id");
- if (faccessat(AT_FDCWD, etc_machine_id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (laccess(etc_machine_id, F_OK) >= 0)
return 0;
if (sd_id128_equal(arg_machine_id, SD_ID128_NULL))
@@ -450,7 +450,7 @@ static int prompt_root_password(void) {
return 0;
etc_shadow = prefix_roota(arg_root, "/etc/shadow");
- if (faccessat(AT_FDCWD, etc_shadow, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (laccess(etc_shadow, F_OK) >= 0)
return 0;
print_welcome();
@@ -533,7 +533,7 @@ static int process_root_password(void) {
int r;
etc_shadow = prefix_roota(arg_root, "/etc/shadow");
- if (faccessat(AT_FDCWD, etc_shadow, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (laccess(etc_shadow, F_OK) >= 0)
return 0;
mkdir_parents(etc_shadow, 0755);
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 97a48764ae..6f576b5ecf 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -336,8 +336,8 @@ static int add_mount(
if (r < 0)
return log_error_errno(r, "Failed to write unit file %s: %m", unit);
- if (!noauto) {
- lnk = strjoin(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL);
+ if (!noauto && !automount) {
+ lnk = strjoin(arg_dest, "/", post, nofail ? ".wants/" : ".requires/", name, NULL);
if (!lnk)
return log_oom();
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index c37e32e96b..d11756e615 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -706,7 +706,7 @@ int main(int argc, char *argv[]) {
log_open();
umask(0022);
- mac_selinux_init("/etc");
+ mac_selinux_init();
if (argc != 1) {
log_error("This program takes no arguments.");
diff --git a/src/journal/compress.c b/src/journal/compress.c
index 1933b87b00..c43849c46a 100644
--- a/src/journal/compress.c
+++ b/src/journal/compress.c
@@ -17,6 +17,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
@@ -498,7 +499,7 @@ int compress_stream_lz4(int fdf, int fdt, uint64_t max_bytes) {
total_out += n;
if (max_bytes != (uint64_t) -1 && total_out > (size_t) max_bytes) {
- log_debug("Compressed stream longer than %zd bytes", max_bytes);
+ log_debug("Compressed stream longer than %"PRIu64" bytes", max_bytes);
return -EFBIG;
}
@@ -649,7 +650,7 @@ int decompress_stream_lz4(int in, int out, uint64_t max_bytes) {
total_out += produced;
if (max_bytes != (uint64_t) -1 && total_out > (size_t) max_bytes) {
- log_debug("Decompressed stream longer than %zd bytes", max_bytes);
+ log_debug("Decompressed stream longer than %"PRIu64" bytes", max_bytes);
r = -EFBIG;
goto cleanup;
}
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
index ac75e39312..3c21d4129e 100644
--- a/src/journal/sd-journal.c
+++ b/src/journal/sd-journal.c
@@ -19,6 +19,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <inttypes.h>
#include <linux/magic.h>
#include <poll.h>
#include <stddef.h>
@@ -1957,7 +1958,7 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **
&f->compress_buffer, &f->compress_buffer_size,
field, field_length, '=');
if (r < 0)
- log_debug_errno(r, "Cannot decompress %s object of length %zu at offset "OFSfmt": %m",
+ log_debug_errno(r, "Cannot decompress %s object of length %"PRIu64" at offset "OFSfmt": %m",
object_compressed_to_string(compression), l, p);
else if (r > 0) {
diff --git a/src/journal/test-compress-benchmark.c b/src/journal/test-compress-benchmark.c
index 5b2d130cd6..0ef6d36a50 100644
--- a/src/journal/test-compress-benchmark.c
+++ b/src/journal/test-compress-benchmark.c
@@ -105,6 +105,8 @@ static void test_compress_decompress(const char* label, const char* type,
int r;
size = permute(i);
+ if (size == 0)
+ continue;
log_debug("%s %zu %zu", type, i, size);
diff --git a/src/libsystemd-network/dhcp-identifier.c b/src/libsystemd-network/dhcp-identifier.c
index 1d9ec7be82..1bef368852 100644
--- a/src/libsystemd-network/dhcp-identifier.c
+++ b/src/libsystemd-network/dhcp-identifier.c
@@ -43,7 +43,7 @@ int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
if (r < 0)
return r;
- unaligned_write_be16(&duid->type, DHCP6_DUID_EN);
+ unaligned_write_be16(&duid->type, DHCP_DUID_TYPE_EN);
unaligned_write_be32(&duid->en.pen, SYSTEMD_PEN);
*len = sizeof(duid->type) + sizeof(duid->en);
diff --git a/src/libsystemd-network/dhcp-identifier.h b/src/libsystemd-network/dhcp-identifier.h
index 93f06f5938..cb953cb416 100644
--- a/src/libsystemd-network/dhcp-identifier.h
+++ b/src/libsystemd-network/dhcp-identifier.h
@@ -25,13 +25,23 @@
#include "sparse-endian.h"
#include "unaligned.h"
+typedef enum DHCPDUIDType {
+ DHCP_DUID_TYPE_RAW = 0,
+ DHCP_DUID_TYPE_LLT = 1,
+ DHCP_DUID_TYPE_EN = 2,
+ DHCP_DUID_TYPE_LL = 3,
+ DHCP_DUID_TYPE_UUID = 4,
+ _DHCP_DUID_TYPE_MAX,
+ _DHCP_DUID_TYPE_INVALID = -1,
+} DHCPDUIDType;
+
/* RFC 3315 section 9.1:
* A DUID can be no more than 128 octets long (not including the type code).
*/
#define MAX_DUID_LEN 128
struct duid {
- uint16_t type;
+ be16_t type;
union {
struct {
/* DHCP6_DUID_LLT */
@@ -61,3 +71,32 @@ struct duid {
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len);
int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id);
+
+static inline int dhcp_validate_duid_len(be16_t duid_type, size_t duid_len) {
+ struct duid d;
+
+ assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL);
+
+ switch (be16toh(duid_type)) {
+ case DHCP_DUID_TYPE_LLT:
+ if (duid_len <= sizeof(d.llt))
+ return -EINVAL;
+ break;
+ case DHCP_DUID_TYPE_EN:
+ if (duid_len != sizeof(d.en))
+ return -EINVAL;
+ break;
+ case DHCP_DUID_TYPE_LL:
+ if (duid_len <= sizeof(d.ll))
+ return -EINVAL;
+ break;
+ case DHCP_DUID_TYPE_UUID:
+ if (duid_len != sizeof(d.uuid))
+ return -EINVAL;
+ break;
+ default:
+ /* accept unknown type in order to be forward compatible */
+ break;
+ }
+ return 0;
+}
diff --git a/src/libsystemd-network/dhcp6-protocol.h b/src/libsystemd-network/dhcp6-protocol.h
index ee4bdfb07f..2487c470ab 100644
--- a/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -62,13 +62,6 @@ enum {
#define DHCP6_REB_TIMEOUT 10 * USEC_PER_SEC
#define DHCP6_REB_MAX_RT 600 * USEC_PER_SEC
-enum {
- DHCP6_DUID_LLT = 1,
- DHCP6_DUID_EN = 2,
- DHCP6_DUID_LL = 3,
- DHCP6_DUID_UUID = 4,
-};
-
enum DHCP6State {
DHCP6_STATE_STOPPED = 0,
DHCP6_STATE_INFORMATION_REQUEST = 1,
diff --git a/src/libsystemd-network/lldp-neighbor.c b/src/libsystemd-network/lldp-neighbor.c
index c61941cd70..190c9baece 100644
--- a/src/libsystemd-network/lldp-neighbor.c
+++ b/src/libsystemd-network/lldp-neighbor.c
@@ -446,7 +446,7 @@ static int format_mac_address(const void *data, size_t sz, char **ret) {
static int format_network_address(const void *data, size_t sz, char **ret) {
union in_addr_union a;
- int family;
+ int family, r;
if (sz == 6 && ((uint8_t*) data)[1] == 1) {
memcpy(&a.in, (uint8_t*) data + 2, sizeof(a.in));
@@ -457,7 +457,10 @@ static int format_network_address(const void *data, size_t sz, char **ret) {
} else
return 0;
- return in_addr_to_string(family, &a, ret);
+ r = in_addr_to_string(family, &a, ret);
+ if (r < 0)
+ return r;
+ return 1;
}
_public_ int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, const char **ret) {
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index cb7252bbeb..7c21f42591 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -335,6 +335,34 @@ int config_parse_hwaddr(const char *unit,
return 0;
}
+int config_parse_iaid_value(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ uint32_t iaid_value;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if ((r = safe_atou32(rvalue, &iaid_value)) < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Unable to read IAID: %s", rvalue);
+ return r;
+ }
+
+ *((be32_t *)data) = htobe32(iaid_value);
+
+ return 0;
+}
+
void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
unsigned i;
diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h
index c8a531ab0f..d8b551e8ce 100644
--- a/src/libsystemd-network/network-internal.h
+++ b/src/libsystemd-network/network-internal.h
@@ -62,6 +62,10 @@ int config_parse_ifalias(const char *unit, const char *filename, unsigned line,
const char *section, unsigned section_line, const char *lvalue,
int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_iaid_value(const char *unit, const char *filename, unsigned line,
+ const char *section, unsigned section_line, const char *lvalue,
+ int ltype, const char *rvalue, void *data, void *userdata);
+
int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result);
const char *net_get_name(struct udev_device *device);
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index d484c37a73..b108e35386 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -82,7 +82,7 @@ struct sd_dhcp_client {
} _packed_ ll;
struct {
/* 255: Node-specific (RFC 4361) */
- uint32_t iaid;
+ be32_t iaid;
struct duid duid;
} _packed_ ns;
struct {
@@ -298,6 +298,51 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
return 0;
}
+int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, be32_t iaid,
+ size_t duid_len, struct duid *duid) {
+ DHCP_CLIENT_DONT_DESTROY(client);
+ int r;
+ assert_return(client, -EINVAL);
+ zero(client->client_id);
+
+ client->client_id.type = 255;
+
+ /* If IAID is not configured, generate it. */
+ if (iaid == 0) {
+ r = dhcp_identifier_set_iaid(client->index, client->mac_addr,
+ client->mac_addr_len,
+ &client->client_id.ns.iaid);
+ if (r < 0)
+ return r;
+ } else
+ client->client_id.ns.iaid = iaid;
+
+ /* If DUID is not configured, generate DUID-EN. */
+ if (duid_len == 0) {
+ r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid,
+ &duid_len);
+ if (r < 0)
+ return r;
+ } else {
+ r = dhcp_validate_duid_len(client->client_id.type,
+ duid_len - sizeof(client->client_id.type));
+ if (r < 0)
+ return r;
+ memcpy(&client->client_id.ns.duid, duid, duid_len);
+ }
+
+ client->client_id_len = sizeof(client->client_id.type) + duid_len +
+ sizeof(client->client_id.ns.iaid);
+
+ if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
+ log_dhcp_client(client, "Configured IAID+DUID, restarting.");
+ client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
+ sd_dhcp_client_start(client);
+ }
+
+ return 0;
+}
+
int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
const char *hostname) {
char *new_hostname = NULL;
@@ -408,7 +453,7 @@ static void client_stop(sd_dhcp_client *client, int error) {
static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
uint8_t type, size_t *_optlen, size_t *_optoffset) {
- _cleanup_free_ DHCPPacket *packet;
+ _cleanup_free_ DHCPPacket *packet = NULL;
size_t optlen, optoffset, size;
be16_t max_size;
usec_t time_now;
@@ -469,7 +514,6 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
if (client->arp_type == ARPHRD_ETHER)
memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN);
- /* If no client identifier exists, construct an RFC 4361-compliant one */
if (client->client_id_len == 0) {
size_t duid_len;
diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c
index 7a119fd488..ef50ed17a1 100644
--- a/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/libsystemd-network/sd-dhcp-lease.c
@@ -825,7 +825,7 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
r = sd_dhcp_lease_get_client_id(lease, &client_id, &client_id_len);
if (r >= 0) {
- _cleanup_free_ char *client_id_hex;
+ _cleanup_free_ char *client_id_hex = NULL;
client_id_hex = hexmem(client_id, client_id_len);
if (!client_id_hex) {
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index af4709d788..7cecba120c 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -180,41 +180,30 @@ static int client_ensure_duid(sd_dhcp6_client *client) {
return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
}
-int sd_dhcp6_client_set_duid(
- sd_dhcp6_client *client,
- uint16_t type,
- uint8_t *duid, size_t duid_len) {
+int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, size_t duid_len,
+ struct duid *duid) {
+ int r;
assert_return(client, -EINVAL);
- assert_return(duid, -EINVAL);
- assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL);
-
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
- switch (type) {
- case DHCP6_DUID_LLT:
- if (duid_len <= sizeof(client->duid.llt))
- return -EINVAL;
- break;
- case DHCP6_DUID_EN:
- if (duid_len != sizeof(client->duid.en))
- return -EINVAL;
- break;
- case DHCP6_DUID_LL:
- if (duid_len <= sizeof(client->duid.ll))
- return -EINVAL;
- break;
- case DHCP6_DUID_UUID:
- if (duid_len != sizeof(client->duid.uuid))
- return -EINVAL;
- break;
- default:
- /* accept unknown type in order to be forward compatible */
- break;
+ if (duid_len > 0) {
+ r = dhcp_validate_duid_len(duid->type,
+ duid_len - sizeof(duid->type));
+ if (r < 0)
+ return r;
+
+ memcpy(&client->duid, duid, duid_len);
+ client->duid_len = duid_len;
}
- client->duid.type = htobe16(type);
- memcpy(&client->duid.raw.data, duid, duid_len);
- client->duid_len = duid_len + sizeof(client->duid.type);
+ return 0;
+}
+
+int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, be32_t iaid) {
+ assert_return(client, -EINVAL);
+ assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
+
+ client->ia_na.id = iaid;
return 0;
}
diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c
index d0743cf3e2..9d4587c80e 100644
--- a/src/libsystemd-network/sd-lldp.c
+++ b/src/libsystemd-network/sd-lldp.c
@@ -112,6 +112,8 @@ static bool lldp_keep_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
return true;
}
+static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor);
+
static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
_cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *old = NULL;
bool keep;
@@ -136,7 +138,7 @@ static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
if (lldp_neighbor_equal(n, old)) {
/* Is this equal, then restart the TTL counter, but don't do anyting else. */
- lldp_neighbor_start_ttl(old);
+ lldp_start_timer(lldp, old);
lldp_callback(lldp, SD_LLDP_EVENT_REFRESHED, old);
return 0;
}
@@ -162,7 +164,7 @@ static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
n->lldp = lldp;
- lldp_neighbor_start_ttl(n);
+ lldp_start_timer(lldp, n);
lldp_callback(lldp, old ? SD_LLDP_EVENT_UPDATED : SD_LLDP_EVENT_ADDED, n);
return 1;
@@ -368,8 +370,6 @@ static int neighbor_compare_func(const void *a, const void *b) {
return lldp_neighbor_id_hash_ops.compare(&(*x)->id, &(*y)->id);
}
-static int lldp_start_timer(sd_lldp *lldp);
-
static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) {
sd_lldp *lldp = userdata;
int r, q;
@@ -378,19 +378,22 @@ static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) {
if (r < 0)
return log_lldp_errno(r, "Failed to make space: %m");
- q = lldp_start_timer(lldp);
+ q = lldp_start_timer(lldp, NULL);
if (q < 0)
return log_lldp_errno(q, "Failed to restart timer: %m");
return 0;
}
-static int lldp_start_timer(sd_lldp *lldp) {
+static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor) {
sd_lldp_neighbor *n;
int r;
assert(lldp);
+ if (neighbor)
+ lldp_neighbor_start_ttl(neighbor);
+
n = prioq_peek(lldp->neighbor_by_expiry);
if (!n) {
@@ -440,7 +443,7 @@ _public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) {
if (!l)
return -ENOMEM;
- r = lldp_start_timer(lldp);
+ r = lldp_start_timer(lldp, NULL);
if (r < 0) {
free(l);
return r;
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
index 542c37e41b..b8958ec7bb 100644
--- a/src/libsystemd/sd-bus/bus-message.c
+++ b/src/libsystemd/sd-bus/bus-message.c
@@ -1131,10 +1131,7 @@ _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
assert_return(!m->sealed, -EPERM);
assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
- if (b)
- m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
- else
- m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
+ SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
return 0;
}
@@ -1143,10 +1140,7 @@ _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
- if (b)
- m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
- else
- m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
+ SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
return 0;
}
@@ -1155,10 +1149,7 @@ _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
- if (b)
- m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
- else
- m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
+ SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
return 0;
}
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index cc15afeb1c..862f26aad7 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -313,10 +313,7 @@ _public_ int sd_bus_negotiate_creds(sd_bus *bus, int b, uint64_t mask) {
assert_return(!IN_SET(bus->state, BUS_CLOSING, BUS_CLOSED), -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
- if (b)
- bus->creds_mask |= mask;
- else
- bus->creds_mask &= ~mask;
+ SET_FLAG(bus->creds_mask, mask, b);
/* The well knowns we need unconditionally, so that matches can work */
bus->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c
index 3924300817..f56798674c 100644
--- a/src/libsystemd/sd-netlink/netlink-message.c
+++ b/src/libsystemd/sd-netlink/netlink-message.c
@@ -107,10 +107,7 @@ int sd_netlink_message_request_dump(sd_netlink_message *m, int dump) {
m->hdr->nlmsg_type == RTM_GETNEIGH,
-EINVAL);
- if (dump)
- m->hdr->nlmsg_flags |= NLM_F_DUMP;
- else
- m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
+ SET_FLAG(m->hdr->nlmsg_flags, NLM_F_DUMP, dump);
return 0;
}
diff --git a/src/libsystemd/sd-path/sd-path.c b/src/libsystemd/sd-path/sd-path.c
index 480f1ad065..b7aec1f20a 100644
--- a/src/libsystemd/sd-path/sd-path.c
+++ b/src/libsystemd/sd-path/sd-path.c
@@ -89,7 +89,8 @@ static int from_home_dir(const char *envname, const char *suffix, char **buffer,
static int from_user_dir(const char *field, char **buffer, const char **ret) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *b = NULL;
- const char *fn = NULL;
+ _cleanup_free_ const char *fn = NULL;
+ const char *c = NULL;
char line[LINE_MAX];
size_t n;
int r;
@@ -98,10 +99,14 @@ static int from_user_dir(const char *field, char **buffer, const char **ret) {
assert(buffer);
assert(ret);
- r = from_home_dir(NULL, ".config/user-dirs.dirs", &b, &fn);
+ r = from_home_dir("XDG_CONFIG_HOME", ".config", &b, &c);
if (r < 0)
return r;
+ fn = strappend(c, "/user-dirs.dirs");
+ if (!fn)
+ return -ENOMEM;
+
f = fopen(fn, "re");
if (!f) {
if (errno == ENOENT)
diff --git a/src/libudev/libudev.h b/src/libudev/libudev.h
index eb58740d26..3f6d0ed16c 100644
--- a/src/libudev/libudev.h
+++ b/src/libudev/libudev.h
@@ -21,6 +21,7 @@
#define _LIBUDEV_H_
#include <stdarg.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#ifdef __cplusplus
diff --git a/src/locale/localed.c b/src/locale/localed.c
index cc86c61edb..46405ca68a 100644
--- a/src/locale/localed.c
+++ b/src/locale/localed.c
@@ -1296,7 +1296,7 @@ int main(int argc, char *argv[]) {
log_open();
umask(0022);
- mac_selinux_init("/etc");
+ mac_selinux_init();
if (argc != 1) {
log_error("This program takes no arguments.");
diff --git a/src/login/70-uaccess.rules b/src/login/70-uaccess.rules
index 694df2cfc8..ff3e68e961 100644
--- a/src/login/70-uaccess.rules
+++ b/src/login/70-uaccess.rules
@@ -42,8 +42,9 @@ SUBSYSTEM=="firewire", ATTR{units}=="*0x00b09d:0x00010*", TAG+="uaccess"
SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x010001*", TAG+="uaccess"
SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x014001*", TAG+="uaccess"
-# DRI video devices
+# DRI and frame buffer video devices
SUBSYSTEM=="drm", KERNEL=="card*|renderD*", TAG+="uaccess"
+SUBSYSTEM=="graphics", KERNEL=="fb*", TAG+="uaccess"
# KVM
SUBSYSTEM=="misc", KERNEL=="kvm", TAG+="uaccess"
diff --git a/src/login/logind.c b/src/login/logind.c
index 933602eb08..d5f6757bd3 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -1126,7 +1126,7 @@ int main(int argc, char *argv[]) {
goto finish;
}
- r = mac_selinux_init("/run");
+ r = mac_selinux_init();
if (r < 0) {
log_error_errno(r, "Could not initialize labelling: %m");
goto finish;
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index 0679114f74..6ec7a911ca 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -45,6 +45,7 @@
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
+#include "strxcpyx.h"
#include "terminal-util.h"
#include "util.h"
#include "verbs.h"
@@ -147,7 +148,6 @@ static int link_info_compare(const void *a, const void *b) {
}
static int decode_link(sd_netlink_message *m, LinkInfo *info) {
- static const struct ether_addr null_address = {};
const char *name;
uint16_t type;
int r;
@@ -174,11 +174,11 @@ static int decode_link(sd_netlink_message *m, LinkInfo *info) {
if (r < 0)
return r;
- strncpy(info->name, name, sizeof(info->name));
+ strscpy(info->name, sizeof info->name, name);
info->has_mac_address =
sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &info->mac_address) >= 0 &&
- memcmp(&info->mac_address, &null_address, sizeof(struct ether_addr)) != 0;
+ memcmp(&info->mac_address, &ETHER_ADDR_NULL, sizeof(struct ether_addr)) != 0;
info->has_mtu =
sd_netlink_message_read_u32(m, IFLA_MTU, &info->mtu) &&
diff --git a/src/network/networkd-conf.c b/src/network/networkd-conf.c
new file mode 100644
index 0000000000..4bc92b8171
--- /dev/null
+++ b/src/network/networkd-conf.c
@@ -0,0 +1,133 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Tom Gundersen <teg@jklm.no>
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+ ***/
+
+#include <ctype.h>
+
+#include "conf-parser.h"
+#include "def.h"
+#include "dhcp-identifier.h"
+#include "networkd-conf.h"
+#include "string-table.h"
+
+int manager_parse_config_file(Manager *m) {
+ assert(m);
+
+ return config_parse_many(PKGSYSCONFDIR "/networkd.conf",
+ CONF_PATHS_NULSTR("systemd/networkd.conf.d"),
+ "DUID\0",
+ config_item_perf_lookup, networkd_gperf_lookup,
+ false, m);
+}
+
+static const char* const dhcp_duid_type_table[_DHCP_DUID_TYPE_MAX] = {
+ [DHCP_DUID_TYPE_RAW] = "raw",
+ [DHCP_DUID_TYPE_LLT] = "link-layer-time",
+ [DHCP_DUID_TYPE_EN] = "vendor",
+ [DHCP_DUID_TYPE_LL] = "link-layer",
+ [DHCP_DUID_TYPE_UUID] = "uuid"
+};
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_duid_type, DHCPDUIDType);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_duid_type, dhcp_duid_type, DHCPDUIDType, "Failed to parse DHCP DUID type");
+
+int config_parse_dhcp_duid_raw(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ int r;
+ long byte;
+ char *cbyte, *pnext;
+ const char *pduid = (const char *)rvalue;
+ size_t count = 0, duid_len = 0;
+ Manager *m = userdata;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(m);
+ assert(m->dhcp_duid_type != _DHCP_DUID_TYPE_INVALID);
+
+ switch (m->dhcp_duid_type) {
+ case DHCP_DUID_TYPE_LLT:
+ /* RawData contains DUID-LLT link-layer address (offset 6) */
+ duid_len = 6;
+ break;
+ case DHCP_DUID_TYPE_EN:
+ /* RawData contains DUID-EN identifier (offset 4) */
+ duid_len = 4;
+ break;
+ case DHCP_DUID_TYPE_LL:
+ /* RawData contains DUID-LL link-layer address (offset 2) */
+ duid_len = 2;
+ break;
+ case DHCP_DUID_TYPE_UUID:
+ /* RawData specifies UUID (offset 0) - fall thru */
+ case DHCP_DUID_TYPE_RAW:
+ /* First two bytes of RawData is DUID Type - fall thru */
+ default:
+ break;
+ }
+
+ if (m->dhcp_duid_type != DHCP_DUID_TYPE_RAW)
+ m->dhcp_duid.type = htobe16(m->dhcp_duid_type);
+
+ /* RawData contains DUID in format " NN:NN:NN... " */
+ while (true) {
+ r = extract_first_word(&pduid, &cbyte, ":", 0);
+ if (r < 0) {
+ log_error("Failed to read DUID.");
+ return -EINVAL;
+ }
+ if (r == 0)
+ break;
+ if (duid_len >= MAX_DUID_LEN) {
+ log_error("DUID length exceeds maximum length.");
+ return -EINVAL;
+ }
+
+ errno = 0;
+ byte = strtol(cbyte, &pnext, 16);
+ if ((errno == ERANGE && (byte == LONG_MAX || byte == LONG_MIN))
+ || (errno != 0 && byte == 0) || (cbyte == pnext)) {
+ log_error("Invalid DUID byte: %s.", cbyte);
+ return -EINVAL;
+ }
+
+ /* If DHCP_DUID_TYPE_RAW, first two bytes holds DUID Type */
+ if ((m->dhcp_duid_type == DHCP_DUID_TYPE_RAW) && (count < 2)) {
+ m->dhcp_duid.type |= (byte << (8 * count));
+ count++;
+ continue;
+ }
+
+ m->dhcp_duid.raw.data[duid_len++] = byte;
+ }
+
+ m->dhcp_duid_len = sizeof(m->dhcp_duid.type) + duid_len;
+
+ return 0;
+}
diff --git a/src/network/networkd-conf.h b/src/network/networkd-conf.h
new file mode 100644
index 0000000000..6d9ce010e3
--- /dev/null
+++ b/src/network/networkd-conf.h
@@ -0,0 +1,32 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Tom Gundersen <teg@jklm.no>
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "networkd.h"
+
+
+int manager_parse_config_file(Manager *m);
+
+const struct ConfigPerfItem* networkd_gperf_lookup(const char *key, unsigned length);
+
+int config_parse_dhcp_duid_type(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_dhcp_duid_raw(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index 68998eabf2..3bbb21295c 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -625,7 +625,13 @@ int dhcp4_configure(Link *link) {
switch (link->network->dhcp_client_identifier) {
case DHCP_CLIENT_ID_DUID:
- /* Library defaults to this. */
+ /* If configured, apply user specified DUID and/or IAID */
+ r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
+ link->network->iaid_value,
+ link->manager->dhcp_duid_len,
+ &link->manager->dhcp_duid);
+ if (r < 0)
+ return r;
break;
case DHCP_CLIENT_ID_MAC:
r = sd_dhcp_client_set_client_id(link->dhcp_client,
diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index 5f7a005c36..9f59cb3f8a 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -230,6 +230,16 @@ int dhcp6_configure(Link *link) {
if (r < 0)
goto error;
+ r = sd_dhcp6_client_set_iaid(client, link->network->iaid_value);
+ if (r < 0)
+ goto error;
+
+ r = sd_dhcp6_client_set_duid(client,
+ link->manager->dhcp_duid_len,
+ &link->manager->dhcp_duid);
+ if (r < 0)
+ goto error;
+
r = sd_dhcp6_client_set_index(client, link->ifindex);
if (r < 0)
goto error;
diff --git a/src/network/networkd-gperf.gperf b/src/network/networkd-gperf.gperf
new file mode 100644
index 0000000000..3ef4155476
--- /dev/null
+++ b/src/network/networkd-gperf.gperf
@@ -0,0 +1,18 @@
+%{
+#include <stddef.h>
+#include "conf-parser.h"
+#include "networkd-conf.h"
+%}
+struct ConfigPerfItem;
+%null_strings
+%language=ANSI-C
+%define slot-name section_and_lvalue
+%define hash-function-name networkd_gperf_hash
+%define lookup-function-name networkd_gperf_lookup
+%readonly-tables
+%omit-struct-type
+%struct-type
+%includes
+%%
+DUID.Type, config_parse_dhcp_duid_type, 0, offsetof(Manager, dhcp_duid_type)
+DUID.RawData, config_parse_dhcp_duid_raw, 0, offsetof(Manager, dhcp_duid)
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index ff4bd76554..67b04560cd 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -2781,6 +2781,13 @@ int link_update(Link *link, sd_netlink_message *m) {
ARPHRD_ETHER);
if (r < 0)
return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m");
+
+ r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
+ link->network->iaid_value,
+ link->manager->dhcp_duid_len,
+ &link->manager->dhcp_duid);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not update DUID/IAID in DHCP client: %m");
}
if (link->dhcp6_client) {
@@ -2790,6 +2797,17 @@ int link_update(Link *link, sd_netlink_message *m) {
ARPHRD_ETHER);
if (r < 0)
return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m");
+
+ r = sd_dhcp6_client_set_iaid(link->dhcp6_client,
+ link->network->iaid_value);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not update DHCPv6 IAID: %m");
+
+ r = sd_dhcp6_client_set_duid(link->dhcp6_client,
+ link->manager->dhcp_duid_len,
+ &link->manager->dhcp_duid);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not update DHCPv6 DUID: %m");
}
}
}
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index b8cb7f875d..8d443f7b0f 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -1037,6 +1037,8 @@ int manager_new(Manager **ret) {
if (r < 0)
return r;
+ m->dhcp_duid_type = _DHCP_DUID_TYPE_INVALID;
+
*ret = m;
m = NULL;
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index a5d1714293..7a9a136d5b 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -26,6 +26,7 @@ Match.KernelCommandLine, config_parse_net_condition,
Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, match_arch)
Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac)
Link.MTUBytes, config_parse_iec_size, 0, offsetof(Network, mtu)
+Link.IAIDValue, config_parse_iaid_value, 0, offsetof(Network, iaid_value)
Network.Description, config_parse_string, 0, offsetof(Network, description)
Network.Bridge, config_parse_netdev, 0, offsetof(Network, bridge)
Network.Bond, config_parse_netdev, 0, offsetof(Network, bond)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index f175788977..491b9a3efa 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -629,10 +629,7 @@ int config_parse_ipv4ll(
* config_parse_address_family_boolean(), except that it
* applies only to IPv4 */
- if (parse_boolean(rvalue))
- *link_local |= ADDRESS_FAMILY_IPV4;
- else
- *link_local &= ~ADDRESS_FAMILY_IPV4;
+ SET_FLAG(*link_local, ADDRESS_FAMILY_IPV4, parse_boolean(rvalue));
return 0;
}
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 4a13e2b574..c5530cdfba 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -30,6 +30,7 @@ typedef struct Network Network;
#include "networkd-route.h"
#include "networkd-util.h"
#include "networkd.h"
+#include "sparse-endian.h"
#define DHCP_ROUTE_METRIC 1024
#define IPV4LL_ROUTE_METRIC 2048
@@ -144,6 +145,7 @@ struct Network {
struct ether_addr *mac;
unsigned mtu;
+ be32_t iaid_value;
LLDPMode lldp_mode; /* LLDP reception */
bool lldp_emit; /* LLDP transmission */
diff --git a/src/network/networkd.c b/src/network/networkd.c
index 3a2615e6fd..c8f81a2ca6 100644
--- a/src/network/networkd.c
+++ b/src/network/networkd.c
@@ -21,6 +21,7 @@
#include "capability-util.h"
#include "networkd.h"
+#include "networkd-conf.h"
#include "signal-util.h"
#include "user-util.h"
@@ -89,6 +90,10 @@ int main(int argc, char *argv[]) {
goto out;
}
+ r = manager_parse_config_file(m);
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse configuration file: %m");
+
r = manager_load_config(m);
if (r < 0) {
log_error_errno(r, "Could not load configuration files: %m");
diff --git a/src/network/networkd.h b/src/network/networkd.h
index 6bdd8302a0..d815f30610 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -35,6 +35,7 @@ typedef struct Manager Manager;
#include "networkd-link.h"
#include "networkd-network.h"
#include "networkd-util.h"
+#include "dhcp-identifier.h"
struct Manager {
sd_netlink *rtnl;
@@ -61,6 +62,10 @@ struct Manager {
LIST_HEAD(AddressPool, address_pools);
usec_t network_dirs_ts_usec;
+
+ DHCPDUIDType dhcp_duid_type;
+ size_t dhcp_duid_len;
+ struct duid dhcp_duid;
};
extern const char* const network_dirs[];
diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c
index 1db5ba7116..9f9a4759d1 100644
--- a/src/nspawn/nspawn-cgroup.c
+++ b/src/nspawn/nspawn-cgroup.c
@@ -73,7 +73,7 @@ int sync_cgroup(pid_t pid, bool unified_requested) {
unified = cg_unified();
if (unified < 0)
- return log_error_errno(unified, "Failed to determine whether the unified hierachy is used: %m");
+ return log_error_errno(unified, "Failed to determine whether the unified hierarchy is used: %m");
if ((unified > 0) == unified_requested)
return 0;
@@ -135,7 +135,7 @@ int create_subcgroup(pid_t pid, bool unified_requested) {
unified = cg_unified();
if (unified < 0)
- return log_error_errno(unified, "Failed to determine whether the unified hierachy is used: %m");
+ return log_error_errno(unified, "Failed to determine whether the unified hierarchy is used: %m");
if (unified == 0)
return 0;
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 4851c439c9..eb89916b7e 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -87,6 +87,7 @@
#ifdef HAVE_SECCOMP
#include "seccomp-util.h"
#endif
+#include "selinux-util.h"
#include "signal-util.h"
#include "socket-util.h"
#include "stat-util.h"
@@ -976,6 +977,13 @@ static int verify_arguments(void) {
return -EINVAL;
}
+#ifndef HAVE_LIBIPTC
+ if (arg_expose_ports) {
+ log_error("--port= is not supported, compiled without libiptc support.");
+ return -EOPNOTSUPP;
+ }
+#endif
+
if (arg_start_mode == START_BOOT && arg_kill_signal <= 0)
arg_kill_signal = SIGRTMIN+3;
@@ -3284,6 +3292,12 @@ int main(int argc, char *argv[]) {
goto finish;
}
+ if (arg_selinux_apifs_context) {
+ r = mac_selinux_apply(console, arg_selinux_apifs_context);
+ if (r < 0)
+ goto finish;
+ }
+
if (unlockpt(master) < 0) {
r = log_error_errno(errno, "Failed to unlock tty: %m");
goto finish;
diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c
index 484fbb4d92..009cc73aec 100644
--- a/src/resolve/resolve-tool.c
+++ b/src/resolve/resolve-tool.c
@@ -1280,40 +1280,28 @@ static int parse_argv(int argc, char *argv[]) {
r = parse_boolean(optarg);
if (r < 0)
return log_error_errno(r, "Failed to parse --cname= argument.");
- if (r == 0)
- arg_flags |= SD_RESOLVED_NO_CNAME;
- else
- arg_flags &= ~SD_RESOLVED_NO_CNAME;
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_CNAME, r == 0);
break;
case ARG_SERVICE_ADDRESS:
r = parse_boolean(optarg);
if (r < 0)
return log_error_errno(r, "Failed to parse --service-address= argument.");
- if (r == 0)
- arg_flags |= SD_RESOLVED_NO_ADDRESS;
- else
- arg_flags &= ~SD_RESOLVED_NO_ADDRESS;
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_ADDRESS, r == 0);
break;
case ARG_SERVICE_TXT:
r = parse_boolean(optarg);
if (r < 0)
return log_error_errno(r, "Failed to parse --service-txt= argument.");
- if (r == 0)
- arg_flags |= SD_RESOLVED_NO_TXT;
- else
- arg_flags &= ~SD_RESOLVED_NO_TXT;
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_TXT, r == 0);
break;
case ARG_SEARCH:
r = parse_boolean(optarg);
if (r < 0)
return log_error_errno(r, "Failed to parse --search argument.");
- if (r == 0)
- arg_flags |= SD_RESOLVED_NO_SEARCH;
- else
- arg_flags &= ~SD_RESOLVED_NO_SEARCH;
+ SET_FLAG(arg_flags, SD_RESOLVED_NO_SEARCH, r == 0);
break;
case ARG_STATISTICS:
diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c
index a46674f6fe..706f8c14ed 100644
--- a/src/resolve/resolved-dns-query.c
+++ b/src/resolve/resolved-dns-query.c
@@ -62,6 +62,7 @@ static void dns_query_candidate_stop(DnsQueryCandidate *c) {
while ((t = set_steal_first(c->transactions))) {
set_remove(t->notify_query_candidates, c);
+ set_remove(t->notify_query_candidates_done, c);
dns_transaction_gc(t);
}
}
@@ -139,6 +140,10 @@ static int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResource
if (r < 0)
goto gc;
+ r = set_ensure_allocated(&t->notify_query_candidates_done, NULL);
+ if (r < 0)
+ goto gc;
+
r = set_put(t->notify_query_candidates, c);
if (r < 0)
goto gc;
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index 57f9455131..a5129c201e 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -52,6 +52,7 @@ static void dns_transaction_flush_dnssec_transactions(DnsTransaction *t) {
while ((z = set_steal_first(t->dnssec_transactions))) {
set_remove(z->notify_transactions, t);
+ set_remove(z->notify_transactions_done, t);
dns_transaction_gc(z);
}
}
@@ -100,14 +101,26 @@ DnsTransaction* dns_transaction_free(DnsTransaction *t) {
set_remove(c->transactions, t);
set_free(t->notify_query_candidates);
+ while ((c = set_steal_first(t->notify_query_candidates_done)))
+ set_remove(c->transactions, t);
+ set_free(t->notify_query_candidates_done);
+
while ((i = set_steal_first(t->notify_zone_items)))
i->probe_transaction = NULL;
set_free(t->notify_zone_items);
+ while ((i = set_steal_first(t->notify_zone_items_done)))
+ i->probe_transaction = NULL;
+ set_free(t->notify_zone_items_done);
+
while ((z = set_steal_first(t->notify_transactions)))
set_remove(z->dnssec_transactions, t);
set_free(t->notify_transactions);
+ while ((z = set_steal_first(t->notify_transactions_done)))
+ set_remove(z->dnssec_transactions, t);
+ set_free(t->notify_transactions_done);
+
dns_transaction_flush_dnssec_transactions(t);
set_free(t->dnssec_transactions);
@@ -127,8 +140,11 @@ bool dns_transaction_gc(DnsTransaction *t) {
return true;
if (set_isempty(t->notify_query_candidates) &&
+ set_isempty(t->notify_query_candidates_done) &&
set_isempty(t->notify_zone_items) &&
- set_isempty(t->notify_transactions)) {
+ set_isempty(t->notify_zone_items_done) &&
+ set_isempty(t->notify_transactions) &&
+ set_isempty(t->notify_transactions_done)) {
dns_transaction_free(t);
return false;
}
@@ -266,6 +282,7 @@ static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
log_debug("We have the lexicographically larger IP address and thus lost in the conflict.");
t->block_gc++;
+
while ((z = set_first(t->notify_zone_items))) {
/* First, make sure the zone item drops the reference
* to us */
@@ -284,7 +301,6 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
DnsQueryCandidate *c;
DnsZoneItem *z;
DnsTransaction *d;
- Iterator i;
const char *st;
char key_str[DNS_RESOURCE_KEY_STRING_MAX];
@@ -333,39 +349,17 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
* transaction isn't freed while we are still looking at it */
t->block_gc++;
- SET_FOREACH(c, t->notify_query_candidates, i)
+ SET_FOREACH_MOVE(c, t->notify_query_candidates_done, t->notify_query_candidates)
dns_query_candidate_notify(c);
- SET_FOREACH(z, t->notify_zone_items, i)
- dns_zone_item_notify(z);
+ SWAP_TWO(t->notify_query_candidates, t->notify_query_candidates_done);
- if (!set_isempty(t->notify_transactions)) {
- DnsTransaction **nt;
- unsigned j, n = 0;
-
- /* We need to be careful when notifying other
- * transactions, as that might destroy other
- * transactions in our list. Hence, in order to be
- * able to safely iterate through the list of
- * transactions, take a GC lock on all of them
- * first. Then, in a second loop, notify them, but
- * first unlock that specific transaction. */
-
- nt = newa(DnsTransaction*, set_size(t->notify_transactions));
- SET_FOREACH(d, t->notify_transactions, i) {
- nt[n++] = d;
- d->block_gc++;
- }
-
- assert(n == set_size(t->notify_transactions));
+ SET_FOREACH_MOVE(z, t->notify_zone_items_done, t->notify_zone_items)
+ dns_zone_item_notify(z);
+ SWAP_TWO(t->notify_zone_items, t->notify_zone_items_done);
- for (j = 0; j < n; j++) {
- if (set_contains(t->notify_transactions, nt[j]))
- dns_transaction_notify(nt[j], t);
-
- nt[j]->block_gc--;
- dns_transaction_gc(nt[j]);
- }
- }
+ SET_FOREACH_MOVE(d, t->notify_transactions_done, t->notify_transactions)
+ dns_transaction_notify(d, t);
+ SWAP_TWO(t->notify_transactions, t->notify_transactions_done);
t->block_gc--;
dns_transaction_gc(t);
@@ -1626,6 +1620,10 @@ static int dns_transaction_add_dnssec_transaction(DnsTransaction *t, DnsResource
if (r < 0)
goto gc;
+ r = set_ensure_allocated(&aux->notify_transactions_done, NULL);
+ if (r < 0)
+ goto gc;
+
r = set_put(t->dnssec_transactions, aux);
if (r < 0)
goto gc;
diff --git a/src/resolve/resolved-dns-transaction.h b/src/resolve/resolved-dns-transaction.h
index 491c62d772..eaece91533 100644
--- a/src/resolve/resolved-dns-transaction.h
+++ b/src/resolve/resolved-dns-transaction.h
@@ -118,17 +118,17 @@ struct DnsTransaction {
/* Query candidates this transaction is referenced by and that
* shall be notified about this specific transaction
* completing. */
- Set *notify_query_candidates;
+ Set *notify_query_candidates, *notify_query_candidates_done;
/* Zone items this transaction is referenced by and that shall
* be notified about completion. */
- Set *notify_zone_items;
+ Set *notify_zone_items, *notify_zone_items_done;
/* Other transactions that this transactions is referenced by
* and that shall be notified about completion. This is used
* when transactions want to validate their RRsets, but need
* another DNSKEY or DS RR to do so. */
- Set *notify_transactions;
+ Set *notify_transactions, *notify_transactions_done;
/* The opposite direction: the transactions this transaction
* created in order to request DNSKEY or DS RRs. */
diff --git a/src/resolve/resolved-dns-zone.c b/src/resolve/resolved-dns-zone.c
index 03813da6a2..850eed8cb8 100644
--- a/src/resolve/resolved-dns-zone.c
+++ b/src/resolve/resolved-dns-zone.c
@@ -38,6 +38,7 @@ void dns_zone_item_probe_stop(DnsZoneItem *i) {
i->probe_transaction = NULL;
set_remove(t->notify_zone_items, i);
+ set_remove(t->notify_zone_items_done, i);
dns_transaction_gc(t);
}
@@ -186,6 +187,10 @@ static int dns_zone_item_probe_start(DnsZoneItem *i) {
if (r < 0)
goto gc;
+ r = set_ensure_allocated(&t->notify_zone_items_done, NULL);
+ if (r < 0)
+ goto gc;
+
r = set_put(t->notify_zone_items, i);
if (r < 0)
goto gc;
diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c
index c7e2ab14d6..161ea03412 100644
--- a/src/resolve/resolved.c
+++ b/src/resolve/resolved.c
@@ -48,7 +48,7 @@ int main(int argc, char *argv[]) {
umask(0022);
- r = mac_selinux_init(NULL);
+ r = mac_selinux_init();
if (r < 0) {
log_error_errno(r, "SELinux setup failed: %m");
goto finish;
diff --git a/src/run/run.c b/src/run/run.c
index e7f4c21f73..1ed1bd96bf 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -83,8 +83,8 @@ static void polkit_agent_open_if_enabled(void) {
static void help(void) {
printf("%s [OPTIONS...] {COMMAND} [ARGS...]\n\n"
"Run the specified command in a transient scope or service or timer\n"
- "unit. If timer option is specified and unit is exist which is\n"
- "specified with --unit option then command can be omitted.\n\n"
+ "unit. If a timer option is specified and the unit specified with\n"
+ "the --unit option exists, the command can be omitted.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --no-ask-password Do not prompt for password\n"
diff --git a/src/shared/acpi-fpdt.c b/src/shared/acpi-fpdt.c
index 3cb9e781fd..6779691c28 100644
--- a/src/shared/acpi-fpdt.c
+++ b/src/shared/acpi-fpdt.c
@@ -119,7 +119,7 @@ int acpi_get_boot_usec(usec_t *loader_start, usec_t *loader_exit) {
}
if (ptr == 0)
- return -EINVAL;
+ return -ENODATA;
/* read Firmware Basic Boot Performance Data Record */
fd = open("/dev/mem", O_CLOEXEC|O_RDONLY);
@@ -146,6 +146,10 @@ int acpi_get_boot_usec(usec_t *loader_start, usec_t *loader_exit) {
if (brec.type != ACPI_FPDT_BOOT_REC)
return -EINVAL;
+ if (brec.exit_services_exit == 0)
+ /* Non-UEFI compatible boot. */
+ return -ENODATA;
+
if (brec.startup_start == 0 || brec.exit_services_exit < brec.startup_start)
return -EINVAL;
if (brec.exit_services_exit > NSEC_PER_HOUR)
diff --git a/src/shared/machine-pool.c b/src/shared/machine-pool.c
index f080b849a4..23890c63a0 100644
--- a/src/shared/machine-pool.c
+++ b/src/shared/machine-pool.c
@@ -139,7 +139,7 @@ static int setup_machine_raw(uint64_t size, sd_bus_error *error) {
execlp("mkfs.btrfs", "-Lvar-lib-machines", tmp, NULL);
if (errno == ENOENT)
- return 99;
+ _exit(99);
_exit(EXIT_FAILURE);
}
@@ -239,10 +239,8 @@ int setup_machine_directory(uint64_t size, sd_bus_error *error) {
}
r = mkfs_exists("btrfs");
- if (r == -ENOENT) {
- log_debug("mkfs.btrfs is missing, cannot create loopback file for /var/lib/machines.");
- return 0;
- }
+ if (r == 0)
+ return sd_bus_error_set_errnof(error, ENOENT, "Cannot set up /var/lib/machines, mkfs.btrfs is missing");
if (r < 0)
return r;
diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c
index 061d31f4de..02c03b98d8 100644
--- a/src/shared/ptyfwd.c
+++ b/src/shared/ptyfwd.c
@@ -461,10 +461,7 @@ int pty_forward_set_ignore_vhangup(PTYForward *f, bool b) {
if (!!(f->flags & PTY_FORWARD_IGNORE_VHANGUP) == b)
return 0;
- if (b)
- f->flags |= PTY_FORWARD_IGNORE_VHANGUP;
- else
- f->flags &= ~PTY_FORWARD_IGNORE_VHANGUP;
+ SET_FLAG(f->flags, PTY_FORWARD_IGNORE_VHANGUP, b);
if (!ignore_vhangup(f)) {
diff --git a/src/stdio-bridge/stdio-bridge.c b/src/stdio-bridge/stdio-bridge.c
index 91eace90e2..ce8efce3d5 100644
--- a/src/stdio-bridge/stdio-bridge.c
+++ b/src/stdio-bridge/stdio-bridge.c
@@ -190,7 +190,7 @@ int main(int argc, char *argv[]) {
}
for (;;) {
- _cleanup_(sd_bus_message_unrefp)sd_bus_message *m = NULL;
+ _cleanup_(sd_bus_message_unrefp)sd_bus_message *m = NULL;
int events_a, events_b, fd;
uint64_t timeout_a, timeout_b, t;
struct timespec _ts, *ts;
@@ -234,12 +234,14 @@ int main(int argc, char *argv[]) {
fd = sd_bus_get_fd(a);
if (fd < 0) {
+ r = fd;
log_error_errno(r, "Failed to get fd: %m");
goto finish;
}
events_a = sd_bus_get_events(a);
if (events_a < 0) {
+ r = events_a;
log_error_errno(r, "Failed to get events mask: %m");
goto finish;
}
@@ -252,6 +254,7 @@ int main(int argc, char *argv[]) {
events_b = sd_bus_get_events(b);
if (events_b < 0) {
+ r = events_b;
log_error_errno(r, "Failed to get events mask: %m");
goto finish;
}
@@ -294,8 +297,6 @@ int main(int argc, char *argv[]) {
}
}
- r = 0;
-
finish:
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index a4491692a9..180c8f9656 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -152,7 +152,7 @@ static bool arg_now = false;
static int daemon_reload(int argc, char *argv[], void* userdata);
static int halt_now(enum action a);
-static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
+static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *active_state);
static bool original_stdout_is_tty;
@@ -1630,11 +1630,27 @@ static int list_dependencies_one(
if (arg_plain)
printf(" ");
else {
- int state;
+ UnitActiveState active_state = _UNIT_ACTIVE_STATE_INVALID;
const char *on;
- state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
- on = state > 0 ? ansi_highlight_green() : ansi_highlight_red();
+ (void) get_state_one_unit(bus, *c, &active_state);
+ switch (active_state) {
+ case UNIT_ACTIVE:
+ case UNIT_RELOADING:
+ case UNIT_ACTIVATING:
+ on = ansi_highlight_green();
+ break;
+
+ case UNIT_INACTIVE:
+ case UNIT_DEACTIVATING:
+ on = ansi_normal();
+ break;
+
+ default:
+ on = ansi_highlight_red();
+ break;
+ }
+
printf("%s%s%s ", on, draw_special_char(DRAW_BLACK_CIRCLE), ansi_normal());
}
@@ -2399,18 +2415,19 @@ static int unit_find_paths(
return r;
}
-static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
+static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *active_state) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_free_ char *buf = NULL;
- const char *path, *state;
+ UnitActiveState state;
+ const char *path;
int r;
assert(name);
+ assert(active_state);
/* We don't use unit_dbus_path_from_name() directly since we don't want to load the unit unnecessarily, if it
* isn't loaded. */
-
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
@@ -2426,7 +2443,7 @@ static int check_one_unit(sd_bus *bus, const char *name, const char *good_states
/* The unit is currently not loaded, hence say it's "inactive", since all units that aren't loaded are
* considered inactive. */
- state = "inactive";
+ state = UNIT_INACTIVE;
} else {
r = sd_bus_message_read(reply, "o", &path);
@@ -2444,13 +2461,15 @@ static int check_one_unit(sd_bus *bus, const char *name, const char *good_states
if (r < 0)
return log_error_errno(r, "Failed to retrieve unit state: %s", bus_error_message(&error, r));
- state = buf;
+ state = unit_active_state_from_string(buf);
+ if (state == _UNIT_ACTIVE_STATE_INVALID) {
+ log_error("Invalid unit state '%s' for: %s", buf, name);
+ return -EINVAL;
+ }
}
- if (!quiet)
- puts(state);
-
- return nulstr_contains(good_states, state);
+ *active_state = state;
+ return 0;
}
static int check_triggering_units(
@@ -2458,9 +2477,10 @@ static int check_triggering_units(
const char *name) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
+ _cleanup_free_ char *path = NULL, *n = NULL, *load_state = NULL;
_cleanup_strv_free_ char **triggered_by = NULL;
bool print_warning_label = true;
+ UnitActiveState active_state;
char **i;
int r;
@@ -2479,11 +2499,11 @@ static int check_triggering_units(
"org.freedesktop.systemd1.Unit",
"LoadState",
&error,
- &state);
+ &load_state);
if (r < 0)
return log_error_errno(r, "Failed to get load state of %s: %s", n, bus_error_message(&error, r));
- if (streq(state, "masked"))
+ if (streq(load_state, "masked"))
return 0;
r = sd_bus_get_property_strv(
@@ -2498,11 +2518,11 @@ static int check_triggering_units(
return log_error_errno(r, "Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
STRV_FOREACH(i, triggered_by) {
- r = check_one_unit(bus, *i, "active\0reloading\0", true);
+ r = get_state_one_unit(bus, *i, &active_state);
if (r < 0)
- return log_error_errno(r, "Failed to check unit: %m");
+ return r;
- if (r == 0)
+ if (!IN_SET(active_state, UNIT_ACTIVE, UNIT_RELOADING))
continue;
if (print_warning_label) {
@@ -2596,7 +2616,10 @@ static int start_unit_one(
if (!sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) &&
!sd_bus_error_has_name(error, BUS_ERROR_UNIT_MASKED))
- log_error("See system logs and 'systemctl status %s' for details.", name);
+ log_error("See %s logs and 'systemctl%s status %s' for details.",
+ arg_scope == UNIT_FILE_SYSTEM ? "system" : "user",
+ arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
+ name);
return r;
}
@@ -3163,11 +3186,12 @@ static int start_special(int argc, char *argv[], void *userdata) {
return start_unit(argc, argv, userdata);
}
-static int check_unit_generic(int code, const char *good_states, char **args) {
+static int check_unit_generic(int code, const UnitActiveState good_states[], int nb_states, char **args) {
_cleanup_strv_free_ char **names = NULL;
+ UnitActiveState active_state;
sd_bus *bus;
char **name;
- int r;
+ int r, i;
bool found = false;
r = acquire_bus(BUS_MANAGER, &bus);
@@ -3179,13 +3203,16 @@ static int check_unit_generic(int code, const char *good_states, char **args) {
return log_error_errno(r, "Failed to expand names: %m");
STRV_FOREACH(name, names) {
- int state;
+ r = get_state_one_unit(bus, *name, &active_state);
+ if (r < 0)
+ return r;
+
+ if (!arg_quiet)
+ puts(unit_active_state_to_string(active_state));
- state = check_one_unit(bus, *name, good_states, arg_quiet);
- if (state < 0)
- return state;
- if (state > 0)
- found = true;
+ for (i = 0; i < nb_states; ++i)
+ if (good_states[i] == active_state)
+ found = true;
}
/* use the given return code for the case that we won't find
@@ -3194,12 +3221,14 @@ static int check_unit_generic(int code, const char *good_states, char **args) {
}
static int check_unit_active(int argc, char *argv[], void *userdata) {
+ const UnitActiveState states[] = { UNIT_ACTIVE, UNIT_RELOADING };
/* According to LSB: 3, "program is not running" */
- return check_unit_generic(3, "active\0reloading\0", strv_skip(argv, 1));
+ return check_unit_generic(3, states, ELEMENTSOF(states), strv_skip(argv, 1));
}
static int check_unit_failed(int argc, char *argv[], void *userdata) {
- return check_unit_generic(1, "failed\0", strv_skip(argv, 1));
+ const UnitActiveState states[] = { UNIT_FAILED };
+ return check_unit_generic(1, states, ELEMENTSOF(states), strv_skip(argv, 1));
}
static int kill_unit(int argc, char *argv[], void *userdata) {
@@ -6162,9 +6191,24 @@ static int edit(int argc, char *argv[], void *userdata) {
r = daemon_reload(argc, argv, userdata);
end:
- STRV_FOREACH_PAIR(original, tmp, paths)
+ STRV_FOREACH_PAIR(original, tmp, paths) {
(void) unlink(*tmp);
+ /* Removing empty dropin dirs */
+ if (!arg_full) {
+ _cleanup_free_ char *dir;
+
+ dir = dirname_malloc(*original);
+ if (!dir)
+ return log_oom();
+
+ /* no need to check if the dir is empty, rmdir
+ * does nothing if it is not the case.
+ */
+ (void) rmdir(dir);
+ }
+ }
+
return r;
}
@@ -7263,6 +7307,7 @@ static int parse_argv(int argc, char *argv[]) {
return systemctl_parse_argv(argc, argv);
}
+#ifdef HAVE_SYSV_COMPAT
_pure_ static int action_to_runlevel(void) {
static const char table[_ACTION_MAX] = {
@@ -7280,6 +7325,7 @@ _pure_ static int action_to_runlevel(void) {
return table[arg_action];
}
+#endif
static int talk_initctl(void) {
#ifdef HAVE_SYSV_COMPAT
diff --git a/src/systemd/_sd-common.h b/src/systemd/_sd-common.h
index 2d4e1f26e1..3bb886be75 100644
--- a/src/systemd/_sd-common.h
+++ b/src/systemd/_sd-common.h
@@ -74,7 +74,7 @@
#endif
#define _SD_DEFINE_POINTER_CLEANUP_FUNC(type, func) \
- static inline void func##p(type **p) { \
+ static __inline__ void func##p(type **p) { \
if (*p) \
func(*p); \
} \
diff --git a/src/systemd/sd-bus-protocol.h b/src/systemd/sd-bus-protocol.h
index 47b256d5b9..623cee0c50 100644
--- a/src/systemd/sd-bus-protocol.h
+++ b/src/systemd/sd-bus-protocol.h
@@ -59,7 +59,7 @@ enum {
SD_BUS_TYPE_STRUCT_END = ')',
SD_BUS_TYPE_DICT_ENTRY = 'e', /* not actually used in signatures */
SD_BUS_TYPE_DICT_ENTRY_BEGIN = '{',
- SD_BUS_TYPE_DICT_ENTRY_END = '}',
+ SD_BUS_TYPE_DICT_ENTRY_END = '}'
};
/* Well-known errors. Note that this is only a sanitized subset of the
diff --git a/src/systemd/sd-bus-vtable.h b/src/systemd/sd-bus-vtable.h
index 6ad6d51979..e8f84eb545 100644
--- a/src/systemd/sd-bus-vtable.h
+++ b/src/systemd/sd-bus-vtable.h
@@ -34,7 +34,7 @@ enum {
_SD_BUS_VTABLE_METHOD = 'M',
_SD_BUS_VTABLE_SIGNAL = 'S',
_SD_BUS_VTABLE_PROPERTY = 'P',
- _SD_BUS_VTABLE_WRITABLE_PROPERTY = 'W',
+ _SD_BUS_VTABLE_WRITABLE_PROPERTY = 'W'
};
enum {
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index 2a2ef0eb98..295989cd69 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -89,13 +89,13 @@ enum {
SD_BUS_CREDS_WELL_KNOWN_NAMES = 1ULL << 32,
SD_BUS_CREDS_DESCRIPTION = 1ULL << 33,
SD_BUS_CREDS_AUGMENT = 1ULL << 63, /* special flag, if on sd-bus will augment creds struct, in a potentially race-full way. */
- _SD_BUS_CREDS_ALL = (1ULL << 34) -1,
+ _SD_BUS_CREDS_ALL = (1ULL << 34) -1
};
enum {
SD_BUS_NAME_REPLACE_EXISTING = 1ULL << 0,
SD_BUS_NAME_ALLOW_REPLACEMENT = 1ULL << 1,
- SD_BUS_NAME_QUEUE = 1ULL << 2,
+ SD_BUS_NAME_QUEUE = 1ULL << 2
};
/* Callbacks */
diff --git a/src/systemd/sd-device.h b/src/systemd/sd-device.h
index 5bfca6ecec..c1d07561d7 100644
--- a/src/systemd/sd-device.h
+++ b/src/systemd/sd-device.h
@@ -22,6 +22,7 @@
***/
#include <inttypes.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#include "_sd-common.h"
diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h
index ef45370505..7873cb1e04 100644
--- a/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/sd-dhcp-client.h
@@ -27,6 +27,7 @@
#include "sd-dhcp-lease.h"
#include "sd-event.h"
+#include "sparse-endian.h"
#include "_sd-common.h"
@@ -82,6 +83,7 @@ enum {
SD_DHCP_OPTION_END = 255,
};
+struct duid;
typedef struct sd_dhcp_client sd_dhcp_client;
typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event,
@@ -98,6 +100,8 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
size_t addr_len, uint16_t arp_type);
int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
const uint8_t *data, size_t data_len);
+int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, be32_t iaid,
+ size_t duid_len, struct duid *duid);
int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
const uint8_t **data, size_t *data_len);
int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu);
diff --git a/src/systemd/sd-dhcp6-client.h b/src/systemd/sd-dhcp6-client.h
index 1bedc941aa..ebdd017628 100644
--- a/src/systemd/sd-dhcp6-client.h
+++ b/src/systemd/sd-dhcp6-client.h
@@ -26,6 +26,7 @@
#include "sd-dhcp6-lease.h"
#include "sd-event.h"
+#include "sparse-endian.h"
#include "_sd-common.h"
@@ -74,6 +75,7 @@ enum {
/* option codes 144-65535 are unassigned */
};
+struct duid;
typedef struct sd_dhcp6_client sd_dhcp6_client;
typedef void (*sd_dhcp6_client_callback_t)(sd_dhcp6_client *client, int event,
@@ -85,8 +87,9 @@ int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index);
int sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address);
int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr,
size_t addr_len, uint16_t arp_type);
-int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *duid,
- size_t duid_len);
+int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, size_t duid_len,
+ struct duid *duid);
+int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, be32_t iaid);
int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, int enabled);
int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, int *enabled);
int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client,
diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h
index 1ea97e47f8..531ace1c34 100644
--- a/src/systemd/sd-event.h
+++ b/src/systemd/sd-event.h
@@ -55,7 +55,7 @@ enum {
SD_EVENT_RUNNING,
SD_EVENT_EXITING,
SD_EVENT_FINISHED,
- SD_EVENT_PREPARING,
+ SD_EVENT_PREPARING
};
enum {
@@ -69,7 +69,11 @@ typedef int (*sd_event_handler_t)(sd_event_source *s, void *userdata);
typedef int (*sd_event_io_handler_t)(sd_event_source *s, int fd, uint32_t revents, void *userdata);
typedef int (*sd_event_time_handler_t)(sd_event_source *s, uint64_t usec, void *userdata);
typedef int (*sd_event_signal_handler_t)(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata);
+#if defined __USE_POSIX199309 || defined __USE_XOPEN_EXTENDED
typedef int (*sd_event_child_handler_t)(sd_event_source *s, const siginfo_t *si, void *userdata);
+#else
+typedef void* sd_event_child_handler_t;
+#endif
int sd_event_default(sd_event **e);
diff --git a/src/systemd/sd-id128.h b/src/systemd/sd-id128.h
index a3bf5897b8..4dff0b9b81 100644
--- a/src/systemd/sd-id128.h
+++ b/src/systemd/sd-id128.h
@@ -100,11 +100,11 @@ int sd_id128_get_boot(sd_id128_t *ret);
((x).bytes[15] & 15) >= 10 ? 'a' + ((x).bytes[15] & 15) - 10 : '0' + ((x).bytes[15] & 15), \
0 })
-_sd_pure_ static inline int sd_id128_equal(sd_id128_t a, sd_id128_t b) {
+_sd_pure_ static __inline__ int sd_id128_equal(sd_id128_t a, sd_id128_t b) {
return memcmp(&a, &b, 16) == 0;
}
-_sd_pure_ static inline int sd_id128_is_null(sd_id128_t a) {
+_sd_pure_ static __inline__ int sd_id128_is_null(sd_id128_t a) {
return a.qwords[0] == 0 && a.qwords[1] == 0;
}
diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h
index abb9eca576..d4c6f409cd 100644
--- a/src/systemd/sd-journal.h
+++ b/src/systemd/sd-journal.h
@@ -72,7 +72,7 @@ enum {
SD_JOURNAL_SYSTEM = 4,
SD_JOURNAL_CURRENT_USER = 8,
- SD_JOURNAL_SYSTEM_ONLY = SD_JOURNAL_SYSTEM, /* deprecated name */
+ SD_JOURNAL_SYSTEM_ONLY = SD_JOURNAL_SYSTEM /* deprecated name */
};
/* Wakeup event types */
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index 863c628323..4377f1b910 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -1820,7 +1820,7 @@ int main(int argc, char *argv[]) {
umask(0022);
- r = mac_selinux_init(NULL);
+ r = mac_selinux_init();
if (r < 0) {
log_error_errno(r, "SELinux setup failed: %m");
goto finish;
diff --git a/src/test/test-alloc-util.c b/src/test/test-alloc-util.c
new file mode 100644
index 0000000000..cc4821eaf5
--- /dev/null
+++ b/src/test/test-alloc-util.c
@@ -0,0 +1,55 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "alloc-util.h"
+#include "macro.h"
+#include "util.h"
+
+static void test_alloca(void) {
+ static const uint8_t zero[997] = { };
+ char *t;
+
+ t = alloca_align(17, 512);
+ assert_se(!((uintptr_t)t & 0xff));
+ memzero(t, 17);
+
+ t = alloca0_align(997, 1024);
+ assert_se(!((uintptr_t)t & 0x1ff));
+ assert_se(!memcmp(t, zero, 997));
+}
+
+static void test_memdup_multiply(void) {
+ int org[] = {1, 2, 3};
+ int *dup;
+
+ dup = (int*)memdup_multiply(org, sizeof(int), 3);
+
+ assert_se(dup);
+ assert_se(dup[0] == 1);
+ assert_se(dup[1] == 2);
+ assert_se(dup[2] == 3);
+ free(dup);
+}
+
+int main(int argc, char *argv[]) {
+ test_alloca();
+ test_memdup_multiply();
+
+ return 0;
+}
diff --git a/src/test/test-boot-timestamps.c b/src/test/test-boot-timestamps.c
index d2add5880c..8e68d6510d 100644
--- a/src/test/test-boot-timestamps.c
+++ b/src/test/test-boot-timestamps.c
@@ -34,17 +34,18 @@ static int test_acpi_fpdt(void) {
r = acpi_get_boot_usec(&loader_start, &loader_exit);
if (r < 0) {
- if (r != -ENOENT)
- log_error_errno(r, "Failed to read ACPI FPDT: %m");
- return r;
+ bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES) || r == -ENODATA;
+
+ log_full_errno(ok ? LOG_DEBUG : LOG_ERR,
+ r, "Failed to read ACPI FPDT: %m");
+ return ok ? 0 : r;
}
log_info("ACPI FPDT: loader start=%s exit=%s duration=%s",
format_timespan(ts_start, sizeof(ts_start), loader_start, USEC_PER_MSEC),
format_timespan(ts_exit, sizeof(ts_exit), loader_exit, USEC_PER_MSEC),
format_timespan(ts_span, sizeof(ts_span), loader_exit - loader_start, USEC_PER_MSEC));
-
- return 0;
+ return 1;
}
static int test_efi_loader(void) {
@@ -57,33 +58,34 @@ static int test_efi_loader(void) {
r = efi_loader_get_boot_usec(&loader_start, &loader_exit);
if (r < 0) {
- if (r != -ENOENT)
- log_error_errno(r, "Failed to read EFI loader data: %m");
- return r;
+ bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES);
+
+ log_full_errno(ok ? LOG_DEBUG : LOG_ERR,
+ r, "Failed to read EFI loader data: %m");
+ return ok ? 0 : r;
}
log_info("EFI Loader: start=%s exit=%s duration=%s",
format_timespan(ts_start, sizeof(ts_start), loader_start, USEC_PER_MSEC),
format_timespan(ts_exit, sizeof(ts_exit), loader_exit, USEC_PER_MSEC),
format_timespan(ts_span, sizeof(ts_span), loader_exit - loader_start, USEC_PER_MSEC));
-
- return 0;
+ return 1;
}
-int main(int argc, char* argv[]) {
+static int test_boot_timestamps(void) {
char s[MAX(FORMAT_TIMESPAN_MAX, FORMAT_TIMESTAMP_MAX)];
int r;
dual_timestamp fw, l, k;
- test_acpi_fpdt();
- test_efi_loader();
-
dual_timestamp_from_monotonic(&k, 0);
r = boot_timestamps(NULL, &fw, &l);
if (r < 0) {
- log_error_errno(r, "Failed to read variables: %m");
- return 1;
+ bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES);
+
+ log_full_errno(ok ? LOG_DEBUG : LOG_ERR,
+ r, "Failed to read variables: %m");
+ return ok ? 0 : r;
}
log_info("Firmware began %s before kernel.", format_timespan(s, sizeof(s), fw.monotonic, 0));
@@ -91,6 +93,21 @@ int main(int argc, char* argv[]) {
log_info("Firmware began %s.", format_timestamp(s, sizeof(s), fw.realtime));
log_info("Loader began %s.", format_timestamp(s, sizeof(s), l.realtime));
log_info("Kernel began %s.", format_timestamp(s, sizeof(s), k.realtime));
+ return 1;
+}
+
+int main(int argc, char* argv[]) {
+ int p, q, r;
+
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+
+ p = test_acpi_fpdt();
+ assert(p >= 0);
+ q = test_efi_loader();
+ assert(q >= 0);
+ r = test_boot_timestamps();
+ assert(r >= 0);
- return 0;
+ return (p > 0 || q > 0 || r >> 0) ? EXIT_SUCCESS : EXIT_TEST_SKIP;
}
diff --git a/src/test/test-clock.c b/src/test/test-clock.c
new file mode 100644
index 0000000000..84f775e5bc
--- /dev/null
+++ b/src/test/test-clock.c
@@ -0,0 +1,96 @@
+/***
+ This file is part of systemd.
+
+ Copyright (C) 2016 Canonical Ltd.
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "clock-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "log.h"
+#include "macro.h"
+
+static void test_clock_is_localtime(void) {
+ char adjtime[] = "/tmp/test-adjtime.XXXXXX";
+ int fd = -1;
+ _cleanup_fclose_ FILE* f = NULL;
+
+ static const struct scenario {
+ const char* contents;
+ int expected_result;
+ } scenarios[] = {
+ /* adjtime configures UTC */
+ {"0.0 0 0\n0\nUTC\n", 0},
+ /* adjtime configures local time */
+ {"0.0 0 0\n0\nLOCAL\n", 1},
+ /* no final EOL */
+ {"0.0 0 0\n0\nUTC", 0},
+ {"0.0 0 0\n0\nLOCAL", 1},
+ /* empty value -> defaults to UTC */
+ {"0.0 0 0\n0\n", 0},
+ /* unknown value -> defaults to UTC */
+ {"0.0 0 0\n0\nFOO\n", 0},
+ /* no third line */
+ {"0.0 0 0", 0},
+ {"0.0 0 0\n", 0},
+ {"0.0 0 0\n0", 0},
+ };
+
+ /* without an adjtime file we default to UTC */
+ assert_se(clock_is_localtime("/nonexisting/adjtime") == 0);
+
+ fd = mkostemp_safe(adjtime, O_WRONLY|O_CLOEXEC);
+ assert_se(fd >= 0);
+ log_info("adjtime test file: %s", adjtime);
+ f = fdopen(fd, "w");
+ assert_se(f);
+
+ for (size_t i = 0; i < ELEMENTSOF(scenarios); ++i) {
+ log_info("scenario #%zu:, expected result %i", i, scenarios[i].expected_result);
+ log_info("%s", scenarios[i].contents);
+ rewind(f);
+ ftruncate(fd, 0);
+ assert_se(write_string_stream(f, scenarios[i].contents, false) == 0);
+ assert_se(clock_is_localtime(adjtime) == scenarios[i].expected_result);
+ }
+
+ unlink(adjtime);
+}
+
+/* Test with the real /etc/adjtime */
+static void test_clock_is_localtime_system(void) {
+ int r;
+ r = clock_is_localtime(NULL);
+
+ if (access("/etc/adjtime", F_OK) == 0) {
+ log_info("/etc/adjtime exists, clock_is_localtime() == %i", r);
+ /* if /etc/adjtime exists we expect some answer, no error or
+ * crash */
+ assert_se(r == 0 || r == 1);
+ } else
+ /* default is UTC if there is no /etc/adjtime */
+ assert_se(r == 0);
+}
+
+int main(int argc, char *argv[]) {
+ test_clock_is_localtime();
+ test_clock_is_localtime_system();
+
+ return 0;
+}
diff --git a/src/test/test-conf-parser.c b/src/test/test-conf-parser.c
index b3a4c40339..be5d2611f8 100644
--- a/src/test/test-conf-parser.c
+++ b/src/test/test-conf-parser.c
@@ -215,6 +215,14 @@ static void test_config_parse_nsec(void) {
test_config_parse_nsec_one("garbage", 0);
}
+static void test_config_parse_iec_uint64(void) {
+ uint64_t offset = 0;
+ assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0);
+ assert_se(offset == 4 * 1024 * 1024);
+
+ assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0);
+}
+
int main(int argc, char **argv) {
log_parse_environment();
log_open();
@@ -230,6 +238,7 @@ int main(int argc, char **argv) {
test_config_parse_mode();
test_config_parse_sec();
test_config_parse_nsec();
+ test_config_parse_iec_uint64();
return 0;
}
diff --git a/src/test/test-copy.c b/src/test/test-copy.c
index ad57cb0202..1462affbcf 100644
--- a/src/test/test-copy.c
+++ b/src/test/test-copy.c
@@ -24,6 +24,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
+#include "log.h"
#include "macro.h"
#include "mkdir.h"
#include "path-util.h"
@@ -39,6 +40,8 @@ static void test_copy_file(void) {
size_t sz = 0;
int fd;
+ log_info("%s", __func__);
+
fd = mkostemp_safe(fn, O_RDWR|O_CLOEXEC);
assert_se(fd >= 0);
close(fd);
@@ -66,6 +69,8 @@ static void test_copy_file_fd(void) {
char text[] = "boohoo\nfoo\n\tbar\n";
char buf[64] = {0};
+ log_info("%s", __func__);
+
in_fd = mkostemp_safe(in_fn, O_RDWR);
assert_se(in_fd >= 0);
out_fd = mkostemp_safe(out_fn, O_RDWR);
@@ -91,6 +96,8 @@ static void test_copy_tree(void) {
"link2", "dir1/file");
char **p, **link;
+ log_info("%s", __func__);
+
(void) rm_rf(copy_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf(original_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
@@ -173,11 +180,65 @@ static void test_copy_bytes(void) {
assert_se(r == -EBADF);
}
+static void test_copy_bytes_regular_file(const char *src, bool try_reflink, size_t max_bytes) {
+ char fn2[] = "/tmp/test-copy-file-XXXXXX";
+ char fn3[] = "/tmp/test-copy-file-XXXXXX";
+ _cleanup_close_ int fd = -1, fd2 = -1, fd3 = -1;
+ int r;
+ struct stat buf, buf2, buf3;
+
+ log_info("%s try_reflink=%s max_bytes=%zu", __func__, yes_no(try_reflink), max_bytes);
+
+ fd = open(src, O_RDONLY | O_CLOEXEC | O_NOCTTY);
+ assert_se(fd >= 0);
+
+ fd2 = mkostemp_safe(fn2, O_RDWR);
+ assert_se(fd2 >= 0);
+
+ fd3 = mkostemp_safe(fn3, O_WRONLY);
+ assert_se(fd3 >= 0);
+
+ r = copy_bytes(fd, fd2, max_bytes, try_reflink);
+ if (max_bytes == (uint64_t) -1)
+ assert_se(r == 0);
+ else
+ assert_se(IN_SET(r, 0, 1));
+
+ assert_se(lseek(fd2, 0, SEEK_SET) == 0);
+
+ r = copy_bytes(fd2, fd3, max_bytes, try_reflink);
+ if (max_bytes == (uint64_t) -1)
+ assert_se(r == 0);
+ else
+ /* We cannot distinguish between the input being exactly max_bytes
+ * or longer than max_bytes (without trying to read one more byte,
+ * or calling stat, or FION_READ, etc, and we don't want to do any
+ * of that). So we expect "truncation" since we know that file we
+ * are copying is exactly max_bytes bytes. */
+ assert_se(r == 1);
+
+ assert_se(fstat(fd, &buf) == 0);
+ assert_se(fstat(fd2, &buf2) == 0);
+ assert_se(fstat(fd3, &buf3) == 0);
+
+ assert_se((size_t) buf2.st_size == MIN((size_t) buf.st_size, max_bytes));
+ assert_se(buf3.st_size == buf2.st_size);
+
+ unlink(fn2);
+ unlink(fn3);
+}
+
int main(int argc, char *argv[]) {
test_copy_file();
test_copy_file_fd();
test_copy_tree();
test_copy_bytes();
+ test_copy_bytes_regular_file(argv[0], false, (uint64_t) -1);
+ test_copy_bytes_regular_file(argv[0], true, (uint64_t) -1);
+ test_copy_bytes_regular_file(argv[0], false, 1000); /* smaller than copy buffer size */
+ test_copy_bytes_regular_file(argv[0], true, 1000);
+ test_copy_bytes_regular_file(argv[0], false, 32000); /* larger than copy buffer size */
+ test_copy_bytes_regular_file(argv[0], true, 32000);
return 0;
}
diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c
new file mode 100644
index 0000000000..8818d1ffb7
--- /dev/null
+++ b/src/test/test-cpu-set-util.c
@@ -0,0 +1,143 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "alloc-util.h"
+#include "cpu-set-util.h"
+#include "macro.h"
+
+static void test_parse_cpu_set(void) {
+ cpu_set_t *c = NULL;
+ int ncpus;
+ int cpu;
+
+ /* Simple range (from CPUAffinity example) */
+ ncpus = parse_cpu_set_and_warn("1 2", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
+ assert_se(CPU_ISSET_S(2, CPU_ALLOC_SIZE(ncpus), c));
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 2);
+ c = mfree(c);
+
+ /* A more interesting range */
+ ncpus = parse_cpu_set_and_warn("0 1 2 3 8 9 10 11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Quoted strings */
+ ncpus = parse_cpu_set_and_warn("8 '9' 10 \"11\"", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 4);
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Use commas as separators */
+ ncpus = parse_cpu_set_and_warn("0,1,2,3 8,9,10,11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Commas with spaces (and trailing comma, space) */
+ ncpus = parse_cpu_set_and_warn("0, 1, 2, 3, 4, 5, 6, 7, ", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 8; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Ranges */
+ ncpus = parse_cpu_set_and_warn("0-3,8-11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Ranges with trailing comma, space */
+ ncpus = parse_cpu_set_and_warn("0-3 8-11, ", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
+ for (cpu = 0; cpu < 4; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 8; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Negative range (returns empty cpu_set) */
+ ncpus = parse_cpu_set_and_warn("3-0", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 0);
+ c = mfree(c);
+
+ /* Overlapping ranges */
+ ncpus = parse_cpu_set_and_warn("0-7 4-11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 12);
+ for (cpu = 0; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Mix ranges and individual CPUs */
+ ncpus = parse_cpu_set_and_warn("0,1 4-11", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus >= 1024);
+ assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 10);
+ assert_se(CPU_ISSET_S(0, CPU_ALLOC_SIZE(ncpus), c));
+ assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
+ for (cpu = 4; cpu < 12; cpu++)
+ assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
+ c = mfree(c);
+
+ /* Garbage */
+ ncpus = parse_cpu_set_and_warn("0 1 2 3 garbage", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus < 0);
+ assert_se(!c);
+
+ /* Range with garbage */
+ ncpus = parse_cpu_set_and_warn("0-3 8-garbage", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus < 0);
+ assert_se(!c);
+
+ /* Empty string */
+ c = NULL;
+ ncpus = parse_cpu_set_and_warn("", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus == 0); /* empty string returns 0 */
+ assert_se(!c);
+
+ /* Runnaway quoted string */
+ ncpus = parse_cpu_set_and_warn("0 1 2 3 \"4 5 6 7 ", &c, NULL, "fake", 1, "CPUAffinity");
+ assert_se(ncpus < 0);
+ assert_se(!c);
+}
+
+int main(int argc, char *argv[]) {
+ test_parse_cpu_set();
+
+ return 0;
+}
diff --git a/src/test/test-daemon.c b/src/test/test-daemon.c
index 4ce00f4b1f..a7cb426282 100644
--- a/src/test/test-daemon.c
+++ b/src/test/test-daemon.c
@@ -38,27 +38,27 @@ int main(int argc, char*argv[]) {
sd_notify(0,
"STATUS=Starting up");
- sleep(5);
+ sleep(1);
sd_notify(0,
"STATUS=Running\n"
"READY=1");
- sleep(5);
+ sleep(1);
sd_notify(0,
"STATUS=Reloading\n"
"RELOADING=1");
- sleep(5);
+ sleep(1);
sd_notify(0,
"STATUS=Running\n"
"READY=1");
- sleep(5);
+ sleep(1);
sd_notify(0,
"STATUS=Quitting\n"
"STOPPING=1");
- sleep(5);
+ sleep(1);
return EXIT_SUCCESS;
}
diff --git a/src/test/test-escape.c b/src/test/test-escape.c
new file mode 100644
index 0000000000..6cbb8443fe
--- /dev/null
+++ b/src/test/test-escape.c
@@ -0,0 +1,114 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "alloc-util.h"
+#include "escape.h"
+#include "macro.h"
+
+static void test_cescape(void) {
+ _cleanup_free_ char *escaped;
+
+ assert_se(escaped = cescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313"));
+ assert_se(streq(escaped, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\a\\003\\177\\234\\313"));
+}
+
+static void test_cunescape(void) {
+ _cleanup_free_ char *unescaped;
+
+ assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", 0, &unescaped) < 0);
+ assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "abc\\\"\b\f\a\n\r\t\v\003\177\234\313\\000\\x00"));
+ unescaped = mfree(unescaped);
+
+ /* incomplete sequences */
+ assert_se(cunescape("\\x0", 0, &unescaped) < 0);
+ assert_se(cunescape("\\x0", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\x0"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\x", 0, &unescaped) < 0);
+ assert_se(cunescape("\\x", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\x"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\", 0, &unescaped) < 0);
+ assert_se(cunescape("\\", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\11", 0, &unescaped) < 0);
+ assert_se(cunescape("\\11", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\11"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\1", 0, &unescaped) < 0);
+ assert_se(cunescape("\\1", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "\\1"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\u0000", 0, &unescaped) < 0);
+ assert_se(cunescape("\\u00DF\\U000000df\\u03a0\\U00000041", UNESCAPE_RELAX, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, "ßßΠA"));
+ unescaped = mfree(unescaped);
+
+ assert_se(cunescape("\\073", 0, &unescaped) >= 0);
+ assert_se(streq_ptr(unescaped, ";"));
+}
+
+static void test_shell_escape_one(const char *s, const char *bad, const char *expected) {
+ _cleanup_free_ char *r;
+
+ assert_se(r = shell_escape(s, bad));
+ assert_se(streq_ptr(r, expected));
+}
+
+static void test_shell_escape(void) {
+ test_shell_escape_one("", "", "");
+ test_shell_escape_one("\\", "", "\\\\");
+ test_shell_escape_one("foobar", "", "foobar");
+ test_shell_escape_one("foobar", "o", "f\\o\\obar");
+ test_shell_escape_one("foo:bar,baz", ",:", "foo\\:bar\\,baz");
+}
+
+static void test_shell_maybe_quote_one(const char *s, const char *expected) {
+ _cleanup_free_ char *r;
+
+ assert_se(r = shell_maybe_quote(s));
+ assert_se(streq(r, expected));
+}
+
+static void test_shell_maybe_quote(void) {
+
+ test_shell_maybe_quote_one("", "");
+ test_shell_maybe_quote_one("\\", "\"\\\\\"");
+ test_shell_maybe_quote_one("\"", "\"\\\"\"");
+ test_shell_maybe_quote_one("foobar", "foobar");
+ test_shell_maybe_quote_one("foo bar", "\"foo bar\"");
+ test_shell_maybe_quote_one("foo \"bar\" waldo", "\"foo \\\"bar\\\" waldo\"");
+ test_shell_maybe_quote_one("foo$bar", "\"foo\\$bar\"");
+}
+
+int main(int argc, char *argv[]) {
+ test_cescape();
+ test_cunescape();
+ test_shell_escape();
+ test_shell_maybe_quote();
+
+ return 0;
+}
diff --git a/src/test/test-fd-util.c b/src/test/test-fd-util.c
new file mode 100644
index 0000000000..421d3bdeb3
--- /dev/null
+++ b/src/test/test-fd-util.c
@@ -0,0 +1,103 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "macro.h"
+
+static void test_close_many(void) {
+ int fds[3];
+ char name0[] = "/tmp/test-close-many.XXXXXX";
+ char name1[] = "/tmp/test-close-many.XXXXXX";
+ char name2[] = "/tmp/test-close-many.XXXXXX";
+
+ fds[0] = mkostemp_safe(name0, O_RDWR|O_CLOEXEC);
+ fds[1] = mkostemp_safe(name1, O_RDWR|O_CLOEXEC);
+ fds[2] = mkostemp_safe(name2, O_RDWR|O_CLOEXEC);
+
+ close_many(fds, 2);
+
+ assert_se(fcntl(fds[0], F_GETFD) == -1);
+ assert_se(fcntl(fds[1], F_GETFD) == -1);
+ assert_se(fcntl(fds[2], F_GETFD) >= 0);
+
+ safe_close(fds[2]);
+
+ unlink(name0);
+ unlink(name1);
+ unlink(name2);
+}
+
+static void test_close_nointr(void) {
+ char name[] = "/tmp/test-test-close_nointr.XXXXXX";
+ int fd;
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ assert_se(close_nointr(fd) >= 0);
+ assert_se(close_nointr(fd) < 0);
+
+ unlink(name);
+}
+
+static void test_same_fd(void) {
+ _cleanup_close_pair_ int p[2] = { -1, -1 };
+ _cleanup_close_ int a = -1, b = -1, c = -1;
+
+ assert_se(pipe2(p, O_CLOEXEC) >= 0);
+ assert_se((a = dup(p[0])) >= 0);
+ assert_se((b = open("/dev/null", O_RDONLY|O_CLOEXEC)) >= 0);
+ assert_se((c = dup(a)) >= 0);
+
+ assert_se(same_fd(p[0], p[0]) > 0);
+ assert_se(same_fd(p[1], p[1]) > 0);
+ assert_se(same_fd(a, a) > 0);
+ assert_se(same_fd(b, b) > 0);
+
+ assert_se(same_fd(a, p[0]) > 0);
+ assert_se(same_fd(p[0], a) > 0);
+ assert_se(same_fd(c, p[0]) > 0);
+ assert_se(same_fd(p[0], c) > 0);
+ assert_se(same_fd(a, c) > 0);
+ assert_se(same_fd(c, a) > 0);
+
+ assert_se(same_fd(p[0], p[1]) == 0);
+ assert_se(same_fd(p[1], p[0]) == 0);
+ assert_se(same_fd(p[0], b) == 0);
+ assert_se(same_fd(b, p[0]) == 0);
+ assert_se(same_fd(p[1], a) == 0);
+ assert_se(same_fd(a, p[1]) == 0);
+ assert_se(same_fd(p[1], b) == 0);
+ assert_se(same_fd(b, p[1]) == 0);
+
+ assert_se(same_fd(a, b) == 0);
+ assert_se(same_fd(b, a) == 0);
+}
+
+int main(int argc, char *argv[]) {
+ test_close_many();
+ test_close_nointr();
+ test_same_fd();
+
+ return 0;
+}
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index 5586a2d6c1..ec9f173da2 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -27,6 +27,7 @@
#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "io-util.h"
#include "parse-util.h"
#include "process-util.h"
#include "string-util.h"
@@ -425,6 +426,134 @@ static void test_load_env_file_pairs(void) {
unlink(fn);
}
+static void test_search_and_fopen(void) {
+ const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
+ char name[] = "/tmp/test-search_and_fopen.XXXXXX";
+ int fd = -1;
+ int r;
+ FILE *f;
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ close(fd);
+
+ r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen(name, "r", NULL, dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen(basename(name), "r", "/", dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
+ assert_se(r < 0);
+ r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
+ assert_se(r < 0);
+
+ r = unlink(name);
+ assert_se(r == 0);
+
+ r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
+ assert_se(r < 0);
+}
+
+
+static void test_search_and_fopen_nulstr(void) {
+ const char dirs[] = "/tmp/foo/bar\0/tmp\0";
+ char name[] = "/tmp/test-search_and_fopen.XXXXXX";
+ int fd = -1;
+ int r;
+ FILE *f;
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ close(fd);
+
+ r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f);
+ assert_se(r >= 0);
+ fclose(f);
+
+ r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
+ assert_se(r < 0);
+ r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
+ assert_se(r < 0);
+
+ r = unlink(name);
+ assert_se(r == 0);
+
+ r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
+ assert_se(r < 0);
+}
+
+static void test_writing_tmpfile(void) {
+ char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
+ _cleanup_free_ char *contents = NULL;
+ size_t size;
+ int fd, r;
+ struct iovec iov[3];
+
+ IOVEC_SET_STRING(iov[0], "abc\n");
+ IOVEC_SET_STRING(iov[1], ALPHANUMERICAL "\n");
+ IOVEC_SET_STRING(iov[2], "");
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ printf("tmpfile: %s", name);
+
+ r = writev(fd, iov, 3);
+ assert_se(r >= 0);
+
+ r = read_full_file(name, &contents, &size);
+ assert_se(r == 0);
+ printf("contents: %s", contents);
+ assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
+
+ unlink(name);
+}
+
+static void test_tempfn(void) {
+ char *ret = NULL, *p;
+
+ assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0);
+ assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX"));
+ free(ret);
+
+ assert_se(tempfn_xxxxxx("/foo/bar/waldo", "[miau]", &ret) >= 0);
+ assert_se(streq_ptr(ret, "/foo/bar/.#[miau]waldoXXXXXX"));
+ free(ret);
+
+ assert_se(tempfn_random("/foo/bar/waldo", NULL, &ret) >= 0);
+ assert_se(p = startswith(ret, "/foo/bar/.#waldo"));
+ assert_se(strlen(p) == 16);
+ assert_se(in_charset(p, "0123456789abcdef"));
+ free(ret);
+
+ assert_se(tempfn_random("/foo/bar/waldo", "[wuff]", &ret) >= 0);
+ assert_se(p = startswith(ret, "/foo/bar/.#[wuff]waldo"));
+ assert_se(strlen(p) == 16);
+ assert_se(in_charset(p, "0123456789abcdef"));
+ free(ret);
+
+ assert_se(tempfn_random_child("/foo/bar/waldo", NULL, &ret) >= 0);
+ assert_se(p = startswith(ret, "/foo/bar/waldo/.#"));
+ assert_se(strlen(p) == 16);
+ assert_se(in_charset(p, "0123456789abcdef"));
+ free(ret);
+
+ assert_se(tempfn_random_child("/foo/bar/waldo", "[kikiriki]", &ret) >= 0);
+ assert_se(p = startswith(ret, "/foo/bar/waldo/.#[kikiriki]"));
+ assert_se(strlen(p) == 16);
+ assert_se(in_charset(p, "0123456789abcdef"));
+ free(ret);
+}
+
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
@@ -439,6 +568,10 @@ int main(int argc, char *argv[]) {
test_write_string_file_no_create();
test_write_string_file_verify();
test_load_env_file_pairs();
+ test_search_and_fopen();
+ test_search_and_fopen_nulstr();
+ test_writing_tmpfile();
+ test_tempfn();
return 0;
}
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c
new file mode 100644
index 0000000000..6db2c2b6f1
--- /dev/null
+++ b/src/test/test-fs-util.c
@@ -0,0 +1,91 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fileio.h"
+#include "fd-util.h"
+#include "fs-util.h"
+#include "macro.h"
+#include "mkdir.h"
+#include "rm-rf.h"
+#include "string-util.h"
+#include "strv.h"
+#include "util.h"
+
+static void test_unlink_noerrno(void) {
+ char name[] = "/tmp/test-close_nointr.XXXXXX";
+ int fd;
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ assert_se(close_nointr(fd) >= 0);
+
+ {
+ PROTECT_ERRNO;
+ errno = -42;
+ assert_se(unlink_noerrno(name) >= 0);
+ assert_se(errno == -42);
+ assert_se(unlink_noerrno(name) < 0);
+ assert_se(errno == -42);
+ }
+}
+
+static void test_readlink_and_make_absolute(void) {
+ char tempdir[] = "/tmp/test-readlink_and_make_absolute";
+ char name[] = "/tmp/test-readlink_and_make_absolute/original";
+ char name2[] = "test-readlink_and_make_absolute/original";
+ char name_alias[] = "/tmp/test-readlink_and_make_absolute-alias";
+ char *r = NULL;
+
+ assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid()) >= 0);
+ assert_se(touch(name) >= 0);
+
+ assert_se(symlink(name, name_alias) >= 0);
+ assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
+ assert_se(streq(r, name));
+ free(r);
+ assert_se(unlink(name_alias) >= 0);
+
+ assert_se(chdir(tempdir) >= 0);
+ assert_se(symlink(name2, name_alias) >= 0);
+ assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
+ assert_se(streq(r, name));
+ free(r);
+ assert_se(unlink(name_alias) >= 0);
+
+ assert_se(rm_rf(tempdir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
+}
+
+static void test_get_files_in_directory(void) {
+ _cleanup_strv_free_ char **l = NULL, **t = NULL;
+
+ assert_se(get_files_in_directory("/tmp", &l) >= 0);
+ assert_se(get_files_in_directory(".", &t) >= 0);
+ assert_se(get_files_in_directory(".", NULL) >= 0);
+}
+
+int main(int argc, char *argv[]) {
+ test_unlink_noerrno();
+ test_readlink_and_make_absolute();
+ test_get_files_in_directory();
+
+ return 0;
+}
diff --git a/src/test/test-fstab-util.c b/src/test/test-fstab-util.c
index ea3d1a6909..63a4b8c243 100644
--- a/src/test/test-fstab-util.c
+++ b/src/test/test-fstab-util.c
@@ -131,8 +131,45 @@ static void test_fstab_yes_no_option(void) {
assert_se(fstab_test_yes_no_option("nofail,nofail=0,fail=0", "nofail\0fail\0") == false);
}
+static void test_fstab_node_to_udev_node(void) {
+ char *n;
+
+ n = fstab_node_to_udev_node("LABEL=applé/jack");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack"));
+ free(n);
+
+ n = fstab_node_to_udev_node("PARTLABEL=pinkié pie");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie"));
+ free(n);
+
+ n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
+ free(n);
+
+ n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
+ puts(n);
+ assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
+ free(n);
+
+ n = fstab_node_to_udev_node("PONIES=awesome");
+ puts(n);
+ assert_se(streq(n, "PONIES=awesome"));
+ free(n);
+
+ n = fstab_node_to_udev_node("/dev/xda1");
+ puts(n);
+ assert_se(streq(n, "/dev/xda1"));
+ free(n);
+}
+
int main(void) {
test_fstab_filter_options();
test_fstab_find_pri();
test_fstab_yes_no_option();
+ test_fstab_node_to_udev_node();
+
+ return 0;
}
diff --git a/src/test/test-glob-util.c b/src/test/test-glob-util.c
new file mode 100644
index 0000000000..227d4290f0
--- /dev/null
+++ b/src/test/test-glob-util.c
@@ -0,0 +1,50 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fileio.h"
+#include "glob-util.h"
+#include "macro.h"
+
+static void test_glob_exists(void) {
+ char name[] = "/tmp/test-glob_exists.XXXXXX";
+ int fd = -1;
+ int r;
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ close(fd);
+
+ r = glob_exists("/tmp/test-glob_exists*");
+ assert_se(r == 1);
+
+ r = unlink(name);
+ assert_se(r == 0);
+ r = glob_exists("/tmp/test-glob_exists*");
+ assert_se(r == 0);
+}
+
+int main(void) {
+ test_glob_exists();
+
+ return 0;
+}
diff --git a/src/test/test-hexdecoct.c b/src/test/test-hexdecoct.c
new file mode 100644
index 0000000000..276f25d091
--- /dev/null
+++ b/src/test/test-hexdecoct.c
@@ -0,0 +1,387 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "alloc-util.h"
+#include "hexdecoct.h"
+#include "macro.h"
+#include "string-util.h"
+
+static void test_hexchar(void) {
+ assert_se(hexchar(0xa) == 'a');
+ assert_se(hexchar(0x0) == '0');
+}
+
+static void test_unhexchar(void) {
+ assert_se(unhexchar('a') == 0xA);
+ assert_se(unhexchar('A') == 0xA);
+ assert_se(unhexchar('0') == 0x0);
+}
+
+static void test_base32hexchar(void) {
+ assert_se(base32hexchar(0) == '0');
+ assert_se(base32hexchar(9) == '9');
+ assert_se(base32hexchar(10) == 'A');
+ assert_se(base32hexchar(31) == 'V');
+}
+
+static void test_unbase32hexchar(void) {
+ assert_se(unbase32hexchar('0') == 0);
+ assert_se(unbase32hexchar('9') == 9);
+ assert_se(unbase32hexchar('A') == 10);
+ assert_se(unbase32hexchar('V') == 31);
+ assert_se(unbase32hexchar('=') == -EINVAL);
+}
+
+static void test_base64char(void) {
+ assert_se(base64char(0) == 'A');
+ assert_se(base64char(26) == 'a');
+ assert_se(base64char(63) == '/');
+}
+
+static void test_unbase64char(void) {
+ assert_se(unbase64char('A') == 0);
+ assert_se(unbase64char('Z') == 25);
+ assert_se(unbase64char('a') == 26);
+ assert_se(unbase64char('z') == 51);
+ assert_se(unbase64char('0') == 52);
+ assert_se(unbase64char('9') == 61);
+ assert_se(unbase64char('+') == 62);
+ assert_se(unbase64char('/') == 63);
+ assert_se(unbase64char('=') == -EINVAL);
+}
+
+static void test_octchar(void) {
+ assert_se(octchar(00) == '0');
+ assert_se(octchar(07) == '7');
+}
+
+static void test_unoctchar(void) {
+ assert_se(unoctchar('0') == 00);
+ assert_se(unoctchar('7') == 07);
+}
+
+static void test_decchar(void) {
+ assert_se(decchar(0) == '0');
+ assert_se(decchar(9) == '9');
+}
+
+static void test_undecchar(void) {
+ assert_se(undecchar('0') == 0);
+ assert_se(undecchar('9') == 9);
+}
+
+static void test_unhexmem(void) {
+ const char *hex = "efa214921";
+ const char *hex_invalid = "efa214921o";
+ _cleanup_free_ char *hex2 = NULL;
+ _cleanup_free_ void *mem = NULL;
+ size_t len;
+
+ assert_se(unhexmem(hex, strlen(hex), &mem, &len) == 0);
+ assert_se(unhexmem(hex, strlen(hex) + 1, &mem, &len) == -EINVAL);
+ assert_se(unhexmem(hex_invalid, strlen(hex_invalid), &mem, &len) == -EINVAL);
+
+ assert_se((hex2 = hexmem(mem, len)));
+
+ free(mem);
+
+ assert_se(memcmp(hex, hex2, strlen(hex)) == 0);
+
+ free(hex2);
+
+ assert_se(unhexmem(hex, strlen(hex) - 1, &mem, &len) == 0);
+ assert_se((hex2 = hexmem(mem, len)));
+ assert_se(memcmp(hex, hex2, strlen(hex) - 1) == 0);
+}
+
+/* https://tools.ietf.org/html/rfc4648#section-10 */
+static void test_base32hexmem(void) {
+ char *b32;
+
+ b32 = base32hexmem("", strlen(""), true);
+ assert_se(b32);
+ assert_se(streq(b32, ""));
+ free(b32);
+
+ b32 = base32hexmem("f", strlen("f"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CO======"));
+ free(b32);
+
+ b32 = base32hexmem("fo", strlen("fo"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNG===="));
+ free(b32);
+
+ b32 = base32hexmem("foo", strlen("foo"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMU==="));
+ free(b32);
+
+ b32 = base32hexmem("foob", strlen("foob"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOG="));
+ free(b32);
+
+ b32 = base32hexmem("fooba", strlen("fooba"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1"));
+ free(b32);
+
+ b32 = base32hexmem("foobar", strlen("foobar"), true);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1E8======"));
+ free(b32);
+
+ b32 = base32hexmem("", strlen(""), false);
+ assert_se(b32);
+ assert_se(streq(b32, ""));
+ free(b32);
+
+ b32 = base32hexmem("f", strlen("f"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CO"));
+ free(b32);
+
+ b32 = base32hexmem("fo", strlen("fo"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNG"));
+ free(b32);
+
+ b32 = base32hexmem("foo", strlen("foo"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMU"));
+ free(b32);
+
+ b32 = base32hexmem("foob", strlen("foob"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOG"));
+ free(b32);
+
+ b32 = base32hexmem("fooba", strlen("fooba"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1"));
+ free(b32);
+
+ b32 = base32hexmem("foobar", strlen("foobar"), false);
+ assert_se(b32);
+ assert_se(streq(b32, "CPNMUOJ1E8"));
+ free(b32);
+}
+
+static void test_unbase32hexmem(void) {
+ void *mem;
+ size_t len;
+
+ assert_se(unbase32hexmem("", strlen(""), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), ""));
+ free(mem);
+
+ assert_se(unbase32hexmem("CO======", strlen("CO======"), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "f"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNG====", strlen("CPNG===="), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMU===", strlen("CPNMU==="), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foob"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fooba"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), true, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foobar"));
+ free(mem);
+
+ assert_se(unbase32hexmem("A", strlen("A"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("A=======", strlen("A======="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAA=====", strlen("AAA====="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAA==", strlen("AAAAAA=="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AB======", strlen("AB======"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAB====", strlen("AAAB===="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAB===", strlen("AAAAB==="), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAAB=", strlen("AAAAAAB="), true, &mem, &len) == -EINVAL);
+
+ assert_se(unbase32hexmem("XPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CXNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPXMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNXUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMXOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMUXJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMUOX1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMUOJX", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
+
+ assert_se(unbase32hexmem("", strlen(""), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), ""));
+ free(mem);
+
+ assert_se(unbase32hexmem("CO", strlen("CO"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "f"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNG", strlen("CPNG"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMU", strlen("CPNMU"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foo"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOG", strlen("CPNMUOG"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foob"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fooba"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOJ1E8", strlen("CPNMUOJ1E8"), false, &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foobar"));
+ free(mem);
+
+ assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAA", strlen("AAA"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAA", strlen("AAAAAA"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AB", strlen("AB"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAB", strlen("AAAB"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAB", strlen("AAAAB"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem("AAAAAAB", strlen("AAAAAAB"), false, &mem, &len) == -EINVAL);
+}
+
+/* https://tools.ietf.org/html/rfc4648#section-10 */
+static void test_base64mem(void) {
+ char *b64;
+
+ assert_se(base64mem("", strlen(""), &b64) == 0);
+ assert_se(streq(b64, ""));
+ free(b64);
+
+ assert_se(base64mem("f", strlen("f"), &b64) == 4);
+ assert_se(streq(b64, "Zg=="));
+ free(b64);
+
+ assert_se(base64mem("fo", strlen("fo"), &b64) == 4);
+ assert_se(streq(b64, "Zm8="));
+ free(b64);
+
+ assert_se(base64mem("foo", strlen("foo"), &b64) == 4);
+ assert_se(streq(b64, "Zm9v"));
+ free(b64);
+
+ assert_se(base64mem("foob", strlen("foob"), &b64) == 8);
+ assert_se(streq(b64, "Zm9vYg=="));
+ free(b64);
+
+ assert_se(base64mem("fooba", strlen("fooba"), &b64) == 8);
+ assert_se(streq(b64, "Zm9vYmE="));
+ free(b64);
+
+ assert_se(base64mem("foobar", strlen("foobar"), &b64) == 8);
+ assert_se(streq(b64, "Zm9vYmFy"));
+ free(b64);
+}
+
+static void test_unbase64mem(void) {
+ void *mem;
+ size_t len;
+
+ assert_se(unbase64mem("", strlen(""), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), ""));
+ free(mem);
+
+ assert_se(unbase64mem("Zg==", strlen("Zg=="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "f"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm8=", strlen("Zm8="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fo"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9v", strlen("Zm9v"), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foo"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9vYg==", strlen("Zm9vYg=="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foob"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9vYmE=", strlen("Zm9vYmE="), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "fooba"));
+ free(mem);
+
+ assert_se(unbase64mem("Zm9vYmFy", strlen("Zm9vYmFy"), &mem, &len) == 0);
+ assert_se(streq(strndupa(mem, len), "foobar"));
+ free(mem);
+
+ assert_se(unbase64mem("A", strlen("A"), &mem, &len) == -EINVAL);
+ assert_se(unbase64mem("A====", strlen("A===="), &mem, &len) == -EINVAL);
+ assert_se(unbase64mem("AAB==", strlen("AAB=="), &mem, &len) == -EINVAL);
+ assert_se(unbase64mem("AAAB=", strlen("AAAB="), &mem, &len) == -EINVAL);
+}
+
+static void test_hexdump(void) {
+ uint8_t data[146];
+ unsigned i;
+
+ hexdump(stdout, NULL, 0);
+ hexdump(stdout, "", 0);
+ hexdump(stdout, "", 1);
+ hexdump(stdout, "x", 1);
+ hexdump(stdout, "x", 2);
+ hexdump(stdout, "foobar", 7);
+ hexdump(stdout, "f\nobar", 7);
+ hexdump(stdout, "xxxxxxxxxxxxxxxxxxxxyz", 23);
+
+ for (i = 0; i < ELEMENTSOF(data); i++)
+ data[i] = i*2;
+
+ hexdump(stdout, data, sizeof(data));
+}
+
+int main(int argc, char *argv[]) {
+ test_hexchar();
+ test_unhexchar();
+ test_base32hexchar();
+ test_unbase32hexchar();
+ test_base64char();
+ test_unbase64char();
+ test_octchar();
+ test_unoctchar();
+ test_decchar();
+ test_undecchar();
+ test_unhexmem();
+ test_base32hexmem();
+ test_unbase32hexmem();
+ test_base64mem();
+ test_unbase64mem();
+ test_hexdump();
+
+ return 0;
+}
diff --git a/src/test/test-io-util.c b/src/test/test-io-util.c
new file mode 100644
index 0000000000..10bd3833bc
--- /dev/null
+++ b/src/test/test-io-util.c
@@ -0,0 +1,69 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "io-util.h"
+#include "macro.h"
+
+static void test_sparse_write_one(int fd, const char *buffer, size_t n) {
+ char check[n];
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(ftruncate(fd, 0) >= 0);
+ assert_se(sparse_write(fd, buffer, n, 4) == (ssize_t) n);
+
+ assert_se(lseek(fd, 0, SEEK_CUR) == (off_t) n);
+ assert_se(ftruncate(fd, n) >= 0);
+
+ assert_se(lseek(fd, 0, SEEK_SET) == 0);
+ assert_se(read(fd, check, n) == (ssize_t) n);
+
+ assert_se(memcmp(buffer, check, n) == 0);
+}
+
+static void test_sparse_write(void) {
+ const char test_a[] = "test";
+ const char test_b[] = "\0\0\0\0test\0\0\0\0";
+ const char test_c[] = "\0\0test\0\0\0\0";
+ const char test_d[] = "\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0\0\0\0";
+ const char test_e[] = "test\0\0\0\0test";
+ _cleanup_close_ int fd = -1;
+ char fn[] = "/tmp/sparseXXXXXX";
+
+ fd = mkostemp(fn, O_CLOEXEC);
+ assert_se(fd >= 0);
+ unlink(fn);
+
+ test_sparse_write_one(fd, test_a, sizeof(test_a));
+ test_sparse_write_one(fd, test_b, sizeof(test_b));
+ test_sparse_write_one(fd, test_c, sizeof(test_c));
+ test_sparse_write_one(fd, test_d, sizeof(test_d));
+ test_sparse_write_one(fd, test_e, sizeof(test_e));
+}
+
+int main(void) {
+ test_sparse_write();
+
+ return 0;
+}
diff --git a/src/test/test-ipcrm.c b/src/test/test-ipcrm.c
index 2464d32458..c5bcaf47bb 100644
--- a/src/test/test-ipcrm.c
+++ b/src/test/test-ipcrm.c
@@ -23,9 +23,14 @@
int main(int argc, char *argv[]) {
uid_t uid;
-
- assert_se(argc == 2);
- assert_se(parse_uid(argv[1], &uid) >= 0);
+ int r;
+ const char* name = argv[1] ?: "nfsnobody";
+
+ r = get_user_creds(&name, &uid, NULL, NULL, NULL);
+ if (r < 0) {
+ log_error_errno(r, "Failed to resolve \"%s\": %m", name);
+ return EXIT_FAILURE;
+ }
return clean_ipc(uid) < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/test/test-libudev.c b/src/test/test-libudev.c
index a7eb60e8cf..e28de9b37b 100644
--- a/src/test/test-libudev.c
+++ b/src/test/test-libudev.c
@@ -24,170 +24,140 @@
#include "libudev.h"
+#include "fd-util.h"
+#include "log.h"
#include "stdio-util.h"
#include "string-util.h"
#include "udev-util.h"
#include "util.h"
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
static void print_device(struct udev_device *device) {
const char *str;
dev_t devnum;
int count;
struct udev_list_entry *list_entry;
- printf("*** device: %p ***\n", device);
+ log_info("*** device: %p ***", device);
str = udev_device_get_action(device);
if (str != NULL)
- printf("action: '%s'\n", str);
+ log_info("action: '%s'", str);
str = udev_device_get_syspath(device);
- printf("syspath: '%s'\n", str);
+ log_info("syspath: '%s'", str);
str = udev_device_get_sysname(device);
- printf("sysname: '%s'\n", str);
+ log_info("sysname: '%s'", str);
str = udev_device_get_sysnum(device);
if (str != NULL)
- printf("sysnum: '%s'\n", str);
+ log_info("sysnum: '%s'", str);
str = udev_device_get_devpath(device);
- printf("devpath: '%s'\n", str);
+ log_info("devpath: '%s'", str);
str = udev_device_get_subsystem(device);
if (str != NULL)
- printf("subsystem: '%s'\n", str);
+ log_info("subsystem: '%s'", str);
str = udev_device_get_devtype(device);
if (str != NULL)
- printf("devtype: '%s'\n", str);
+ log_info("devtype: '%s'", str);
str = udev_device_get_driver(device);
if (str != NULL)
- printf("driver: '%s'\n", str);
+ log_info("driver: '%s'", str);
str = udev_device_get_devnode(device);
if (str != NULL)
- printf("devname: '%s'\n", str);
+ log_info("devname: '%s'", str);
devnum = udev_device_get_devnum(device);
if (major(devnum) > 0)
- printf("devnum: %u:%u\n", major(devnum), minor(devnum));
+ log_info("devnum: %u:%u", major(devnum), minor(devnum));
count = 0;
udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device)) {
- printf("link: '%s'\n", udev_list_entry_get_name(list_entry));
+ log_info("link: '%s'", udev_list_entry_get_name(list_entry));
count++;
}
if (count > 0)
- printf("found %i links\n", count);
+ log_info("found %i links", count);
count = 0;
udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(device)) {
- printf("property: '%s=%s'\n",
+ log_info("property: '%s=%s'",
udev_list_entry_get_name(list_entry),
udev_list_entry_get_value(list_entry));
count++;
}
if (count > 0)
- printf("found %i properties\n", count);
+ log_info("found %i properties", count);
str = udev_device_get_property_value(device, "MAJOR");
if (str != NULL)
- printf("MAJOR: '%s'\n", str);
+ log_info("MAJOR: '%s'", str);
str = udev_device_get_sysattr_value(device, "dev");
if (str != NULL)
- printf("attr{dev}: '%s'\n", str);
-
- printf("\n");
+ log_info("attr{dev}: '%s'", str);
}
-static int test_device(struct udev *udev, const char *syspath) {
+static void test_device(struct udev *udev, const char *syspath) {
_cleanup_udev_device_unref_ struct udev_device *device;
- printf("looking at device: %s\n", syspath);
+ log_info("looking at device: %s", syspath);
device = udev_device_new_from_syspath(udev, syspath);
- if (device == NULL) {
- printf("no device found\n");
- return -1;
- }
- print_device(device);
-
- return 0;
+ if (device == NULL)
+ log_warning_errno(errno, "udev_device_new_from_syspath: %m");
+ else
+ print_device(device);
}
-static int test_device_parents(struct udev *udev, const char *syspath) {
+static void test_device_parents(struct udev *udev, const char *syspath) {
_cleanup_udev_device_unref_ struct udev_device *device;
struct udev_device *device_parent;
- printf("looking at device: %s\n", syspath);
+ log_info("looking at device: %s", syspath);
device = udev_device_new_from_syspath(udev, syspath);
if (device == NULL)
- return -1;
+ return;
- printf("looking at parents\n");
+ log_info("looking at parents");
device_parent = device;
do {
print_device(device_parent);
device_parent = udev_device_get_parent(device_parent);
} while (device_parent != NULL);
- printf("looking at parents again\n");
+ log_info("looking at parents again");
device_parent = device;
do {
print_device(device_parent);
device_parent = udev_device_get_parent(device_parent);
} while (device_parent != NULL);
-
- return 0;
}
-static int test_device_devnum(struct udev *udev) {
+static void test_device_devnum(struct udev *udev) {
dev_t devnum = makedev(1, 3);
- struct udev_device *device;
+ _cleanup_udev_device_unref_ struct udev_device *device;
- printf("looking up device: %u:%u\n", major(devnum), minor(devnum));
+ log_info("looking up device: %u:%u", major(devnum), minor(devnum));
device = udev_device_new_from_devnum(udev, 'c', devnum);
if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
- return 0;
+ log_warning_errno(errno, "udev_device_new_from_devnum: %m");
+ else
+ print_device(device);
}
-static int test_device_subsys_name(struct udev *udev) {
- struct udev_device *device;
-
- printf("looking up device: 'block':'sda'\n");
- device = udev_device_new_from_subsystem_sysname(udev, "block", "sda");
- if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
-
- printf("looking up device: 'subsystem':'pci'\n");
- device = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci");
- if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
-
- printf("looking up device: 'drivers':'scsi:sd'\n");
- device = udev_device_new_from_subsystem_sysname(udev, "drivers", "scsi:sd");
- if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
+static void test_device_subsys_name(struct udev *udev, const char *subsys, const char *dev) {
+ _cleanup_udev_device_unref_ struct udev_device *device;
- printf("looking up device: 'module':'printk'\n");
- device = udev_device_new_from_subsystem_sysname(udev, "module", "printk");
+ log_info("looking up device: '%s:%s'", subsys, dev);
+ device = udev_device_new_from_subsystem_sysname(udev, subsys, dev);
if (device == NULL)
- return -1;
- print_device(device);
- udev_device_unref(device);
- return 0;
+ log_warning_errno(errno, "udev_device_new_from_subsystem_sysname: %m");
+ else
+ print_device(device);
}
static int test_enumerate_print_list(struct udev_enumerate *enumerate) {
@@ -200,63 +170,45 @@ static int test_enumerate_print_list(struct udev_enumerate *enumerate) {
device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate),
udev_list_entry_get_name(list_entry));
if (device != NULL) {
- printf("device: '%s' (%s)\n",
- udev_device_get_syspath(device),
- udev_device_get_subsystem(device));
+ log_info("device: '%s' (%s)",
+ udev_device_get_syspath(device),
+ udev_device_get_subsystem(device));
udev_device_unref(device);
count++;
}
}
- printf("found %i devices\n\n", count);
+ log_info("found %i devices", count);
return count;
}
-static int test_monitor(struct udev *udev) {
- struct udev_monitor *udev_monitor = NULL;
- int fd_ep;
- int fd_udev = -1;
- struct epoll_event ep_udev, ep_stdin;
+static void test_monitor(struct udev *udev) {
+ _cleanup_udev_monitor_unref_ struct udev_monitor *udev_monitor;
+ _cleanup_close_ int fd_ep;
+ int fd_udev;
+ struct epoll_event ep_udev = {
+ .events = EPOLLIN,
+ }, ep_stdin = {
+ .events = EPOLLIN,
+ .data.fd = STDIN_FILENO,
+ };
fd_ep = epoll_create1(EPOLL_CLOEXEC);
- if (fd_ep < 0) {
- printf("error creating epoll fd: %m\n");
- goto out;
- }
+ assert_se(fd_ep >= 0);
udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
- if (udev_monitor == NULL) {
- printf("no socket\n");
- goto out;
- }
+ assert_se(udev_monitor != NULL);
+
fd_udev = udev_monitor_get_fd(udev_monitor);
+ ep_udev.data.fd = fd_udev;
- if (udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "block", NULL) < 0 ||
- udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL) < 0 ||
- udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device") < 0) {
- printf("filter failed\n");
- goto out;
- }
+ assert_se(udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "block", NULL) >= 0);
+ assert_se(udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL) >= 0);
+ assert_se(udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device") >= 0);
- if (udev_monitor_enable_receiving(udev_monitor) < 0) {
- printf("bind failed\n");
- goto out;
- }
+ assert_se(udev_monitor_enable_receiving(udev_monitor) >= 0);
- memzero(&ep_udev, sizeof(struct epoll_event));
- ep_udev.events = EPOLLIN;
- ep_udev.data.fd = fd_udev;
- if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) < 0) {
- printf("fail to add fd to epoll: %m\n");
- goto out;
- }
-
- memzero(&ep_stdin, sizeof(struct epoll_event));
- ep_stdin.events = EPOLLIN;
- ep_stdin.data.fd = STDIN_FILENO;
- if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, STDIN_FILENO, &ep_stdin) < 0) {
- printf("fail to add fd to epoll: %m\n");
- goto out;
- }
+ assert_se(epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) >= 0);
+ assert_se(epoll_ctl(fd_ep, EPOLL_CTL_ADD, STDIN_FILENO, &ep_stdin) >= 0);
for (;;) {
int fdcount;
@@ -265,7 +217,7 @@ static int test_monitor(struct udev *udev) {
int i;
printf("waiting for events from udev, press ENTER to exit\n");
- fdcount = epoll_wait(fd_ep, ev, ARRAY_SIZE(ev), -1);
+ fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), -1);
printf("epoll fd count: %i\n", fdcount);
for (i = 0; i < fdcount; i++) {
@@ -279,36 +231,29 @@ static int test_monitor(struct udev *udev) {
udev_device_unref(device);
} else if (ev[i].data.fd == STDIN_FILENO && ev[i].events & EPOLLIN) {
printf("exiting loop\n");
- goto out;
+ return;
}
}
}
-out:
- if (fd_ep >= 0)
- close(fd_ep);
- udev_monitor_unref(udev_monitor);
- return 0;
}
-static int test_queue(struct udev *udev) {
+static void test_queue(struct udev *udev) {
struct udev_queue *udev_queue;
+ bool empty;
udev_queue = udev_queue_new(udev);
- if (udev_queue == NULL)
- return -1;
-
- if (udev_queue_get_queue_is_empty(udev_queue))
- printf("queue is empty\n");
+ assert_se(udev_queue);
+ empty = udev_queue_get_queue_is_empty(udev_queue);
+ log_info("queue is %s", empty ? "empty" : "not empty");
udev_queue_unref(udev_queue);
- return 0;
}
static int test_enumerate(struct udev *udev, const char *subsystem) {
struct udev_enumerate *udev_enumerate;
int r;
- printf("enumerate '%s'\n", subsystem == NULL ? "<all>" : subsystem);
+ log_info("enumerate '%s'", subsystem == NULL ? "<all>" : subsystem);
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -317,7 +262,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'net' + duplicated scan + null + zero\n");
+ log_info("enumerate 'net' + duplicated scan + null + zero");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -337,7 +282,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'block'\n");
+ log_info("enumerate 'block'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -351,7 +296,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'not block'\n");
+ log_info("enumerate 'not block'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -360,7 +305,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'pci, mem, vc'\n");
+ log_info("enumerate 'pci, mem, vc'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -371,7 +316,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'subsystem'\n");
+ log_info("enumerate 'subsystem'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -379,7 +324,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) {
test_enumerate_print_list(udev_enumerate);
udev_enumerate_unref(udev_enumerate);
- printf("enumerate 'property IF_FS_*=filesystem'\n");
+ log_info("enumerate 'property IF_FS_*=filesystem'");
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
@@ -397,32 +342,32 @@ static void test_hwdb(struct udev *udev, const char *modalias) {
hwdb = udev_hwdb_new(udev);
udev_list_entry_foreach(entry, udev_hwdb_get_properties_list_entry(hwdb, modalias, 0))
- printf("'%s'='%s'\n", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry));
- printf("\n");
+ log_info("'%s'='%s'", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry));
hwdb = udev_hwdb_unref(hwdb);
assert_se(hwdb == NULL);
}
int main(int argc, char *argv[]) {
- struct udev *udev = NULL;
+ _cleanup_udev_unref_ struct udev *udev = NULL;
+ bool arg_monitor = false;
static const struct option options[] = {
- { "syspath", required_argument, NULL, 'p' },
+ { "syspath", required_argument, NULL, 'p' },
{ "subsystem", required_argument, NULL, 's' },
- { "debug", no_argument, NULL, 'd' },
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, 'V' },
+ { "debug", no_argument, NULL, 'd' },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' },
+ { "monitor", no_argument, NULL, 'm' },
{}
};
const char *syspath = "/devices/virtual/mem/null";
const char *subsystem = NULL;
- char path[1024];
int c;
udev = udev_new();
- printf("context: %p\n", udev);
+ log_info("context: %p", udev);
if (udev == NULL) {
- printf("no context\n");
+ log_info("no context");
return 1;
}
@@ -444,14 +389,18 @@ int main(int argc, char *argv[]) {
case 'h':
printf("--debug --syspath= --subsystem= --help\n");
- goto out;
+ return EXIT_SUCCESS;
case 'V':
printf("%s\n", VERSION);
- goto out;
+ return EXIT_SUCCESS;
+
+ case 'm':
+ arg_monitor = true;
+ break;
case '?':
- goto out;
+ return EXIT_FAILURE;
default:
assert_not_reached("Unhandled option code.");
@@ -459,14 +408,16 @@ int main(int argc, char *argv[]) {
/* add sys path if needed */
- if (!startswith(syspath, "/sys")) {
- xsprintf(path, "/sys/%s", syspath);
- syspath = path;
- }
+ if (!startswith(syspath, "/sys"))
+ syspath = strjoina("/sys/", syspath);
test_device(udev, syspath);
test_device_devnum(udev);
- test_device_subsys_name(udev);
+ test_device_subsys_name(udev, "block", "sda");
+ test_device_subsys_name(udev, "subsystem", "pci");
+ test_device_subsys_name(udev, "drivers", "scsi:sd");
+ test_device_subsys_name(udev, "module", "printk");
+
test_device_parents(udev, syspath);
test_enumerate(udev, subsystem);
@@ -475,8 +426,8 @@ int main(int argc, char *argv[]) {
test_hwdb(udev, "usb:v0D50p0011*");
- test_monitor(udev);
-out:
- udev_unref(udev);
- return 0;
+ if (arg_monitor)
+ test_monitor(udev);
+
+ return EXIT_SUCCESS;
}
diff --git a/src/test/test-loopback.c b/src/test/test-loopback.c
index 2748395ade..7b67337331 100644
--- a/src/test/test-loopback.c
+++ b/src/test/test-loopback.c
@@ -31,7 +31,7 @@ int main(int argc, char* argv[]) {
r = loopback_setup();
if (r < 0)
- fprintf(stderr, "loopback: %s\n", strerror(-r));
+ log_error("loopback: %m");
- return 0;
+ return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
index 53a585290a..d376dd56c5 100644
--- a/src/test/test-path-util.c
+++ b/src/test/test-path-util.c
@@ -433,6 +433,50 @@ static void test_path_is_mount_point(void) {
assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
}
+static void test_file_in_same_dir(void) {
+ char *t;
+
+ t = file_in_same_dir("/", "a");
+ assert_se(streq(t, "/a"));
+ free(t);
+
+ t = file_in_same_dir("/", "/a");
+ assert_se(streq(t, "/a"));
+ free(t);
+
+ t = file_in_same_dir("", "a");
+ assert_se(streq(t, "a"));
+ free(t);
+
+ t = file_in_same_dir("a/", "a");
+ assert_se(streq(t, "a/a"));
+ free(t);
+
+ t = file_in_same_dir("bar/foo", "bar");
+ assert_se(streq(t, "bar/bar"));
+ free(t);
+}
+
+static void test_filename_is_valid(void) {
+ char foo[FILENAME_MAX+2];
+ int i;
+
+ assert_se(!filename_is_valid(""));
+ assert_se(!filename_is_valid("/bar/foo"));
+ assert_se(!filename_is_valid("/"));
+ assert_se(!filename_is_valid("."));
+ assert_se(!filename_is_valid(".."));
+
+ for (i=0; i<FILENAME_MAX+1; i++)
+ foo[i] = 'a';
+ foo[FILENAME_MAX+1] = '\0';
+
+ assert_se(!filename_is_valid(foo));
+
+ assert_se(filename_is_valid("foo_bar-333"));
+ assert_se(filename_is_valid("o.o"));
+}
+
int main(int argc, char **argv) {
test_path();
test_find_binary(argv[0]);
@@ -444,6 +488,8 @@ int main(int argc, char **argv) {
test_path_startswith();
test_prefix_root();
test_path_is_mount_point();
+ test_file_in_same_dir();
+ test_filename_is_valid();
return 0;
}
diff --git a/src/test/test-proc-cmdline.c b/src/test/test-proc-cmdline.c
new file mode 100644
index 0000000000..a7a8f621a2
--- /dev/null
+++ b/src/test/test-proc-cmdline.c
@@ -0,0 +1,52 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "alloc-util.h"
+#include "log.h"
+#include "macro.h"
+#include "proc-cmdline.h"
+#include "special.h"
+#include "string-util.h"
+
+static int parse_item(const char *key, const char *value) {
+ assert_se(key);
+
+ log_info("kernel cmdline option <%s> = <%s>", key, strna(value));
+ return 0;
+}
+
+static void test_parse_proc_cmdline(void) {
+ assert_se(parse_proc_cmdline(parse_item) >= 0);
+}
+
+static void test_runlevel_to_target(void) {
+ assert_se(streq_ptr(runlevel_to_target(NULL), NULL));
+ assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL));
+ assert_se(streq_ptr(runlevel_to_target("3"), SPECIAL_MULTI_USER_TARGET));
+}
+
+int main(void) {
+ log_parse_environment();
+ log_open();
+
+ test_parse_proc_cmdline();
+ test_runlevel_to_target();
+
+ return 0;
+}
diff --git a/src/test/test-selinux.c b/src/test/test-selinux.c
new file mode 100644
index 0000000000..7545ad3764
--- /dev/null
+++ b/src/test/test-selinux.c
@@ -0,0 +1,122 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2016 Zbigniew Jędrzejewski-Szmek
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <sys/stat.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "log.h"
+#include "selinux-util.h"
+#include "string-util.h"
+#include "time-util.h"
+#include "util.h"
+
+static void test_testing(void) {
+ bool b;
+
+ log_info("============ %s ==========", __func__);
+
+ b = mac_selinux_use();
+ log_info("mac_selinux_use → %s", yes_no(b));
+
+ b = mac_selinux_have();
+ log_info("mac_selinux_have → %s", yes_no(b));
+
+ mac_selinux_retest();
+
+ b = mac_selinux_use();
+ log_info("mac_selinux_use → %s", yes_no(b));
+
+ b = mac_selinux_have();
+ log_info("mac_selinux_have → %s", yes_no(b));
+}
+
+static void test_loading(void) {
+ usec_t n1, n2;
+ int r;
+
+ log_info("============ %s ==========", __func__);
+
+ n1 = now(CLOCK_MONOTONIC);
+ r = mac_selinux_init();
+ n2 = now(CLOCK_MONOTONIC);
+ log_info_errno(r, "mac_selinux_init → %d (%m) %.2fs", r, (n2 - n1)/1e6);
+}
+
+static void test_cleanup(void) {
+ usec_t n1, n2;
+
+ log_info("============ %s ==========", __func__);
+
+ n1 = now(CLOCK_MONOTONIC);
+ mac_selinux_finish();
+ n2 = now(CLOCK_MONOTONIC);
+ log_info("mac_selinux_finish → %.2fs", (n2 - n1)/1e6);
+}
+
+static void test_misc(const char* fname) {
+ _cleanup_(mac_selinux_freep) char *label = NULL, *label2 = NULL, *label3 = NULL;
+ int r;
+ _cleanup_close_ int fd = -1;
+
+ log_info("============ %s ==========", __func__);
+
+ r = mac_selinux_get_our_label(&label);
+ log_info_errno(r, "mac_selinux_get_our_label → %d (%m), \"%s\"",
+ r, strnull(label));
+
+ r = mac_selinux_get_create_label_from_exe(fname, &label2);
+ log_info_errno(r, "mac_selinux_create_label_from_exe → %d (%m), \"%s\"",
+ r, strnull(label2));
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ assert_se(fd >= 0);
+
+ r = mac_selinux_get_child_mls_label(fd, fname, label2, &label3);
+ log_info_errno(r, "mac_selinux_get_child_mls_label → %d (%m), \"%s\"",
+ r, strnull(label3));
+}
+
+static void test_create_file_prepare(const char* fname) {
+ int r;
+
+ log_info("============ %s ==========", __func__);
+
+ r = mac_selinux_create_file_prepare(fname, S_IRWXU);
+ log_info_errno(r, "mac_selinux_create_file_prepare → %d (%m)", r);
+
+ mac_selinux_create_file_clear();
+}
+
+int main(int argc, char **argv) {
+ const char *path = SYSTEMD_BINARY_PATH;
+ if (argc >= 2)
+ path = argv[1];
+
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+
+ test_testing();
+ test_loading();
+ test_misc(path);
+ test_create_file_prepare(path);
+ test_cleanup();
+
+ return 0;
+}
diff --git a/src/test/test-signal-util.c b/src/test/test-signal-util.c
index 3083501ce9..671eb869cb 100644
--- a/src/test/test-signal-util.c
+++ b/src/test/test-signal-util.c
@@ -17,6 +17,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <signal.h>
+#include <unistd.h>
+
+#include "macro.h"
#include "signal-util.h"
static void test_block_signals(void) {
@@ -44,6 +48,20 @@ static void test_block_signals(void) {
assert_se(sigismember(&ss, SIGVTALRM) == 0);
}
+static void test_ignore_signals(void) {
+ assert_se(ignore_signals(SIGINT, -1) >= 0);
+ assert_se(kill(getpid(), SIGINT) >= 0);
+ assert_se(ignore_signals(SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
+ assert_se(kill(getpid(), SIGUSR1) >= 0);
+ assert_se(kill(getpid(), SIGUSR2) >= 0);
+ assert_se(kill(getpid(), SIGTERM) >= 0);
+ assert_se(kill(getpid(), SIGPIPE) >= 0);
+ assert_se(default_signals(SIGINT, SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
+}
+
int main(int argc, char *argv[]) {
test_block_signals();
+ test_ignore_signals();
+
+ return 0;
}
diff --git a/src/test/test-sizeof.c b/src/test/test-sizeof.c
new file mode 100644
index 0000000000..8f99a13772
--- /dev/null
+++ b/src/test/test-sizeof.c
@@ -0,0 +1,53 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2016 Zbigniew Jędrzejewski-Szmek
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "log.h"
+#include "time-util.h"
+
+/* Print information about various types. Useful when diagnosing
+ * gcc diagnostics on an unfamiliar architecture. */
+
+#pragma GCC diagnostic ignored "-Wtype-limits"
+
+#define info(t) \
+ log_info("%s → %zu bits%s", STRINGIFY(t), \
+ sizeof(t)*CHAR_BIT, \
+ strstr(STRINGIFY(t), "signed") ? "" : \
+ ((t)-1 < (t)0 ? ", signed" : ", unsigned"));
+
+int main(void) {
+ info(char);
+ info(signed char);
+ info(unsigned char);
+ info(short unsigned);
+ info(unsigned);
+ info(long unsigned);
+ info(long long unsigned);
+
+ info(float);
+ info(double);
+ info(long double);
+
+ info(size_t);
+ info(ssize_t);
+ info(time_t);
+ info(usec_t);
+
+ return 0;
+}
diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c
new file mode 100644
index 0000000000..a10227f823
--- /dev/null
+++ b/src/test/test-stat-util.c
@@ -0,0 +1,68 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "macro.h"
+#include "stat-util.h"
+
+static void test_files_same(void) {
+ _cleanup_close_ int fd = -1;
+ char name[] = "/tmp/test-files_same.XXXXXX";
+ char name_alias[] = "/tmp/test-files_same.alias";
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ assert_se(symlink(name, name_alias) >= 0);
+
+ assert_se(files_same(name, name));
+ assert_se(files_same(name, name_alias));
+
+ unlink(name);
+ unlink(name_alias);
+}
+
+static void test_is_symlink(void) {
+ char name[] = "/tmp/test-is_symlink.XXXXXX";
+ char name_link[] = "/tmp/test-is_symlink.link";
+ _cleanup_close_ int fd = -1;
+
+ fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
+ assert_se(fd >= 0);
+ assert_se(symlink(name, name_link) >= 0);
+
+ assert_se(is_symlink(name) == 0);
+ assert_se(is_symlink(name_link) == 1);
+ assert_se(is_symlink("/a/file/which/does/not/exist/i/guess") < 0);
+
+
+ unlink(name);
+ unlink(name_link);
+}
+
+int main(int argc, char *argv[]) {
+ test_files_same();
+ test_is_symlink();
+
+ return 0;
+}
diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c
index 9b48e95998..d0f84d70bc 100644
--- a/src/test/test-string-util.c
+++ b/src/test/test-string-util.c
@@ -17,7 +17,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
+#include "macro.h"
#include "string-util.h"
+#include "strv.h"
static void test_string_erase(void) {
char *x;
@@ -97,9 +100,271 @@ static void test_ascii_strcasecmp_nn(void) {
assert_se(ascii_strcasecmp_nn("BBbb", 4, "aaaa", 4) > 0);
}
+static void test_streq_ptr(void) {
+ assert_se(streq_ptr(NULL, NULL));
+ assert_se(!streq_ptr("abc", "cdef"));
+}
+
+static void test_strstrip(void) {
+ char *r;
+ char input[] = " hello, waldo. ";
+
+ r = strstrip(input);
+ assert_se(streq(r, "hello, waldo."));
+}
+
+static void test_strextend(void) {
+ _cleanup_free_ char *str = strdup("0123");
+ strextend(&str, "456", "78", "9", NULL);
+ assert_se(streq(str, "0123456789"));
+}
+
+static void test_strrep(void) {
+ _cleanup_free_ char *one, *three, *zero;
+ one = strrep("waldo", 1);
+ three = strrep("waldo", 3);
+ zero = strrep("waldo", 0);
+
+ assert_se(streq(one, "waldo"));
+ assert_se(streq(three, "waldowaldowaldo"));
+ assert_se(streq(zero, ""));
+}
+
+
+static void test_strappend(void) {
+ _cleanup_free_ char *t1, *t2, *t3, *t4;
+
+ t1 = strappend(NULL, NULL);
+ assert_se(streq(t1, ""));
+
+ t2 = strappend(NULL, "suf");
+ assert_se(streq(t2, "suf"));
+
+ t3 = strappend("pre", NULL);
+ assert_se(streq(t3, "pre"));
+
+ t4 = strappend("pre", "suf");
+ assert_se(streq(t4, "presuf"));
+}
+
+static void test_string_has_cc(void) {
+ assert_se(string_has_cc("abc\1", NULL));
+ assert_se(string_has_cc("abc\x7f", NULL));
+ assert_se(string_has_cc("abc\x7f", NULL));
+ assert_se(string_has_cc("abc\t\x7f", "\t"));
+ assert_se(string_has_cc("abc\t\x7f", "\t"));
+ assert_se(string_has_cc("\x7f", "\t"));
+ assert_se(string_has_cc("\x7f", "\t\a"));
+
+ assert_se(!string_has_cc("abc\t\t", "\t"));
+ assert_se(!string_has_cc("abc\t\t\a", "\t\a"));
+ assert_se(!string_has_cc("a\ab\tc", "\t\a"));
+}
+
+static void test_ascii_strlower(void) {
+ char a[] = "AabBcC Jk Ii Od LKJJJ kkd LK";
+ assert_se(streq(ascii_strlower(a), "aabbcc jk ii od lkjjj kkd lk"));
+}
+
+static void test_strshorten(void) {
+ char s[] = "foobar";
+
+ assert_se(strlen(strshorten(s, 6)) == 6);
+ assert_se(strlen(strshorten(s, 12)) == 6);
+ assert_se(strlen(strshorten(s, 2)) == 2);
+ assert_se(strlen(strshorten(s, 0)) == 0);
+}
+
+static void test_strjoina(void) {
+ char *actual;
+
+ actual = strjoina("", "foo", "bar");
+ assert_se(streq(actual, "foobar"));
+
+ actual = strjoina("foo", "bar", "baz");
+ assert_se(streq(actual, "foobarbaz"));
+
+ actual = strjoina("foo", "", "bar", "baz");
+ assert_se(streq(actual, "foobarbaz"));
+
+ actual = strjoina("foo");
+ assert_se(streq(actual, "foo"));
+
+ actual = strjoina(NULL);
+ assert_se(streq(actual, ""));
+
+ actual = strjoina(NULL, "foo");
+ assert_se(streq(actual, ""));
+
+ actual = strjoina("foo", NULL, "bar");
+ assert_se(streq(actual, "foo"));
+}
+
+static void test_strcmp_ptr(void) {
+ assert_se(strcmp_ptr(NULL, NULL) == 0);
+ assert_se(strcmp_ptr("", NULL) > 0);
+ assert_se(strcmp_ptr("foo", NULL) > 0);
+ assert_se(strcmp_ptr(NULL, "") < 0);
+ assert_se(strcmp_ptr(NULL, "bar") < 0);
+ assert_se(strcmp_ptr("foo", "bar") > 0);
+ assert_se(strcmp_ptr("bar", "baz") < 0);
+ assert_se(strcmp_ptr("foo", "foo") == 0);
+ assert_se(strcmp_ptr("", "") == 0);
+}
+
+static void test_foreach_word(void) {
+ const char *word, *state;
+ size_t l;
+ int i = 0;
+ const char test[] = "test abc d\te f ";
+ const char * const expected[] = {
+ "test",
+ "abc",
+ "d",
+ "e",
+ "f",
+ "",
+ NULL
+ };
+
+ FOREACH_WORD(word, l, test, state)
+ assert_se(strneq(expected[i++], word, l));
+}
+
+static void check(const char *test, char** expected, bool trailing) {
+ const char *word, *state;
+ size_t l;
+ int i = 0;
+
+ printf("<<<%s>>>\n", test);
+ FOREACH_WORD_QUOTED(word, l, test, state) {
+ _cleanup_free_ char *t = NULL;
+
+ assert_se(t = strndup(word, l));
+ assert_se(strneq(expected[i++], word, l));
+ printf("<%s>\n", t);
+ }
+ printf("<<<%s>>>\n", state);
+ assert_se(expected[i] == NULL);
+ assert_se(isempty(state) == !trailing);
+}
+
+static void test_foreach_word_quoted(void) {
+ check("test a b c 'd' e '' '' hhh '' '' \"a b c\"",
+ STRV_MAKE("test",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "",
+ "",
+ "hhh",
+ "",
+ "",
+ "a b c"),
+ false);
+
+ check("test \"xxx",
+ STRV_MAKE("test"),
+ true);
+
+ check("test\\",
+ STRV_MAKE_EMPTY,
+ true);
+}
+
+static void test_endswith(void) {
+ assert_se(endswith("foobar", "bar"));
+ assert_se(endswith("foobar", ""));
+ assert_se(endswith("foobar", "foobar"));
+ assert_se(endswith("", ""));
+
+ assert_se(!endswith("foobar", "foo"));
+ assert_se(!endswith("foobar", "foobarfoofoo"));
+}
+
+static void test_endswith_no_case(void) {
+ assert_se(endswith_no_case("fooBAR", "bar"));
+ assert_se(endswith_no_case("foobar", ""));
+ assert_se(endswith_no_case("foobar", "FOOBAR"));
+ assert_se(endswith_no_case("", ""));
+
+ assert_se(!endswith_no_case("foobar", "FOO"));
+ assert_se(!endswith_no_case("foobar", "FOOBARFOOFOO"));
+}
+
+static void test_delete_chars(void) {
+ char *r;
+ char input[] = " hello, waldo. abc";
+
+ r = delete_chars(input, WHITESPACE);
+ assert_se(streq(r, "hello,waldo.abc"));
+}
+
+static void test_in_charset(void) {
+ assert_se(in_charset("dddaaabbbcccc", "abcd"));
+ assert_se(!in_charset("dddaaabbbcccc", "abc f"));
+}
+
+static void test_split_pair(void) {
+ _cleanup_free_ char *a = NULL, *b = NULL;
+
+ assert_se(split_pair("", "", &a, &b) == -EINVAL);
+ assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
+ assert_se(split_pair("", "=", &a, &b) == -EINVAL);
+ assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
+ assert_se(streq(a, "foo"));
+ assert_se(streq(b, "bar"));
+ free(a);
+ free(b);
+ assert_se(split_pair("==", "==", &a, &b) >= 0);
+ assert_se(streq(a, ""));
+ assert_se(streq(b, ""));
+ free(a);
+ free(b);
+
+ assert_se(split_pair("===", "==", &a, &b) >= 0);
+ assert_se(streq(a, ""));
+ assert_se(streq(b, "="));
+}
+
+static void test_first_word(void) {
+ assert_se(first_word("Hello", ""));
+ assert_se(first_word("Hello", "Hello"));
+ assert_se(first_word("Hello world", "Hello"));
+ assert_se(first_word("Hello\tworld", "Hello"));
+ assert_se(first_word("Hello\nworld", "Hello"));
+ assert_se(first_word("Hello\rworld", "Hello"));
+ assert_se(first_word("Hello ", "Hello"));
+
+ assert_se(!first_word("Hello", "Hellooo"));
+ assert_se(!first_word("Hello", "xxxxx"));
+ assert_se(!first_word("Hellooo", "Hello"));
+}
+
int main(int argc, char *argv[]) {
test_string_erase();
test_ascii_strcasecmp_n();
test_ascii_strcasecmp_nn();
+ test_streq_ptr();
+ test_strstrip();
+ test_strextend();
+ test_strrep();
+ test_strappend();
+ test_string_has_cc();
+ test_ascii_strlower();
+ test_strshorten();
+ test_strjoina();
+ test_strcmp_ptr();
+ test_foreach_word();
+ test_foreach_word_quoted();
+ test_endswith();
+ test_endswith_no_case();
+ test_delete_chars();
+ test_in_charset();
+ test_split_pair();
+ test_first_word();
+
return 0;
}
diff --git a/src/test/test-strv.c b/src/test/test-strv.c
index ef451c6abf..fea1f848cd 100644
--- a/src/test/test-strv.c
+++ b/src/test/test-strv.c
@@ -660,6 +660,25 @@ static void test_strv_make_nulstr(void) {
test_strv_make_nulstr_one(STRV_MAKE("foo", "bar", "quuux"));
}
+static void test_foreach_string(void) {
+ const char * const t[] = {
+ "foo",
+ "bar",
+ "waldo",
+ NULL
+ };
+ const char *x;
+ unsigned i = 0;
+
+ FOREACH_STRING(x, "foo", "bar", "waldo")
+ assert_se(streq_ptr(t[i++], x));
+
+ assert_se(i == 3);
+
+ FOREACH_STRING(x, "zzz")
+ assert_se(streq(x, "zzz"));
+}
+
int main(int argc, char *argv[]) {
test_specifier_printf();
test_strv_foreach();
@@ -724,5 +743,7 @@ int main(int argc, char *argv[]) {
test_strv_extend_n();
test_strv_make_nulstr();
+ test_foreach_string();
+
return 0;
}
diff --git a/src/test/test-udev.c b/src/test/test-udev.c
index 9cc64f7c68..d01789fe08 100644
--- a/src/test/test-udev.c
+++ b/src/test/test-udev.c
@@ -93,7 +93,7 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
log_debug("version %s", VERSION);
- mac_selinux_init("/dev");
+ mac_selinux_init();
action = argv[1];
if (action == NULL) {
diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c
index 42c6a8d5e2..8d1ec19f17 100644
--- a/src/test/test-user-util.c
+++ b/src/test/test-user-util.c
@@ -37,6 +37,30 @@ static void test_gid_to_name_one(gid_t gid, const char *name) {
assert_se(streq_ptr(t, name));
}
+static void test_parse_uid(void) {
+ int r;
+ uid_t uid;
+
+ r = parse_uid("100", &uid);
+ assert_se(r == 0);
+ assert_se(uid == 100);
+
+ r = parse_uid("65535", &uid);
+ assert_se(r == -ENXIO);
+
+ r = parse_uid("asdsdas", &uid);
+ assert_se(r == -EINVAL);
+}
+
+static void test_uid_ptr(void) {
+
+ assert_se(UID_TO_PTR(0) != NULL);
+ assert_se(UID_TO_PTR(1000) != NULL);
+
+ assert_se(PTR_TO_UID(UID_TO_PTR(0)) == 0);
+ assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000);
+}
+
int main(int argc, char*argv[]) {
test_uid_to_name_one(0, "root");
@@ -48,5 +72,8 @@ int main(int argc, char*argv[]) {
test_gid_to_name_one(0xFFFF, "65535");
test_gid_to_name_one(0xFFFFFFFF, "4294967295");
+ test_parse_uid();
+ test_uid_ptr();
+
return 0;
}
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 9a8a265790..05cb1eae76 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -19,47 +19,16 @@
***/
#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
#include <string.h>
-#include <sys/types.h>
#include <sys/wait.h>
-#include <sys/xattr.h>
#include <unistd.h>
-#include "alloc-util.h"
-#include "conf-parser.h"
-#include "cpu-set-util.h"
#include "def.h"
-#include "escape.h"
-#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
-#include "fstab-util.h"
-#include "glob-util.h"
-#include "hexdecoct.h"
-#include "io-util.h"
-#include "mkdir.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "proc-cmdline.h"
-#include "process-util.h"
#include "rm-rf.h"
-#include "signal-util.h"
-#include "special.h"
-#include "stat-util.h"
#include "string-util.h"
-#include "strv.h"
-#include "user-util.h"
#include "util.h"
-#include "virt.h"
-#include "web-util.h"
-#include "xattr-util.h"
-
-static void test_streq_ptr(void) {
- assert_se(streq_ptr(NULL, NULL));
- assert_se(!streq_ptr("abc", "cdef"));
-}
static void test_align_power2(void) {
unsigned long i, p2;
@@ -151,19 +120,6 @@ static void test_container_of(void) {
v1) == &myval);
}
-static void test_alloca(void) {
- static const uint8_t zero[997] = { };
- char *t;
-
- t = alloca_align(17, 512);
- assert_se(!((uintptr_t)t & 0xff));
- memzero(t, 17);
-
- t = alloca0_align(997, 1024);
- assert_se(!((uintptr_t)t & 0x1ff));
- assert_se(!memcmp(t, zero, 997));
-}
-
static void test_div_round_up(void) {
int div;
@@ -197,544 +153,6 @@ static void test_div_round_up(void) {
assert_se(0xfffffffdU / 10U + !!(0xfffffffdU % 10U) == 429496730U);
}
-static void test_first_word(void) {
- assert_se(first_word("Hello", ""));
- assert_se(first_word("Hello", "Hello"));
- assert_se(first_word("Hello world", "Hello"));
- assert_se(first_word("Hello\tworld", "Hello"));
- assert_se(first_word("Hello\nworld", "Hello"));
- assert_se(first_word("Hello\rworld", "Hello"));
- assert_se(first_word("Hello ", "Hello"));
-
- assert_se(!first_word("Hello", "Hellooo"));
- assert_se(!first_word("Hello", "xxxxx"));
- assert_se(!first_word("Hellooo", "Hello"));
-}
-
-static void test_close_many(void) {
- int fds[3];
- char name0[] = "/tmp/test-close-many.XXXXXX";
- char name1[] = "/tmp/test-close-many.XXXXXX";
- char name2[] = "/tmp/test-close-many.XXXXXX";
-
- fds[0] = mkostemp_safe(name0, O_RDWR|O_CLOEXEC);
- fds[1] = mkostemp_safe(name1, O_RDWR|O_CLOEXEC);
- fds[2] = mkostemp_safe(name2, O_RDWR|O_CLOEXEC);
-
- close_many(fds, 2);
-
- assert_se(fcntl(fds[0], F_GETFD) == -1);
- assert_se(fcntl(fds[1], F_GETFD) == -1);
- assert_se(fcntl(fds[2], F_GETFD) >= 0);
-
- safe_close(fds[2]);
-
- unlink(name0);
- unlink(name1);
- unlink(name2);
-}
-
-static void test_parse_uid(void) {
- int r;
- uid_t uid;
-
- r = parse_uid("100", &uid);
- assert_se(r == 0);
- assert_se(uid == 100);
-
- r = parse_uid("65535", &uid);
- assert_se(r == -ENXIO);
-
- r = parse_uid("asdsdas", &uid);
- assert_se(r == -EINVAL);
-}
-
-static void test_strappend(void) {
- _cleanup_free_ char *t1, *t2, *t3, *t4;
-
- t1 = strappend(NULL, NULL);
- assert_se(streq(t1, ""));
-
- t2 = strappend(NULL, "suf");
- assert_se(streq(t2, "suf"));
-
- t3 = strappend("pre", NULL);
- assert_se(streq(t3, "pre"));
-
- t4 = strappend("pre", "suf");
- assert_se(streq(t4, "presuf"));
-}
-
-static void test_strstrip(void) {
- char *r;
- char input[] = " hello, waldo. ";
-
- r = strstrip(input);
- assert_se(streq(r, "hello, waldo."));
-}
-
-static void test_delete_chars(void) {
- char *r;
- char input[] = " hello, waldo. abc";
-
- r = delete_chars(input, WHITESPACE);
- assert_se(streq(r, "hello,waldo.abc"));
-}
-
-static void test_in_charset(void) {
- assert_se(in_charset("dddaaabbbcccc", "abcd"));
- assert_se(!in_charset("dddaaabbbcccc", "abc f"));
-}
-
-static void test_hexchar(void) {
- assert_se(hexchar(0xa) == 'a');
- assert_se(hexchar(0x0) == '0');
-}
-
-static void test_unhexchar(void) {
- assert_se(unhexchar('a') == 0xA);
- assert_se(unhexchar('A') == 0xA);
- assert_se(unhexchar('0') == 0x0);
-}
-
-static void test_base32hexchar(void) {
- assert_se(base32hexchar(0) == '0');
- assert_se(base32hexchar(9) == '9');
- assert_se(base32hexchar(10) == 'A');
- assert_se(base32hexchar(31) == 'V');
-}
-
-static void test_unbase32hexchar(void) {
- assert_se(unbase32hexchar('0') == 0);
- assert_se(unbase32hexchar('9') == 9);
- assert_se(unbase32hexchar('A') == 10);
- assert_se(unbase32hexchar('V') == 31);
- assert_se(unbase32hexchar('=') == -EINVAL);
-}
-
-static void test_base64char(void) {
- assert_se(base64char(0) == 'A');
- assert_se(base64char(26) == 'a');
- assert_se(base64char(63) == '/');
-}
-
-static void test_unbase64char(void) {
- assert_se(unbase64char('A') == 0);
- assert_se(unbase64char('Z') == 25);
- assert_se(unbase64char('a') == 26);
- assert_se(unbase64char('z') == 51);
- assert_se(unbase64char('0') == 52);
- assert_se(unbase64char('9') == 61);
- assert_se(unbase64char('+') == 62);
- assert_se(unbase64char('/') == 63);
- assert_se(unbase64char('=') == -EINVAL);
-}
-
-static void test_octchar(void) {
- assert_se(octchar(00) == '0');
- assert_se(octchar(07) == '7');
-}
-
-static void test_unoctchar(void) {
- assert_se(unoctchar('0') == 00);
- assert_se(unoctchar('7') == 07);
-}
-
-static void test_decchar(void) {
- assert_se(decchar(0) == '0');
- assert_se(decchar(9) == '9');
-}
-
-static void test_undecchar(void) {
- assert_se(undecchar('0') == 0);
- assert_se(undecchar('9') == 9);
-}
-
-static void test_unhexmem(void) {
- const char *hex = "efa214921";
- const char *hex_invalid = "efa214921o";
- _cleanup_free_ char *hex2 = NULL;
- _cleanup_free_ void *mem = NULL;
- size_t len;
-
- assert_se(unhexmem(hex, strlen(hex), &mem, &len) == 0);
- assert_se(unhexmem(hex, strlen(hex) + 1, &mem, &len) == -EINVAL);
- assert_se(unhexmem(hex_invalid, strlen(hex_invalid), &mem, &len) == -EINVAL);
-
- assert_se((hex2 = hexmem(mem, len)));
-
- free(mem);
-
- assert_se(memcmp(hex, hex2, strlen(hex)) == 0);
-
- free(hex2);
-
- assert_se(unhexmem(hex, strlen(hex) - 1, &mem, &len) == 0);
- assert_se((hex2 = hexmem(mem, len)));
- assert_se(memcmp(hex, hex2, strlen(hex) - 1) == 0);
-}
-
-/* https://tools.ietf.org/html/rfc4648#section-10 */
-static void test_base32hexmem(void) {
- char *b32;
-
- b32 = base32hexmem("", strlen(""), true);
- assert_se(b32);
- assert_se(streq(b32, ""));
- free(b32);
-
- b32 = base32hexmem("f", strlen("f"), true);
- assert_se(b32);
- assert_se(streq(b32, "CO======"));
- free(b32);
-
- b32 = base32hexmem("fo", strlen("fo"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNG===="));
- free(b32);
-
- b32 = base32hexmem("foo", strlen("foo"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNMU==="));
- free(b32);
-
- b32 = base32hexmem("foob", strlen("foob"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOG="));
- free(b32);
-
- b32 = base32hexmem("fooba", strlen("fooba"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOJ1"));
- free(b32);
-
- b32 = base32hexmem("foobar", strlen("foobar"), true);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOJ1E8======"));
- free(b32);
-
- b32 = base32hexmem("", strlen(""), false);
- assert_se(b32);
- assert_se(streq(b32, ""));
- free(b32);
-
- b32 = base32hexmem("f", strlen("f"), false);
- assert_se(b32);
- assert_se(streq(b32, "CO"));
- free(b32);
-
- b32 = base32hexmem("fo", strlen("fo"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNG"));
- free(b32);
-
- b32 = base32hexmem("foo", strlen("foo"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNMU"));
- free(b32);
-
- b32 = base32hexmem("foob", strlen("foob"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOG"));
- free(b32);
-
- b32 = base32hexmem("fooba", strlen("fooba"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOJ1"));
- free(b32);
-
- b32 = base32hexmem("foobar", strlen("foobar"), false);
- assert_se(b32);
- assert_se(streq(b32, "CPNMUOJ1E8"));
- free(b32);
-}
-
-static void test_unbase32hexmem(void) {
- void *mem;
- size_t len;
-
- assert_se(unbase32hexmem("", strlen(""), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase32hexmem("CO======", strlen("CO======"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNG====", strlen("CPNG===="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMU===", strlen("CPNMU==="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
-
- assert_se(unbase32hexmem("A", strlen("A"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A=======", strlen("A======="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAA=====", strlen("AAA====="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAA==", strlen("AAAAAA=="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AB======", strlen("AB======"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAB====", strlen("AAAB===="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAB===", strlen("AAAAB==="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAAB=", strlen("AAAAAAB="), true, &mem, &len) == -EINVAL);
-
- assert_se(unbase32hexmem("XPNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CXNMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPXMUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNXUOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMXOJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUXJ1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOX1", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOJX", strlen("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
-
- assert_se(unbase32hexmem("", strlen(""), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase32hexmem("CO", strlen("CO"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNG", strlen("CPNG"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMU", strlen("CPNMU"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG", strlen("CPNMUOG"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1", strlen("CPNMUOJ1"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1E8", strlen("CPNMUOJ1E8"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG=", strlen("CPNMUOG="), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOJ1E8======", strlen("CPNMUOJ1E8======"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A", strlen("A"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAA", strlen("AAA"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAA", strlen("AAAAAA"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AB", strlen("AB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAB", strlen("AAAB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAB", strlen("AAAAB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAAB", strlen("AAAAAAB"), false, &mem, &len) == -EINVAL);
-}
-
-/* https://tools.ietf.org/html/rfc4648#section-10 */
-static void test_base64mem(void) {
- char *b64;
-
- assert_se(base64mem("", strlen(""), &b64) == 0);
- assert_se(streq(b64, ""));
- free(b64);
-
- assert_se(base64mem("f", strlen("f"), &b64) == 4);
- assert_se(streq(b64, "Zg=="));
- free(b64);
-
- assert_se(base64mem("fo", strlen("fo"), &b64) == 4);
- assert_se(streq(b64, "Zm8="));
- free(b64);
-
- assert_se(base64mem("foo", strlen("foo"), &b64) == 4);
- assert_se(streq(b64, "Zm9v"));
- free(b64);
-
- assert_se(base64mem("foob", strlen("foob"), &b64) == 8);
- assert_se(streq(b64, "Zm9vYg=="));
- free(b64);
-
- assert_se(base64mem("fooba", strlen("fooba"), &b64) == 8);
- assert_se(streq(b64, "Zm9vYmE="));
- free(b64);
-
- assert_se(base64mem("foobar", strlen("foobar"), &b64) == 8);
- assert_se(streq(b64, "Zm9vYmFy"));
- free(b64);
-}
-
-static void test_unbase64mem(void) {
- void *mem;
- size_t len;
-
- assert_se(unbase64mem("", strlen(""), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase64mem("Zg==", strlen("Zg=="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase64mem("Zm8=", strlen("Zm8="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
-
- assert_se(unbase64mem("Zm9v", strlen("Zm9v"), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
-
- assert_se(unbase64mem("Zm9vYg==", strlen("Zm9vYg=="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase64mem("Zm9vYmE=", strlen("Zm9vYmE="), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
-
- assert_se(unbase64mem("Zm9vYmFy", strlen("Zm9vYmFy"), &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
-
- assert_se(unbase64mem("A", strlen("A"), &mem, &len) == -EINVAL);
- assert_se(unbase64mem("A====", strlen("A===="), &mem, &len) == -EINVAL);
- assert_se(unbase64mem("AAB==", strlen("AAB=="), &mem, &len) == -EINVAL);
- assert_se(unbase64mem("AAAB=", strlen("AAAB="), &mem, &len) == -EINVAL);
-}
-
-static void test_cescape(void) {
- _cleanup_free_ char *escaped;
-
- assert_se(escaped = cescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313"));
- assert_se(streq(escaped, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\a\\003\\177\\234\\313"));
-}
-
-static void test_cunescape(void) {
- _cleanup_free_ char *unescaped;
-
- assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", 0, &unescaped) < 0);
- assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "abc\\\"\b\f\a\n\r\t\v\003\177\234\313\\000\\x00"));
- unescaped = mfree(unescaped);
-
- /* incomplete sequences */
- assert_se(cunescape("\\x0", 0, &unescaped) < 0);
- assert_se(cunescape("\\x0", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\x0"));
- unescaped = mfree(unescaped);
-
- assert_se(cunescape("\\x", 0, &unescaped) < 0);
- assert_se(cunescape("\\x", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\x"));
- unescaped = mfree(unescaped);
-
- assert_se(cunescape("\\", 0, &unescaped) < 0);
- assert_se(cunescape("\\", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\"));
- unescaped = mfree(unescaped);
-
- assert_se(cunescape("\\11", 0, &unescaped) < 0);
- assert_se(cunescape("\\11", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\11"));
- unescaped = mfree(unescaped);
-
- assert_se(cunescape("\\1", 0, &unescaped) < 0);
- assert_se(cunescape("\\1", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "\\1"));
- unescaped = mfree(unescaped);
-
- assert_se(cunescape("\\u0000", 0, &unescaped) < 0);
- assert_se(cunescape("\\u00DF\\U000000df\\u03a0\\U00000041", UNESCAPE_RELAX, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, "ßßΠA"));
- unescaped = mfree(unescaped);
-
- assert_se(cunescape("\\073", 0, &unescaped) >= 0);
- assert_se(streq_ptr(unescaped, ";"));
-}
-
-static void test_foreach_word(void) {
- const char *word, *state;
- size_t l;
- int i = 0;
- const char test[] = "test abc d\te f ";
- const char * const expected[] = {
- "test",
- "abc",
- "d",
- "e",
- "f",
- "",
- NULL
- };
-
- FOREACH_WORD(word, l, test, state)
- assert_se(strneq(expected[i++], word, l));
-}
-
-static void check(const char *test, char** expected, bool trailing) {
- const char *word, *state;
- size_t l;
- int i = 0;
-
- printf("<<<%s>>>\n", test);
- FOREACH_WORD_QUOTED(word, l, test, state) {
- _cleanup_free_ char *t = NULL;
-
- assert_se(t = strndup(word, l));
- assert_se(strneq(expected[i++], word, l));
- printf("<%s>\n", t);
- }
- printf("<<<%s>>>\n", state);
- assert_se(expected[i] == NULL);
- assert_se(isempty(state) == !trailing);
-}
-
-static void test_foreach_word_quoted(void) {
- check("test a b c 'd' e '' '' hhh '' '' \"a b c\"",
- STRV_MAKE("test",
- "a",
- "b",
- "c",
- "d",
- "e",
- "",
- "",
- "hhh",
- "",
- "",
- "a b c"),
- false);
-
- check("test \"xxx",
- STRV_MAKE("test"),
- true);
-
- check("test\\",
- STRV_MAKE_EMPTY,
- true);
-}
-
-static void test_memdup_multiply(void) {
- int org[] = {1, 2, 3};
- int *dup;
-
- dup = (int*)memdup_multiply(org, sizeof(int), 3);
-
- assert_se(dup);
- assert_se(dup[0] == 1);
- assert_se(dup[1] == 2);
- assert_se(dup[2] == 3);
- free(dup);
-}
-
static void test_u64log2(void) {
assert_se(u64log2(0) == 0);
assert_se(u64log2(8) == 3);
@@ -754,210 +172,6 @@ static void test_protect_errno(void) {
assert_se(errno == 12);
}
-static void test_parse_cpu_set(void) {
- cpu_set_t *c = NULL;
- int ncpus;
- int cpu;
-
- /* Simple range (from CPUAffinity example) */
- ncpus = parse_cpu_set_and_warn("1 2", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
- assert_se(CPU_ISSET_S(2, CPU_ALLOC_SIZE(ncpus), c));
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 2);
- c = mfree(c);
-
- /* A more interesting range */
- ncpus = parse_cpu_set_and_warn("0 1 2 3 8 9 10 11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
- for (cpu = 0; cpu < 4; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Quoted strings */
- ncpus = parse_cpu_set_and_warn("8 '9' 10 \"11\"", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 4);
- for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Use commas as separators */
- ncpus = parse_cpu_set_and_warn("0,1,2,3 8,9,10,11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
- for (cpu = 0; cpu < 4; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Commas with spaces (and trailing comma, space) */
- ncpus = parse_cpu_set_and_warn("0, 1, 2, 3, 4, 5, 6, 7, ", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
- for (cpu = 0; cpu < 8; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Ranges */
- ncpus = parse_cpu_set_and_warn("0-3,8-11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
- for (cpu = 0; cpu < 4; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Ranges with trailing comma, space */
- ncpus = parse_cpu_set_and_warn("0-3 8-11, ", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
- for (cpu = 0; cpu < 4; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- for (cpu = 8; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Negative range (returns empty cpu_set) */
- ncpus = parse_cpu_set_and_warn("3-0", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 0);
- c = mfree(c);
-
- /* Overlapping ranges */
- ncpus = parse_cpu_set_and_warn("0-7 4-11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 12);
- for (cpu = 0; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Mix ranges and individual CPUs */
- ncpus = parse_cpu_set_and_warn("0,1 4-11", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus >= 1024);
- assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 10);
- assert_se(CPU_ISSET_S(0, CPU_ALLOC_SIZE(ncpus), c));
- assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
- for (cpu = 4; cpu < 12; cpu++)
- assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
- c = mfree(c);
-
- /* Garbage */
- ncpus = parse_cpu_set_and_warn("0 1 2 3 garbage", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus < 0);
- assert_se(!c);
-
- /* Range with garbage */
- ncpus = parse_cpu_set_and_warn("0-3 8-garbage", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus < 0);
- assert_se(!c);
-
- /* Empty string */
- c = NULL;
- ncpus = parse_cpu_set_and_warn("", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus == 0); /* empty string returns 0 */
- assert_se(!c);
-
- /* Runnaway quoted string */
- ncpus = parse_cpu_set_and_warn("0 1 2 3 \"4 5 6 7 ", &c, NULL, "fake", 1, "CPUAffinity");
- assert_se(ncpus < 0);
- assert_se(!c);
-}
-
-static void test_config_parse_iec_uint64(void) {
- uint64_t offset = 0;
- assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0);
- assert_se(offset == 4 * 1024 * 1024);
-
- assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0);
-}
-
-static void test_strextend(void) {
- _cleanup_free_ char *str = strdup("0123");
- strextend(&str, "456", "78", "9", NULL);
- assert_se(streq(str, "0123456789"));
-}
-
-static void test_strrep(void) {
- _cleanup_free_ char *one, *three, *zero;
- one = strrep("waldo", 1);
- three = strrep("waldo", 3);
- zero = strrep("waldo", 0);
-
- assert_se(streq(one, "waldo"));
- assert_se(streq(three, "waldowaldowaldo"));
- assert_se(streq(zero, ""));
-}
-
-static void test_split_pair(void) {
- _cleanup_free_ char *a = NULL, *b = NULL;
-
- assert_se(split_pair("", "", &a, &b) == -EINVAL);
- assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL);
- assert_se(split_pair("", "=", &a, &b) == -EINVAL);
- assert_se(split_pair("foo=bar", "=", &a, &b) >= 0);
- assert_se(streq(a, "foo"));
- assert_se(streq(b, "bar"));
- free(a);
- free(b);
- assert_se(split_pair("==", "==", &a, &b) >= 0);
- assert_se(streq(a, ""));
- assert_se(streq(b, ""));
- free(a);
- free(b);
-
- assert_se(split_pair("===", "==", &a, &b) >= 0);
- assert_se(streq(a, ""));
- assert_se(streq(b, "="));
-}
-
-static void test_fstab_node_to_udev_node(void) {
- char *n;
-
- n = fstab_node_to_udev_node("LABEL=applé/jack");
- puts(n);
- assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack"));
- free(n);
-
- n = fstab_node_to_udev_node("PARTLABEL=pinkié pie");
- puts(n);
- assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie"));
- free(n);
-
- n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
- puts(n);
- assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
- free(n);
-
- n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535");
- puts(n);
- assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535"));
- free(n);
-
- n = fstab_node_to_udev_node("PONIES=awesome");
- puts(n);
- assert_se(streq(n, "PONIES=awesome"));
- free(n);
-
- n = fstab_node_to_udev_node("/dev/xda1");
- puts(n);
- assert_se(streq(n, "/dev/xda1"));
- free(n);
-}
-
-static void test_get_files_in_directory(void) {
- _cleanup_strv_free_ char **l = NULL, **t = NULL;
-
- assert_se(get_files_in_directory("/tmp", &l) >= 0);
- assert_se(get_files_in_directory(".", &t) >= 0);
- assert_se(get_files_in_directory(".", NULL) >= 0);
-}
-
static void test_in_set(void) {
assert_se(IN_SET(1, 1));
assert_se(IN_SET(1, 1, 2, 3, 4));
@@ -968,50 +182,6 @@ static void test_in_set(void) {
assert_se(!IN_SET(0, 1, 2, 3, 4));
}
-static void test_writing_tmpfile(void) {
- char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
- _cleanup_free_ char *contents = NULL;
- size_t size;
- int fd, r;
- struct iovec iov[3];
-
- IOVEC_SET_STRING(iov[0], "abc\n");
- IOVEC_SET_STRING(iov[1], ALPHANUMERICAL "\n");
- IOVEC_SET_STRING(iov[2], "");
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- printf("tmpfile: %s", name);
-
- r = writev(fd, iov, 3);
- assert_se(r >= 0);
-
- r = read_full_file(name, &contents, &size);
- assert_se(r == 0);
- printf("contents: %s", contents);
- assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
-
- unlink(name);
-}
-
-static void test_hexdump(void) {
- uint8_t data[146];
- unsigned i;
-
- hexdump(stdout, NULL, 0);
- hexdump(stdout, "", 0);
- hexdump(stdout, "", 1);
- hexdump(stdout, "x", 1);
- hexdump(stdout, "x", 2);
- hexdump(stdout, "foobar", 7);
- hexdump(stdout, "f\nobar", 7);
- hexdump(stdout, "xxxxxxxxxxxxxxxxxxxxyz", 23);
-
- for (i = 0; i < ELEMENTSOF(data); i++)
- data[i] = i*2;
-
- hexdump(stdout, data, sizeof(data));
-}
-
static void test_log2i(void) {
assert_se(log2i(1) == 0);
assert_se(log2i(2) == 1);
@@ -1023,341 +193,6 @@ static void test_log2i(void) {
assert_se(log2i(INT_MAX) == sizeof(int)*8-2);
}
-static void test_foreach_string(void) {
- const char * const t[] = {
- "foo",
- "bar",
- "waldo",
- NULL
- };
- const char *x;
- unsigned i = 0;
-
- FOREACH_STRING(x, "foo", "bar", "waldo")
- assert_se(streq_ptr(t[i++], x));
-
- assert_se(i == 3);
-
- FOREACH_STRING(x, "zzz")
- assert_se(streq(x, "zzz"));
-}
-
-static void test_filename_is_valid(void) {
- char foo[FILENAME_MAX+2];
- int i;
-
- assert_se(!filename_is_valid(""));
- assert_se(!filename_is_valid("/bar/foo"));
- assert_se(!filename_is_valid("/"));
- assert_se(!filename_is_valid("."));
- assert_se(!filename_is_valid(".."));
-
- for (i=0; i<FILENAME_MAX+1; i++)
- foo[i] = 'a';
- foo[FILENAME_MAX+1] = '\0';
-
- assert_se(!filename_is_valid(foo));
-
- assert_se(filename_is_valid("foo_bar-333"));
- assert_se(filename_is_valid("o.o"));
-}
-
-static void test_string_has_cc(void) {
- assert_se(string_has_cc("abc\1", NULL));
- assert_se(string_has_cc("abc\x7f", NULL));
- assert_se(string_has_cc("abc\x7f", NULL));
- assert_se(string_has_cc("abc\t\x7f", "\t"));
- assert_se(string_has_cc("abc\t\x7f", "\t"));
- assert_se(string_has_cc("\x7f", "\t"));
- assert_se(string_has_cc("\x7f", "\t\a"));
-
- assert_se(!string_has_cc("abc\t\t", "\t"));
- assert_se(!string_has_cc("abc\t\t\a", "\t\a"));
- assert_se(!string_has_cc("a\ab\tc", "\t\a"));
-}
-
-static void test_ascii_strlower(void) {
- char a[] = "AabBcC Jk Ii Od LKJJJ kkd LK";
- assert_se(streq(ascii_strlower(a), "aabbcc jk ii od lkjjj kkd lk"));
-}
-
-static void test_files_same(void) {
- _cleanup_close_ int fd = -1;
- char name[] = "/tmp/test-files_same.XXXXXX";
- char name_alias[] = "/tmp/test-files_same.alias";
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- assert_se(symlink(name, name_alias) >= 0);
-
- assert_se(files_same(name, name));
- assert_se(files_same(name, name_alias));
-
- unlink(name);
- unlink(name_alias);
-}
-
-static void test_is_valid_documentation_url(void) {
- assert_se(documentation_url_is_valid("http://www.freedesktop.org/wiki/Software/systemd"));
- assert_se(documentation_url_is_valid("https://www.kernel.org/doc/Documentation/binfmt_misc.txt"));
- assert_se(documentation_url_is_valid("file:/foo/foo"));
- assert_se(documentation_url_is_valid("man:systemd.special(7)"));
- assert_se(documentation_url_is_valid("info:bar"));
-
- assert_se(!documentation_url_is_valid("foo:"));
- assert_se(!documentation_url_is_valid("info:"));
- assert_se(!documentation_url_is_valid(""));
-}
-
-static void test_file_in_same_dir(void) {
- char *t;
-
- t = file_in_same_dir("/", "a");
- assert_se(streq(t, "/a"));
- free(t);
-
- t = file_in_same_dir("/", "/a");
- assert_se(streq(t, "/a"));
- free(t);
-
- t = file_in_same_dir("", "a");
- assert_se(streq(t, "a"));
- free(t);
-
- t = file_in_same_dir("a/", "a");
- assert_se(streq(t, "a/a"));
- free(t);
-
- t = file_in_same_dir("bar/foo", "bar");
- assert_se(streq(t, "bar/bar"));
- free(t);
-}
-
-static void test_endswith(void) {
- assert_se(endswith("foobar", "bar"));
- assert_se(endswith("foobar", ""));
- assert_se(endswith("foobar", "foobar"));
- assert_se(endswith("", ""));
-
- assert_se(!endswith("foobar", "foo"));
- assert_se(!endswith("foobar", "foobarfoofoo"));
-}
-
-static void test_endswith_no_case(void) {
- assert_se(endswith_no_case("fooBAR", "bar"));
- assert_se(endswith_no_case("foobar", ""));
- assert_se(endswith_no_case("foobar", "FOOBAR"));
- assert_se(endswith_no_case("", ""));
-
- assert_se(!endswith_no_case("foobar", "FOO"));
- assert_se(!endswith_no_case("foobar", "FOOBARFOOFOO"));
-}
-
-static void test_close_nointr(void) {
- char name[] = "/tmp/test-test-close_nointr.XXXXXX";
- int fd;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- assert_se(close_nointr(fd) >= 0);
- assert_se(close_nointr(fd) < 0);
-
- unlink(name);
-}
-
-
-static void test_unlink_noerrno(void) {
- char name[] = "/tmp/test-close_nointr.XXXXXX";
- int fd;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- assert_se(close_nointr(fd) >= 0);
-
- {
- PROTECT_ERRNO;
- errno = -42;
- assert_se(unlink_noerrno(name) >= 0);
- assert_se(errno == -42);
- assert_se(unlink_noerrno(name) < 0);
- assert_se(errno == -42);
- }
-}
-
-static void test_readlink_and_make_absolute(void) {
- char tempdir[] = "/tmp/test-readlink_and_make_absolute";
- char name[] = "/tmp/test-readlink_and_make_absolute/original";
- char name2[] = "test-readlink_and_make_absolute/original";
- char name_alias[] = "/tmp/test-readlink_and_make_absolute-alias";
- char *r = NULL;
-
- assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid()) >= 0);
- assert_se(touch(name) >= 0);
-
- assert_se(symlink(name, name_alias) >= 0);
- assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
- assert_se(streq(r, name));
- free(r);
- assert_se(unlink(name_alias) >= 0);
-
- assert_se(chdir(tempdir) >= 0);
- assert_se(symlink(name2, name_alias) >= 0);
- assert_se(readlink_and_make_absolute(name_alias, &r) >= 0);
- assert_se(streq(r, name));
- free(r);
- assert_se(unlink(name_alias) >= 0);
-
- assert_se(rm_rf(tempdir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
-}
-
-static void test_ignore_signals(void) {
- assert_se(ignore_signals(SIGINT, -1) >= 0);
- assert_se(kill(getpid(), SIGINT) >= 0);
- assert_se(ignore_signals(SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
- assert_se(kill(getpid(), SIGUSR1) >= 0);
- assert_se(kill(getpid(), SIGUSR2) >= 0);
- assert_se(kill(getpid(), SIGTERM) >= 0);
- assert_se(kill(getpid(), SIGPIPE) >= 0);
- assert_se(default_signals(SIGINT, SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0);
-}
-
-static void test_strshorten(void) {
- char s[] = "foobar";
-
- assert_se(strlen(strshorten(s, 6)) == 6);
- assert_se(strlen(strshorten(s, 12)) == 6);
- assert_se(strlen(strshorten(s, 2)) == 2);
- assert_se(strlen(strshorten(s, 0)) == 0);
-}
-
-static void test_strjoina(void) {
- char *actual;
-
- actual = strjoina("", "foo", "bar");
- assert_se(streq(actual, "foobar"));
-
- actual = strjoina("foo", "bar", "baz");
- assert_se(streq(actual, "foobarbaz"));
-
- actual = strjoina("foo", "", "bar", "baz");
- assert_se(streq(actual, "foobarbaz"));
-
- actual = strjoina("foo");
- assert_se(streq(actual, "foo"));
-
- actual = strjoina(NULL);
- assert_se(streq(actual, ""));
-
- actual = strjoina(NULL, "foo");
- assert_se(streq(actual, ""));
-
- actual = strjoina("foo", NULL, "bar");
- assert_se(streq(actual, "foo"));
-}
-
-static void test_is_symlink(void) {
- char name[] = "/tmp/test-is_symlink.XXXXXX";
- char name_link[] = "/tmp/test-is_symlink.link";
- _cleanup_close_ int fd = -1;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- assert_se(symlink(name, name_link) >= 0);
-
- assert_se(is_symlink(name) == 0);
- assert_se(is_symlink(name_link) == 1);
- assert_se(is_symlink("/a/file/which/does/not/exist/i/guess") < 0);
-
-
- unlink(name);
- unlink(name_link);
-}
-
-static void test_search_and_fopen(void) {
- const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
- char name[] = "/tmp/test-search_and_fopen.XXXXXX";
- int fd = -1;
- int r;
- FILE *f;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- close(fd);
-
- r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen(name, "r", NULL, dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen(basename(name), "r", "/", dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
- assert_se(r < 0);
- r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
- assert_se(r < 0);
-
- r = unlink(name);
- assert_se(r == 0);
-
- r = search_and_fopen(basename(name), "r", NULL, dirs, &f);
- assert_se(r < 0);
-}
-
-
-static void test_search_and_fopen_nulstr(void) {
- const char dirs[] = "/tmp/foo/bar\0/tmp\0";
- char name[] = "/tmp/test-search_and_fopen.XXXXXX";
- int fd = -1;
- int r;
- FILE *f;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- close(fd);
-
- r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f);
- assert_se(r >= 0);
- fclose(f);
-
- r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f);
- assert_se(r < 0);
- r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f);
- assert_se(r < 0);
-
- r = unlink(name);
- assert_se(r == 0);
-
- r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f);
- assert_se(r < 0);
-}
-
-static void test_glob_exists(void) {
- char name[] = "/tmp/test-glob_exists.XXXXXX";
- int fd = -1;
- int r;
-
- fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
- assert_se(fd >= 0);
- close(fd);
-
- r = glob_exists("/tmp/test-glob_exists*");
- assert_se(r == 1);
-
- r = unlink(name);
- assert_se(r == 0);
- r = glob_exists("/tmp/test-glob_exists*");
- assert_se(r == 0);
-}
-
static void test_execute_directory(void) {
char template_lo[] = "/tmp/test-readlink_and_make_absolute-lo.XXXXXXX";
char template_hi[] = "/tmp/test-readlink_and_make_absolute-hi.XXXXXXX";
@@ -1402,17 +237,6 @@ static void test_execute_directory(void) {
(void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL);
}
-static int parse_item(const char *key, const char *value) {
- assert_se(key);
-
- log_info("kernel cmdline option <%s> = <%s>", key, strna(value));
- return 0;
-}
-
-static void test_parse_proc_cmdline(void) {
- assert_se(parse_proc_cmdline(parse_item) >= 0);
-}
-
static void test_raw_clone(void) {
pid_t parent, pid, pid2;
@@ -1438,285 +262,20 @@ static void test_raw_clone(void) {
}
}
-static void test_same_fd(void) {
- _cleanup_close_pair_ int p[2] = { -1, -1 };
- _cleanup_close_ int a = -1, b = -1, c = -1;
-
- assert_se(pipe2(p, O_CLOEXEC) >= 0);
- assert_se((a = dup(p[0])) >= 0);
- assert_se((b = open("/dev/null", O_RDONLY|O_CLOEXEC)) >= 0);
- assert_se((c = dup(a)) >= 0);
-
- assert_se(same_fd(p[0], p[0]) > 0);
- assert_se(same_fd(p[1], p[1]) > 0);
- assert_se(same_fd(a, a) > 0);
- assert_se(same_fd(b, b) > 0);
-
- assert_se(same_fd(a, p[0]) > 0);
- assert_se(same_fd(p[0], a) > 0);
- assert_se(same_fd(c, p[0]) > 0);
- assert_se(same_fd(p[0], c) > 0);
- assert_se(same_fd(a, c) > 0);
- assert_se(same_fd(c, a) > 0);
-
- assert_se(same_fd(p[0], p[1]) == 0);
- assert_se(same_fd(p[1], p[0]) == 0);
- assert_se(same_fd(p[0], b) == 0);
- assert_se(same_fd(b, p[0]) == 0);
- assert_se(same_fd(p[1], a) == 0);
- assert_se(same_fd(a, p[1]) == 0);
- assert_se(same_fd(p[1], b) == 0);
- assert_se(same_fd(b, p[1]) == 0);
-
- assert_se(same_fd(a, b) == 0);
- assert_se(same_fd(b, a) == 0);
-}
-
-static void test_uid_ptr(void) {
-
- assert_se(UID_TO_PTR(0) != NULL);
- assert_se(UID_TO_PTR(1000) != NULL);
-
- assert_se(PTR_TO_UID(UID_TO_PTR(0)) == 0);
- assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000);
-}
-
-static void test_sparse_write_one(int fd, const char *buffer, size_t n) {
- char check[n];
-
- assert_se(lseek(fd, 0, SEEK_SET) == 0);
- assert_se(ftruncate(fd, 0) >= 0);
- assert_se(sparse_write(fd, buffer, n, 4) == (ssize_t) n);
-
- assert_se(lseek(fd, 0, SEEK_CUR) == (off_t) n);
- assert_se(ftruncate(fd, n) >= 0);
-
- assert_se(lseek(fd, 0, SEEK_SET) == 0);
- assert_se(read(fd, check, n) == (ssize_t) n);
-
- assert_se(memcmp(buffer, check, n) == 0);
-}
-
-static void test_sparse_write(void) {
- const char test_a[] = "test";
- const char test_b[] = "\0\0\0\0test\0\0\0\0";
- const char test_c[] = "\0\0test\0\0\0\0";
- const char test_d[] = "\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0\0\0\0";
- const char test_e[] = "test\0\0\0\0test";
- _cleanup_close_ int fd = -1;
- char fn[] = "/tmp/sparseXXXXXX";
-
- fd = mkostemp(fn, O_CLOEXEC);
- assert_se(fd >= 0);
- unlink(fn);
-
- test_sparse_write_one(fd, test_a, sizeof(test_a));
- test_sparse_write_one(fd, test_b, sizeof(test_b));
- test_sparse_write_one(fd, test_c, sizeof(test_c));
- test_sparse_write_one(fd, test_d, sizeof(test_d));
- test_sparse_write_one(fd, test_e, sizeof(test_e));
-}
-
-static void test_shell_escape_one(const char *s, const char *bad, const char *expected) {
- _cleanup_free_ char *r;
-
- assert_se(r = shell_escape(s, bad));
- assert_se(streq_ptr(r, expected));
-}
-
-static void test_shell_escape(void) {
- test_shell_escape_one("", "", "");
- test_shell_escape_one("\\", "", "\\\\");
- test_shell_escape_one("foobar", "", "foobar");
- test_shell_escape_one("foobar", "o", "f\\o\\obar");
- test_shell_escape_one("foo:bar,baz", ",:", "foo\\:bar\\,baz");
-}
-
-static void test_shell_maybe_quote_one(const char *s, const char *expected) {
- _cleanup_free_ char *r;
-
- assert_se(r = shell_maybe_quote(s));
- assert_se(streq(r, expected));
-}
-
-static void test_shell_maybe_quote(void) {
-
- test_shell_maybe_quote_one("", "");
- test_shell_maybe_quote_one("\\", "\"\\\\\"");
- test_shell_maybe_quote_one("\"", "\"\\\"\"");
- test_shell_maybe_quote_one("foobar", "foobar");
- test_shell_maybe_quote_one("foo bar", "\"foo bar\"");
- test_shell_maybe_quote_one("foo \"bar\" waldo", "\"foo \\\"bar\\\" waldo\"");
- test_shell_maybe_quote_one("foo$bar", "\"foo\\$bar\"");
-}
-
-static void test_tempfn(void) {
- char *ret = NULL, *p;
-
- assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0);
- assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX"));
- free(ret);
-
- assert_se(tempfn_xxxxxx("/foo/bar/waldo", "[miau]", &ret) >= 0);
- assert_se(streq_ptr(ret, "/foo/bar/.#[miau]waldoXXXXXX"));
- free(ret);
-
- assert_se(tempfn_random("/foo/bar/waldo", NULL, &ret) >= 0);
- assert_se(p = startswith(ret, "/foo/bar/.#waldo"));
- assert_se(strlen(p) == 16);
- assert_se(in_charset(p, "0123456789abcdef"));
- free(ret);
-
- assert_se(tempfn_random("/foo/bar/waldo", "[wuff]", &ret) >= 0);
- assert_se(p = startswith(ret, "/foo/bar/.#[wuff]waldo"));
- assert_se(strlen(p) == 16);
- assert_se(in_charset(p, "0123456789abcdef"));
- free(ret);
-
- assert_se(tempfn_random_child("/foo/bar/waldo", NULL, &ret) >= 0);
- assert_se(p = startswith(ret, "/foo/bar/waldo/.#"));
- assert_se(strlen(p) == 16);
- assert_se(in_charset(p, "0123456789abcdef"));
- free(ret);
-
- assert_se(tempfn_random_child("/foo/bar/waldo", "[kikiriki]", &ret) >= 0);
- assert_se(p = startswith(ret, "/foo/bar/waldo/.#[kikiriki]"));
- assert_se(strlen(p) == 16);
- assert_se(in_charset(p, "0123456789abcdef"));
- free(ret);
-}
-
-static void test_strcmp_ptr(void) {
- assert_se(strcmp_ptr(NULL, NULL) == 0);
- assert_se(strcmp_ptr("", NULL) > 0);
- assert_se(strcmp_ptr("foo", NULL) > 0);
- assert_se(strcmp_ptr(NULL, "") < 0);
- assert_se(strcmp_ptr(NULL, "bar") < 0);
- assert_se(strcmp_ptr("foo", "bar") > 0);
- assert_se(strcmp_ptr("bar", "baz") < 0);
- assert_se(strcmp_ptr("foo", "foo") == 0);
- assert_se(strcmp_ptr("", "") == 0);
-}
-
-static void test_fgetxattrat_fake(void) {
- char t[] = "/var/tmp/xattrtestXXXXXX";
- _cleanup_close_ int fd = -1;
- const char *x;
- char v[3] = {};
- int r;
-
- assert_se(mkdtemp(t));
- x = strjoina(t, "/test");
- assert_se(touch(x) >= 0);
-
- r = setxattr(x, "user.foo", "bar", 3, 0);
- if (r < 0 && errno == EOPNOTSUPP) /* no xattrs supported on /var/tmp... */
- goto cleanup;
- assert_se(r >= 0);
-
- fd = open(t, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY);
- assert_se(fd >= 0);
-
- assert_se(fgetxattrat_fake(fd, "test", "user.foo", v, 3, 0) >= 0);
- assert_se(memcmp(v, "bar", 3) == 0);
-
- safe_close(fd);
- fd = open("/", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY);
- assert_se(fd >= 0);
- assert_se(fgetxattrat_fake(fd, "usr", "user.idontexist", v, 3, 0) == -ENODATA);
-
-cleanup:
- assert_se(unlink(x) >= 0);
- assert_se(rmdir(t) >= 0);
-}
-
-static void test_runlevel_to_target(void) {
- assert_se(streq_ptr(runlevel_to_target(NULL), NULL));
- assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL));
- assert_se(streq_ptr(runlevel_to_target("3"), SPECIAL_MULTI_USER_TARGET));
-}
-
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
- test_streq_ptr();
test_align_power2();
test_max();
test_container_of();
- test_alloca();
test_div_round_up();
- test_first_word();
- test_close_many();
- test_parse_uid();
- test_strappend();
- test_strstrip();
- test_delete_chars();
- test_in_charset();
- test_hexchar();
- test_unhexchar();
- test_base32hexchar();
- test_unbase32hexchar();
- test_base64char();
- test_unbase64char();
- test_octchar();
- test_unoctchar();
- test_decchar();
- test_undecchar();
- test_unhexmem();
- test_base32hexmem();
- test_unbase32hexmem();
- test_base64mem();
- test_unbase64mem();
- test_cescape();
- test_cunescape();
- test_foreach_word();
- test_foreach_word_quoted();
- test_memdup_multiply();
test_u64log2();
test_protect_errno();
- test_parse_cpu_set();
- test_config_parse_iec_uint64();
- test_strextend();
- test_strrep();
- test_split_pair();
- test_fstab_node_to_udev_node();
- test_get_files_in_directory();
test_in_set();
- test_writing_tmpfile();
- test_hexdump();
test_log2i();
- test_foreach_string();
- test_filename_is_valid();
- test_string_has_cc();
- test_ascii_strlower();
- test_files_same();
- test_is_valid_documentation_url();
- test_file_in_same_dir();
- test_endswith();
- test_endswith_no_case();
- test_close_nointr();
- test_unlink_noerrno();
- test_readlink_and_make_absolute();
- test_ignore_signals();
- test_strshorten();
- test_strjoina();
- test_is_symlink();
- test_search_and_fopen();
- test_search_and_fopen_nulstr();
- test_glob_exists();
test_execute_directory();
- test_parse_proc_cmdline();
test_raw_clone();
- test_same_fd();
- test_uid_ptr();
- test_sparse_write();
- test_shell_escape();
- test_shell_maybe_quote();
- test_tempfn();
- test_strcmp_ptr();
- test_fgetxattrat_fake();
- test_runlevel_to_target();
return 0;
}
diff --git a/src/test/test-web-util.c b/src/test/test-web-util.c
new file mode 100644
index 0000000000..79a3a13af6
--- /dev/null
+++ b/src/test/test-web-util.c
@@ -0,0 +1,39 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "macro.h"
+#include "web-util.h"
+
+static void test_is_valid_documentation_url(void) {
+ assert_se(documentation_url_is_valid("http://www.freedesktop.org/wiki/Software/systemd"));
+ assert_se(documentation_url_is_valid("https://www.kernel.org/doc/Documentation/binfmt_misc.txt"));
+ assert_se(documentation_url_is_valid("file:/foo/foo"));
+ assert_se(documentation_url_is_valid("man:systemd.special(7)"));
+ assert_se(documentation_url_is_valid("info:bar"));
+
+ assert_se(!documentation_url_is_valid("foo:"));
+ assert_se(!documentation_url_is_valid("info:"));
+ assert_se(!documentation_url_is_valid(""));
+}
+
+int main(int argc, char *argv[]) {
+ test_is_valid_documentation_url();
+
+ return 0;
+}
diff --git a/src/test/test-xattr-util.c b/src/test/test-xattr-util.c
new file mode 100644
index 0000000000..267f29426c
--- /dev/null
+++ b/src/test/test-xattr-util.c
@@ -0,0 +1,69 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fs-util.h"
+#include "macro.h"
+#include "string-util.h"
+#include "xattr-util.h"
+
+static void test_fgetxattrat_fake(void) {
+ char t[] = "/var/tmp/xattrtestXXXXXX";
+ _cleanup_close_ int fd = -1;
+ const char *x;
+ char v[3] = {};
+ int r;
+
+ assert_se(mkdtemp(t));
+ x = strjoina(t, "/test");
+ assert_se(touch(x) >= 0);
+
+ r = setxattr(x, "user.foo", "bar", 3, 0);
+ if (r < 0 && errno == EOPNOTSUPP) /* no xattrs supported on /var/tmp... */
+ goto cleanup;
+ assert_se(r >= 0);
+
+ fd = open(t, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY);
+ assert_se(fd >= 0);
+
+ assert_se(fgetxattrat_fake(fd, "test", "user.foo", v, 3, 0) >= 0);
+ assert_se(memcmp(v, "bar", 3) == 0);
+
+ safe_close(fd);
+ fd = open("/", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY);
+ assert_se(fd >= 0);
+ assert_se(fgetxattrat_fake(fd, "usr", "user.idontexist", v, 3, 0) == -ENODATA);
+
+cleanup:
+ assert_se(unlink(x) >= 0);
+ assert_se(rmdir(t) >= 0);
+}
+
+int main(void) {
+ test_fgetxattrat_fake();
+
+ return 0;
+}
diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index 2a10135fba..ffec609c69 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -78,7 +78,7 @@ static int context_read_data(Context *c) {
c->zone = t;
t = NULL;
- c->local_rtc = clock_is_localtime() > 0;
+ c->local_rtc = clock_is_localtime(NULL) > 0;
return 0;
}
@@ -125,30 +125,44 @@ static int context_write_data_local_rtc(Context *c) {
if (!w)
return -ENOMEM;
} else {
- char *p, *e;
+ char *p;
+ const char *e = "\n"; /* default if there is less than 3 lines */
+ const char *prepend = "";
size_t a, b;
- p = strchr(s, '\n');
- if (!p)
- return -EIO;
-
- p = strchr(p+1, '\n');
- if (!p)
- return -EIO;
-
- p++;
- e = strchr(p, '\n');
- if (!e)
- return -EIO;
+ p = strchrnul(s, '\n');
+ if (*p == '\0')
+ /* only one line, no \n terminator */
+ prepend = "\n0\n";
+ else if (p[1] == '\0') {
+ /* only one line, with \n terminator */
+ ++p;
+ prepend = "0\n";
+ } else {
+ p = strchr(p+1, '\n');
+ if (!p) {
+ /* only two lines, no \n terminator */
+ prepend = "\n";
+ p = s + strlen(s);
+ } else {
+ char *end;
+ /* third line might have a \n terminator or not */
+ p++;
+ end = strchr(p, '\n');
+ /* if we actually have a fourth line, use that as suffix "e", otherwise the default \n */
+ if (end)
+ e = end;
+ }
+ }
a = p - s;
b = strlen(e);
- w = new(char, a + (c->local_rtc ? 5 : 3) + b + 1);
+ w = new(char, a + (c->local_rtc ? 5 : 3) + strlen(prepend) + b + 1);
if (!w)
return -ENOMEM;
- *(char*) mempcpy(stpcpy(mempcpy(w, s, a), c->local_rtc ? "LOCAL" : "UTC"), e, b) = 0;
+ *(char*) mempcpy(stpcpy(stpcpy(mempcpy(w, s, a), prepend), c->local_rtc ? "LOCAL" : "UTC"), e, b) = 0;
if (streq(w, NULL_ADJTIME_UTC)) {
if (unlink("/etc/adjtime") < 0)
@@ -159,7 +173,7 @@ static int context_write_data_local_rtc(Context *c) {
}
}
- mac_selinux_init("/etc");
+ mac_selinux_init();
return write_string_file_atomic_label("/etc/adjtime", w);
}
diff --git a/src/timesync/timesyncd.c b/src/timesync/timesyncd.c
index 23e19159e0..b67d672a6a 100644
--- a/src/timesync/timesyncd.c
+++ b/src/timesync/timesyncd.c
@@ -122,7 +122,7 @@ int main(int argc, char *argv[]) {
goto finish;
}
- if (clock_is_localtime() > 0) {
+ if (clock_is_localtime(NULL) > 0) {
log_info("The system is configured to read the RTC time in the local time zone. "
"This mode can not be fully supported. All system time to RTC updates are disabled.");
m->rtc_local_time = true;
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 7b105a6bd4..efd264b34d 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -613,7 +613,7 @@ static int path_set_perms(Item *i, const char *path) {
* with AT_SYMLINK_NOFOLLOW, hence we emulate it here via
* O_PATH. */
- fd = open(path, O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH|O_NOATIME);
+ fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
if (fd < 0)
return log_error_errno(errno, "Adjusting owner and mode for %s failed: %m", path);
@@ -804,7 +804,7 @@ static int path_set_acls(Item *item, const char *path) {
assert(item);
assert(path);
- fd = open(path, O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH|O_NOATIME);
+ fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
if (fd < 0)
return log_error_errno(errno, "Adjusting ACL of %s failed: %m", path);
@@ -917,10 +917,7 @@ static int parse_attribute_from_arg(Item *item) {
v = attributes[i].value;
- if (mode == MODE_ADD || mode == MODE_SET)
- value |= v;
- else
- value &= ~v;
+ SET_FLAG(value, v, (mode == MODE_ADD || mode == MODE_SET));
mask |= v;
}
@@ -2288,7 +2285,7 @@ int main(int argc, char *argv[]) {
umask(0022);
- mac_selinux_init(NULL);
+ mac_selinux_init();
items = ordered_hashmap_new(&string_hash_ops);
globs = ordered_hashmap_new(&string_hash_ops);
diff --git a/src/udev/udev.h b/src/udev/udev.h
index 56590517ef..8433e8d9f2 100644
--- a/src/udev/udev.h
+++ b/src/udev/udev.h
@@ -19,6 +19,7 @@
*/
#include <sys/param.h>
+#include <sys/sysmacros.h>
#include <sys/types.h>
#include "libudev.h"
diff --git a/src/udev/udevadm.c b/src/udev/udevadm.c
index 7bd2c1ea42..a6a873e5de 100644
--- a/src/udev/udevadm.c
+++ b/src/udev/udevadm.c
@@ -93,7 +93,7 @@ int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
- mac_selinux_init("/dev");
+ mac_selinux_init();
while ((c = getopt_long(argc, argv, "+dhV", options, NULL)) >= 0)
switch (c) {
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index bb92f16352..243df7386f 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -1695,7 +1695,7 @@ int main(int argc, char *argv[]) {
umask(022);
- r = mac_selinux_init("/dev");
+ r = mac_selinux_init();
if (r < 0) {
log_error_errno(r, "could not initialize labelling: %m");
goto exit;
diff --git a/src/update-done/update-done.c b/src/update-done/update-done.c
index 931e583785..da306a4444 100644
--- a/src/update-done/update-done.c
+++ b/src/update-done/update-done.c
@@ -101,7 +101,7 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}
- r = mac_selinux_init(NULL);
+ r = mac_selinux_init();
if (r < 0) {
log_error_errno(r, "SELinux setup failed: %m");
goto finish;
diff --git a/src/user-sessions/user-sessions.c b/src/user-sessions/user-sessions.c
index 8bf44e2100..9b29b5ba1d 100644
--- a/src/user-sessions/user-sessions.c
+++ b/src/user-sessions/user-sessions.c
@@ -40,7 +40,7 @@ int main(int argc, char*argv[]) {
umask(0022);
- mac_selinux_init(NULL);
+ mac_selinux_init();
if (streq(argv[1], "start")) {
int r = 0;