summaryrefslogtreecommitdiff
path: root/src/basic
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic')
-rw-r--r--src/basic/barrier.c1
-rw-r--r--src/basic/btrfs-util.c2
-rw-r--r--src/basic/cgroup-util.c6
-rw-r--r--src/basic/clock-util.c4
-rw-r--r--src/basic/errno-list.c5
-rw-r--r--src/basic/escape.c51
-rw-r--r--src/basic/escape.h2
-rw-r--r--src/basic/extract-word.c9
-rw-r--r--src/basic/fd-util.h3
-rw-r--r--src/basic/fileio.c33
-rw-r--r--src/basic/fileio.h2
-rw-r--r--src/basic/fs-util.c2
-rw-r--r--src/basic/glob-util.c4
-rw-r--r--src/basic/in-addr-util.c4
-rw-r--r--src/basic/in-addr-util.h5
-rw-r--r--src/basic/log.c89
-rw-r--r--src/basic/log.h10
-rw-r--r--src/basic/missing.h15
-rw-r--r--src/basic/ordered-set.c64
-rw-r--r--src/basic/ordered-set.h6
-rw-r--r--src/basic/parse-util.c22
-rw-r--r--src/basic/path-util.c2
-rw-r--r--src/basic/process-util.c32
-rw-r--r--src/basic/process-util.h3
-rw-r--r--src/basic/rm-rf.c2
-rw-r--r--src/basic/socket-label.c6
-rw-r--r--src/basic/socket-util.c4
-rw-r--r--src/basic/socket-util.h4
-rw-r--r--src/basic/strv.c20
-rw-r--r--src/basic/strv.h2
-rw-r--r--src/basic/terminal-util.c17
-rw-r--r--src/basic/terminal-util.h17
-rw-r--r--src/basic/user-util.c2
-rw-r--r--src/basic/util.c2
34 files changed, 332 insertions, 120 deletions
diff --git a/src/basic/barrier.c b/src/basic/barrier.c
index 9a78a80eb2..26ae123341 100644
--- a/src/basic/barrier.c
+++ b/src/basic/barrier.c
@@ -197,6 +197,7 @@ static bool barrier_write(Barrier *b, uint64_t buf) {
if (barrier_i_aborted(b))
return false;
+ assert(b->me >= 0);
do {
len = write(b->me, &buf, sizeof(buf));
} while (len < 0 && IN_SET(errno, EAGAIN, EINTR));
diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c
index acd48f6954..d07d1df5a8 100644
--- a/src/basic/btrfs-util.c
+++ b/src/basic/btrfs-util.c
@@ -2051,7 +2051,7 @@ int btrfs_subvol_get_parent(int fd, uint64_t subvol_id, uint64_t *ret) {
args.key.nr_items = 256;
if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
- return -errno;
+ return negative_errno();
if (args.key.nr_items <= 0)
break;
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
index 3945d37c8d..f873fb89d3 100644
--- a/src/basic/cgroup-util.c
+++ b/src/basic/cgroup-util.c
@@ -93,7 +93,7 @@ int cg_read_pid(FILE *f, pid_t *_pid) {
if (feof(f))
return 0;
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
}
if (ul <= 0)
@@ -648,7 +648,7 @@ int cg_trim(const char *controller, const char *path, bool delete_root) {
if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0) {
if (errno == ENOENT)
r = 0;
- else if (errno != 0)
+ else if (errno > 0)
r = -errno;
else
r = -EIO;
@@ -2091,7 +2091,7 @@ int cg_kernel_controllers(Set *controllers) {
if (feof(f))
break;
- if (ferror(f) && errno != 0)
+ if (ferror(f) && errno > 0)
return -errno;
return -EBADMSG;
diff --git a/src/basic/clock-util.c b/src/basic/clock-util.c
index 00f549c023..05788a360e 100644
--- a/src/basic/clock-util.c
+++ b/src/basic/clock-util.c
@@ -33,6 +33,7 @@
#include "fd-util.h"
#include "macro.h"
#include "string-util.h"
+#include "util.h"
int clock_get_hwclock(struct tm *tm) {
_cleanup_close_ int fd = -1;
@@ -121,7 +122,8 @@ int clock_set_timezone(int *min) {
* have read from the RTC.
*/
if (settimeofday(tv_null, &tz) < 0)
- return -errno;
+ return negative_errno();
+
if (min)
*min = minutesdelta;
return 0;
diff --git a/src/basic/errno-list.c b/src/basic/errno-list.c
index 0a66902ac9..b4d080103b 100644
--- a/src/basic/errno-list.c
+++ b/src/basic/errno-list.c
@@ -25,7 +25,7 @@
#include "macro.h"
static const struct errno_name* lookup_errno(register const char *str,
- register unsigned int len);
+ register unsigned int len);
#include "errno-from-name.h"
#include "errno-to-name.h"
@@ -48,8 +48,9 @@ int errno_from_name(const char *name) {
sc = lookup_errno(name, strlen(name));
if (!sc)
- return 0;
+ return -EINVAL;
+ assert(sc->id > 0);
return sc->id;
}
diff --git a/src/basic/escape.c b/src/basic/escape.c
index ab282efa3c..5661f36813 100644
--- a/src/basic/escape.c
+++ b/src/basic/escape.c
@@ -119,16 +119,18 @@ char *cescape(const char *s) {
return cescape_length(s, strlen(s));
}
-int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode) {
+int cunescape_one(const char *p, size_t length, uint32_t *ret, bool *eight_bit) {
int r = 1;
assert(p);
assert(*p);
assert(ret);
- /* Unescapes C style. Returns the unescaped character in ret,
- * unless we encountered a \u sequence in which case the full
- * unicode character is returned in ret_unicode, instead. */
+ /* Unescapes C style. Returns the unescaped character in ret.
+ * Sets *eight_bit to true if the escaped sequence either fits in
+ * one byte in UTF-8 or is a non-unicode literal byte and should
+ * instead be copied directly.
+ */
if (length != (size_t) -1 && length < 1)
return -EINVAL;
@@ -190,7 +192,8 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
if (a == 0 && b == 0)
return -EINVAL;
- *ret = (char) ((a << 4U) | b);
+ *ret = (a << 4U) | b;
+ *eight_bit = true;
r = 3;
break;
}
@@ -217,16 +220,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
if (c == 0)
return -EINVAL;
- if (c < 128)
- *ret = c;
- else {
- if (!ret_unicode)
- return -EINVAL;
-
- *ret = 0;
- *ret_unicode = c;
- }
-
+ *ret = c;
r = 5;
break;
}
@@ -258,16 +252,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
if (!unichar_is_valid(c))
return -EINVAL;
- if (c < 128)
- *ret = c;
- else {
- if (!ret_unicode)
- return -EINVAL;
-
- *ret = 0;
- *ret_unicode = c;
- }
-
+ *ret = c;
r = 9;
break;
}
@@ -309,6 +294,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
return -EINVAL;
*ret = m;
+ *eight_bit = true;
r = 3;
break;
}
@@ -342,7 +328,7 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
for (f = s, t = r + pl; f < s + length; f++) {
size_t remaining;
uint32_t u;
- char c;
+ bool eight_bit = false;
int k;
remaining = s + length - f;
@@ -365,7 +351,7 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
return -EINVAL;
}
- k = cunescape_one(f + 1, remaining - 1, &c, &u);
+ k = cunescape_one(f + 1, remaining - 1, &u, &eight_bit);
if (k < 0) {
if (flags & UNESCAPE_RELAX) {
/* Invalid escape code, let's take it literal then */
@@ -377,14 +363,13 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
return k;
}
- if (c != 0)
- /* Non-Unicode? Let's encode this directly */
- *(t++) = c;
+ f += k;
+ if (eight_bit)
+ /* One byte? Set directly as specified */
+ *(t++) = u;
else
- /* Unicode? Then let's encode this in UTF-8 */
+ /* Otherwise encode as multi-byte UTF-8 */
t += utf8_encode_unichar(t, u);
-
- f += k;
}
*t = 0;
diff --git a/src/basic/escape.h b/src/basic/escape.h
index c710f01743..d943aa71f5 100644
--- a/src/basic/escape.h
+++ b/src/basic/escape.h
@@ -45,7 +45,7 @@ size_t cescape_char(char c, char *buf);
int cunescape(const char *s, UnescapeFlags flags, char **ret);
int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret);
int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret);
-int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode);
+int cunescape_one(const char *p, size_t length, uint32_t *ret, bool *eight_bit);
char *xescape(const char *s, const char *bad);
diff --git a/src/basic/extract-word.c b/src/basic/extract-word.c
index 7cc2a1de13..090d2a7884 100644
--- a/src/basic/extract-word.c
+++ b/src/basic/extract-word.c
@@ -108,8 +108,9 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
if (flags & EXTRACT_CUNESCAPE) {
uint32_t u;
+ bool eight_bit = false;
- r = cunescape_one(*p, (size_t) -1, &c, &u);
+ r = cunescape_one(*p, (size_t) -1, &u, &eight_bit);
if (r < 0) {
if (flags & EXTRACT_CUNESCAPE_RELAX) {
s[sz++] = '\\';
@@ -119,10 +120,10 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
} else {
(*p) += r - 1;
- if (c != 0)
- s[sz++] = c; /* normal explicit char */
+ if (eight_bit)
+ s[sz++] = u;
else
- sz += utf8_encode_unichar(s + sz, u); /* unicode chars we'll encode as utf8 */
+ sz += utf8_encode_unichar(s + sz, u);
}
} else
s[sz++] = c;
diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h
index 973413ff42..20890e3279 100644
--- a/src/basic/fd-util.h
+++ b/src/basic/fd-util.h
@@ -74,5 +74,6 @@ void cmsg_close_all(struct msghdr *mh);
bool fdname_is_valid(const char *s);
+/* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */
#define ERRNO_IS_DISCONNECT(r) \
- IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE)
+ IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH)
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index 3a237252b5..3ff70310e1 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -165,7 +165,7 @@ int read_one_line_file(const char *fn, char **line) {
if (!fgets(t, sizeof(t), f)) {
if (ferror(f))
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
t[0] = 0;
}
@@ -1064,7 +1064,7 @@ int fflush_and_check(FILE *f) {
fflush(f);
if (ferror(f))
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
return 0;
}
@@ -1251,3 +1251,32 @@ int read_timestamp_file(const char *fn, usec_t *ret) {
*ret = (usec_t) t;
return 0;
}
+
+int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space) {
+ int r;
+
+ assert(s);
+
+ /* Outputs the specified string with fputs(), but optionally prefixes it with a separator. The *space parameter
+ * when specified shall initially point to a boolean variable initialized to false. It is set to true after the
+ * first invocation. This call is supposed to be use in loops, where a separator shall be inserted between each
+ * element, but not before the first one. */
+
+ if (!f)
+ f = stdout;
+
+ if (space) {
+ if (!separator)
+ separator = " ";
+
+ if (*space) {
+ r = fputs(separator, f);
+ if (r < 0)
+ return r;
+ }
+
+ *space = true;
+ }
+
+ return fputs(s, f);
+}
diff --git a/src/basic/fileio.h b/src/basic/fileio.h
index 95e8698941..9e09574133 100644
--- a/src/basic/fileio.h
+++ b/src/basic/fileio.h
@@ -82,3 +82,5 @@ int tempfn_random_child(const char *p, const char *extra, char **ret);
int write_timestamp_file_atomic(const char *fn, usec_t n);
int read_timestamp_file(const char *fn, usec_t *ret);
+
+int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space);
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
index fb760abe18..d31bd6e273 100644
--- a/src/basic/fs-util.c
+++ b/src/basic/fs-util.c
@@ -481,7 +481,7 @@ int get_files_in_directory(const char *path, char ***list) {
errno = 0;
de = readdir(d);
- if (!de && errno != 0)
+ if (!de && errno > 0)
return -errno;
if (!de)
break;
diff --git a/src/basic/glob-util.c b/src/basic/glob-util.c
index a0be0efd40..811ab6ec36 100644
--- a/src/basic/glob-util.c
+++ b/src/basic/glob-util.c
@@ -40,7 +40,7 @@ int glob_exists(const char *path) {
if (k == GLOB_NOSPACE)
return -ENOMEM;
if (k != 0)
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
return !strv_isempty(g.gl_pathv);
}
@@ -58,7 +58,7 @@ int glob_extend(char ***strv, const char *path) {
if (k == GLOB_NOSPACE)
return -ENOMEM;
if (k != 0)
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
if (strv_isempty(g.gl_pathv))
return -ENOENT;
diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c
index 5143dddf8f..8609ffb3c9 100644
--- a/src/basic/in-addr-util.c
+++ b/src/basic/in-addr-util.c
@@ -219,7 +219,7 @@ int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
errno = 0;
if (!inet_ntop(family, u, x, l)) {
free(x);
- return errno ? -errno : -EINVAL;
+ return errno > 0 ? -errno : -EINVAL;
}
*ret = x;
@@ -236,7 +236,7 @@ int in_addr_from_string(int family, const char *s, union in_addr_union *ret) {
errno = 0;
if (inet_pton(family, s, ret) <= 0)
- return errno ? -errno : -EINVAL;
+ return errno > 0 ? -errno : -EINVAL;
return 0;
}
diff --git a/src/basic/in-addr-util.h b/src/basic/in-addr-util.h
index bcc116c783..f2b8865df5 100644
--- a/src/basic/in-addr-util.h
+++ b/src/basic/in-addr-util.h
@@ -33,6 +33,11 @@ union in_addr_union {
struct in6_addr in6;
};
+struct in_addr_data {
+ int family;
+ union in_addr_union address;
+};
+
int in_addr_is_null(int family, const union in_addr_union *u);
int in_addr_is_link_local(int family, const union in_addr_union *u);
int in_addr_is_localhost(int family, const union in_addr_union *u);
diff --git a/src/basic/log.c b/src/basic/log.c
index a2bc0d5be2..18d4b82be2 100644
--- a/src/basic/log.c
+++ b/src/basic/log.c
@@ -805,6 +805,52 @@ int log_oom_internal(const char *file, int line, const char *func) {
return -ENOMEM;
}
+int log_format_iovec(
+ struct iovec *iovec,
+ unsigned iovec_len,
+ unsigned *n,
+ bool newline_separator,
+ int error,
+ const char *format,
+ va_list ap) {
+
+ static const char nl = '\n';
+
+ while (format && *n + 1 < iovec_len) {
+ va_list aq;
+ char *m;
+ int r;
+
+ /* We need to copy the va_list structure,
+ * since vasprintf() leaves it afterwards at
+ * an undefined location */
+
+ if (error != 0)
+ errno = error;
+
+ va_copy(aq, ap);
+ r = vasprintf(&m, format, aq);
+ va_end(aq);
+ if (r < 0)
+ return -EINVAL;
+
+ /* Now, jump enough ahead, so that we point to
+ * the next format string */
+ VA_FORMAT_ADVANCE(format, ap);
+
+ IOVEC_SET_STRING(iovec[(*n)++], m);
+
+ if (newline_separator) {
+ iovec[*n].iov_base = (char*) &nl;
+ iovec[*n].iov_len = 1;
+ (*n)++;
+ }
+
+ format = va_arg(ap, char *);
+ }
+ return 0;
+}
+
int log_struct_internal(
int level,
int error,
@@ -837,10 +883,10 @@ int log_struct_internal(
char header[LINE_MAX];
struct iovec iovec[17] = {};
unsigned n = 0, i;
+ int r;
struct msghdr mh = {
.msg_iov = iovec,
};
- static const char nl = '\n';
bool fallback = false;
/* If the journal is available do structured logging */
@@ -848,43 +894,14 @@ int log_struct_internal(
IOVEC_SET_STRING(iovec[n++], header);
va_start(ap, format);
- while (format && n + 1 < ELEMENTSOF(iovec)) {
- va_list aq;
- char *m;
-
- /* We need to copy the va_list structure,
- * since vasprintf() leaves it afterwards at
- * an undefined location */
-
- if (error != 0)
- errno = error;
-
- va_copy(aq, ap);
- if (vasprintf(&m, format, aq) < 0) {
- va_end(aq);
- fallback = true;
- goto finish;
- }
- va_end(aq);
-
- /* Now, jump enough ahead, so that we point to
- * the next format string */
- VA_FORMAT_ADVANCE(format, ap);
-
- IOVEC_SET_STRING(iovec[n++], m);
-
- iovec[n].iov_base = (char*) &nl;
- iovec[n].iov_len = 1;
- n++;
-
- format = va_arg(ap, char *);
+ r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, true, error, format, ap);
+ if (r < 0)
+ fallback = true;
+ else {
+ mh.msg_iovlen = n;
+ (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
}
- mh.msg_iovlen = n;
-
- (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
-
- finish:
va_end(ap);
for (i = 1; i < n; i += 2)
free(iovec[i].iov_base);
diff --git a/src/basic/log.h b/src/basic/log.h
index cda1e45cc8..8c7c5e4598 100644
--- a/src/basic/log.h
+++ b/src/basic/log.h
@@ -26,6 +26,7 @@
#include <stdbool.h>
#include <stdlib.h>
#include <sys/signalfd.h>
+#include <sys/socket.h>
#include <syslog.h>
#include "sd-id128.h"
@@ -127,6 +128,15 @@ int log_oom_internal(
int line,
const char *func);
+int log_format_iovec(
+ struct iovec *iovec,
+ unsigned iovec_len,
+ unsigned *n,
+ bool newline_separator,
+ int error,
+ const char *format,
+ va_list ap);
+
/* This modifies the buffer passed! */
int log_dump_internal(
int level,
diff --git a/src/basic/missing.h b/src/basic/missing.h
index 2d2785bead..6ed2133ed1 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -974,6 +974,10 @@ static inline int setns(int fd, int nstype) {
#define IFA_FLAGS 8
#endif
+#ifndef IFA_F_MANAGETEMPADDR
+#define IFA_F_MANAGETEMPADDR 0x100
+#endif
+
#ifndef IFA_F_NOPREFIXROUTE
#define IFA_F_NOPREFIXROUTE 0x200
#endif
@@ -1145,3 +1149,14 @@ static inline key_serial_t request_key(const char *type, const char *description
#ifndef PR_CAP_AMBIENT_CLEAR_ALL
#define PR_CAP_AMBIENT_CLEAR_ALL 4
#endif
+
+/* The following two defines are actually available in the kernel headers for longer, but we define them here anyway,
+ * since that makes it easier to use them in conjunction with the glibc net/if.h header which conflicts with
+ * linux/if.h. */
+#ifndef IF_OPER_UNKNOWN
+#define IF_OPER_UNKNOWN 0
+#endif
+
+#ifndef IF_OPER_UP
+#define IF_OPER_UP 6
+#endif
diff --git a/src/basic/ordered-set.c b/src/basic/ordered-set.c
new file mode 100644
index 0000000000..2e0bdf6488
--- /dev/null
+++ b/src/basic/ordered-set.c
@@ -0,0 +1,64 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2016 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "ordered-set.h"
+#include "strv.h"
+
+int ordered_set_consume(OrderedSet *s, void *p) {
+ int r;
+
+ r = ordered_set_put(s, p);
+ if (r <= 0)
+ free(p);
+
+ return r;
+}
+
+int ordered_set_put_strdup(OrderedSet *s, const char *p) {
+ char *c;
+ int r;
+
+ assert(s);
+ assert(p);
+
+ c = strdup(p);
+ if (!c)
+ return -ENOMEM;
+
+ r = ordered_set_consume(s, c);
+ if (r == -EEXIST)
+ return 0;
+
+ return r;
+}
+
+int ordered_set_put_strdupv(OrderedSet *s, char **l) {
+ int n = 0, r;
+ char **i;
+
+ STRV_FOREACH(i, l) {
+ r = ordered_set_put_strdup(s, *i);
+ if (r < 0)
+ return r;
+
+ n += r;
+ }
+
+ return n;
+}
diff --git a/src/basic/ordered-set.h b/src/basic/ordered-set.h
index da10e90ff2..ab185c11aa 100644
--- a/src/basic/ordered-set.h
+++ b/src/basic/ordered-set.h
@@ -62,9 +62,15 @@ static inline bool ordered_set_iterate(OrderedSet *s, Iterator *i, void **value)
return ordered_hashmap_iterate((OrderedHashmap*) s, i, value, NULL);
}
+int ordered_set_consume(OrderedSet *s, void *p);
+int ordered_set_put_strdup(OrderedSet *s, const char *p);
+int ordered_set_put_strdupv(OrderedSet *s, char **l);
+
#define ORDERED_SET_FOREACH(e, s, i) \
for ((i) = ITERATOR_FIRST; ordered_set_iterate((s), &(i), (void**)&(e)); )
DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free_free);
#define _cleanup_ordered_set_free_ _cleanup_(ordered_set_freep)
+#define _cleanup_ordered_set_free_free_ _cleanup_(ordered_set_free_freep)
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
index 618ef5d564..d8de6f90ea 100644
--- a/src/basic/parse-util.c
+++ b/src/basic/parse-util.c
@@ -81,7 +81,7 @@ int parse_mode(const char *s, mode_t *ret) {
errno = 0;
l = strtol(s, &x, 8);
- if (errno != 0)
+ if (errno > 0)
return -errno;
if (!x || x == s || *x)
return -EINVAL;
@@ -176,7 +176,7 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) {
errno = 0;
l = strtoull(p, &e, 10);
- if (errno != 0)
+ if (errno > 0)
return -errno;
if (e == p)
return -EINVAL;
@@ -192,7 +192,7 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) {
char *e2;
l2 = strtoull(e, &e2, 10);
- if (errno != 0)
+ if (errno > 0)
return -errno;
/* Ignore failure. E.g. 10.M is valid */
@@ -330,7 +330,7 @@ int safe_atou(const char *s, unsigned *ret_u) {
errno = 0;
l = strtoul(s, &x, 0);
- if (errno != 0)
+ if (errno > 0)
return -errno;
if (!x || x == s || *x)
return -EINVAL;
@@ -352,7 +352,7 @@ int safe_atoi(const char *s, int *ret_i) {
errno = 0;
l = strtol(s, &x, 0);
- if (errno != 0)
+ if (errno > 0)
return -errno;
if (!x || x == s || *x)
return -EINVAL;
@@ -374,7 +374,7 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) {
errno = 0;
l = strtoull(s, &x, 0);
- if (errno != 0)
+ if (errno > 0)
return -errno;
if (!x || x == s || *x)
return -EINVAL;
@@ -394,7 +394,7 @@ int safe_atolli(const char *s, long long int *ret_lli) {
errno = 0;
l = strtoll(s, &x, 0);
- if (errno != 0)
+ if (errno > 0)
return -errno;
if (!x || x == s || *x)
return -EINVAL;
@@ -414,7 +414,7 @@ int safe_atou8(const char *s, uint8_t *ret) {
errno = 0;
l = strtoul(s, &x, 0);
- if (errno != 0)
+ if (errno > 0)
return -errno;
if (!x || x == s || *x)
return -EINVAL;
@@ -438,7 +438,7 @@ int safe_atou16(const char *s, uint16_t *ret) {
errno = 0;
l = strtoul(s, &x, 0);
- if (errno != 0)
+ if (errno > 0)
return -errno;
if (!x || x == s || *x)
return -EINVAL;
@@ -460,7 +460,7 @@ int safe_atoi16(const char *s, int16_t *ret) {
errno = 0;
l = strtol(s, &x, 0);
- if (errno != 0)
+ if (errno > 0)
return -errno;
if (!x || x == s || *x)
return -EINVAL;
@@ -485,7 +485,7 @@ int safe_atod(const char *s, double *ret_d) {
errno = 0;
d = strtod_l(s, &x, loc);
- if (errno != 0) {
+ if (errno > 0) {
freelocale(loc);
return -errno;
}
diff --git a/src/basic/path-util.c b/src/basic/path-util.c
index 61fab0e087..4837bb2d7d 100644
--- a/src/basic/path-util.c
+++ b/src/basic/path-util.c
@@ -102,7 +102,7 @@ int path_make_absolute_cwd(const char *p, char **ret) {
cwd = get_current_dir_name();
if (!cwd)
- return -errno;
+ return negative_errno();
c = strjoin(cwd, "/", p, NULL);
}
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index 4cc54a51fb..189ef9ab60 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -33,6 +33,9 @@
#include <sys/wait.h>
#include <syslog.h>
#include <unistd.h>
+#ifdef HAVE_VALGRIND_VALGRIND_H
+#include <valgrind/valgrind.h>
+#endif
#include "alloc-util.h"
#include "escape.h"
@@ -45,6 +48,7 @@
#include "missing.h"
#include "process-util.h"
#include "signal-util.h"
+#include "stat-util.h"
#include "string-table.h"
#include "string-util.h"
#include "user-util.h"
@@ -634,6 +638,17 @@ bool pid_is_alive(pid_t pid) {
return true;
}
+int pid_from_same_root_fs(pid_t pid) {
+ const char *root;
+
+ if (pid < 0)
+ return 0;
+
+ root = procfs_file_alloca(pid, "root");
+
+ return files_same(root, "/proc/1/root");
+}
+
bool is_main_thread(void) {
static thread_local int cached = 0;
@@ -730,6 +745,23 @@ const char* personality_to_string(unsigned long p) {
return NULL;
}
+void valgrind_summary_hack(void) {
+#ifdef HAVE_VALGRIND_VALGRIND_H
+ if (getpid() == 1 && RUNNING_ON_VALGRIND) {
+ pid_t pid;
+ pid = raw_clone(SIGCHLD, NULL);
+ if (pid < 0)
+ log_emergency_errno(errno, "Failed to fork off valgrind helper: %m");
+ else if (pid == 0)
+ exit(EXIT_SUCCESS);
+ else {
+ log_info("Spawned valgrind helper as PID "PID_FMT".", pid);
+ (void) wait_for_terminate(pid, NULL);
+ }
+ }
+#endif
+}
+
static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_NONE] = "none",
[IOPRIO_CLASS_RT] = "realtime",
diff --git a/src/basic/process-util.h b/src/basic/process-util.h
index f4c4437624..f5d193e762 100644
--- a/src/basic/process-util.h
+++ b/src/basic/process-util.h
@@ -70,6 +70,7 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value);
bool pid_is_alive(pid_t pid);
bool pid_is_unwaited(pid_t pid);
+int pid_from_same_root_fs(pid_t pid);
bool is_main_thread(void);
@@ -98,3 +99,5 @@ int sched_policy_from_string(const char *s);
#define PTR_TO_PID(p) ((pid_t) ((uintptr_t) p))
#define PID_TO_PTR(p) ((void*) ((uintptr_t) p))
+
+void valgrind_summary_hack(void);
diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c
index 14f8474da0..4807561723 100644
--- a/src/basic/rm-rf.c
+++ b/src/basic/rm-rf.c
@@ -82,7 +82,7 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
errno = 0;
de = readdir(d);
if (!de) {
- if (errno != 0 && ret == 0)
+ if (errno > 0 && ret == 0)
ret = -errno;
return ret;
}
diff --git a/src/basic/socket-label.c b/src/basic/socket-label.c
index e169439e04..bd206586ce 100644
--- a/src/basic/socket-label.c
+++ b/src/basic/socket-label.c
@@ -147,7 +147,7 @@ int socket_address_listen(
return r;
}
-int make_socket_fd(int log_level, const char* address, int flags) {
+int make_socket_fd(int log_level, const char* address, int type, int flags) {
SocketAddress a;
int fd, r;
@@ -155,7 +155,9 @@ int make_socket_fd(int log_level, const char* address, int flags) {
if (r < 0)
return log_error_errno(r, "Failed to parse socket address \"%s\": %m", address);
- fd = socket_address_listen(&a, flags, SOMAXCONN, SOCKET_ADDRESS_DEFAULT,
+ a.type = type;
+
+ fd = socket_address_listen(&a, type | flags, SOMAXCONN, SOCKET_ADDRESS_DEFAULT,
NULL, false, false, false, 0755, 0644, NULL);
if (fd < 0 || log_get_max_level() >= log_level) {
_cleanup_free_ char *p = NULL;
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index be144e157d..f2bb3bab86 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -601,7 +601,7 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
return 0;
}
-int getpeername_pretty(int fd, char **ret) {
+int getpeername_pretty(int fd, bool include_port, char **ret) {
union sockaddr_union sa;
socklen_t salen = sizeof(sa);
int r;
@@ -631,7 +631,7 @@ int getpeername_pretty(int fd, char **ret) {
/* For remote sockets we translate IPv6 addresses back to IPv4
* if applicable, since that's nicer. */
- return sockaddr_pretty(&sa.sa, salen, true, true, ret);
+ return sockaddr_pretty(&sa.sa, salen, true, include_port, ret);
}
int getsockname_pretty(int fd, char **ret) {
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
index 6da1df68d8..2323ccf3ab 100644
--- a/src/basic/socket-util.h
+++ b/src/basic/socket-util.h
@@ -89,7 +89,7 @@ int socket_address_listen(
mode_t directory_mode,
mode_t socket_mode,
const char *label);
-int make_socket_fd(int log_level, const char* address, int flags);
+int make_socket_fd(int log_level, const char* address, int type, int flags);
bool socket_address_is(const SocketAddress *a, const char *s, int type);
bool socket_address_is_netlink(const SocketAddress *a, const char *s);
@@ -105,7 +105,7 @@ bool socket_ipv6_is_supported(void);
int sockaddr_port(const struct sockaddr *_sa) _pure_;
int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret);
-int getpeername_pretty(int fd, char **ret);
+int getpeername_pretty(int fd, bool include_port, char **ret);
int getsockname_pretty(int fd, char **ret);
int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret);
diff --git a/src/basic/strv.c b/src/basic/strv.c
index 0a3d15706f..5532c53ad1 100644
--- a/src/basic/strv.c
+++ b/src/basic/strv.c
@@ -29,6 +29,7 @@
#include "alloc-util.h"
#include "escape.h"
#include "extract-word.h"
+#include "fileio.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
@@ -871,3 +872,22 @@ rollback:
nl[k] = NULL;
return -ENOMEM;
}
+
+int fputstrv(FILE *f, char **l, const char *separator, bool *space) {
+ bool b = false;
+ char **s;
+ int r;
+
+ /* Like fputs(), but for strv, and with a less stupid argument order */
+
+ if (!space)
+ space = &b;
+
+ STRV_FOREACH(s, l) {
+ r = fputs_with_space(f, *s, separator, space);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
diff --git a/src/basic/strv.h b/src/basic/strv.h
index bb61db2638..560f90115c 100644
--- a/src/basic/strv.h
+++ b/src/basic/strv.h
@@ -169,3 +169,5 @@ char ***strv_free_free(char ***l);
char **strv_skip(char **l, size_t n);
int strv_extend_n(char ***l, const char *value, size_t n);
+
+int fputstrv(FILE *f, char **l, const char *separator, bool *space);
diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c
index a39764472b..fedfc8a5df 100644
--- a/src/basic/terminal-util.c
+++ b/src/basic/terminal-util.c
@@ -128,7 +128,7 @@ int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
errno = 0;
if (!fgets(line, sizeof(line), f))
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
truncate_nl(line);
@@ -212,7 +212,7 @@ int ask_string(char **ret, const char *text, ...) {
errno = 0;
if (!fgets(line, sizeof(line), stdin))
- return errno ? -errno : -EIO;
+ return errno > 0 ? -errno : -EIO;
if (!endswith(line, "\n"))
putchar('\n');
@@ -1135,3 +1135,16 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
return receive_one_fd(pair[0], 0);
}
+
+bool colors_enabled(void) {
+ const char *colors;
+
+ colors = getenv("SYSTEMD_COLORS");
+ if (!colors) {
+ if (streq_ptr(getenv("TERM"), "dumb"))
+ return false;
+ return on_tty();
+ }
+
+ return parse_boolean(colors) != 0;
+}
diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h
index 597a0060ad..a7c96a77cb 100644
--- a/src/basic/terminal-util.h
+++ b/src/basic/terminal-util.h
@@ -79,37 +79,38 @@ unsigned lines(void);
void columns_lines_cache_reset(int _unused_ signum);
bool on_tty(void);
+bool colors_enabled(void);
static inline const char *ansi_underline(void) {
- return on_tty() ? ANSI_UNDERLINE : "";
+ return colors_enabled() ? ANSI_UNDERLINE : "";
}
static inline const char *ansi_highlight(void) {
- return on_tty() ? ANSI_HIGHLIGHT : "";
+ return colors_enabled() ? ANSI_HIGHLIGHT : "";
}
static inline const char *ansi_highlight_underline(void) {
- return on_tty() ? ANSI_HIGHLIGHT_UNDERLINE : "";
+ return colors_enabled() ? ANSI_HIGHLIGHT_UNDERLINE : "";
}
static inline const char *ansi_highlight_red(void) {
- return on_tty() ? ANSI_HIGHLIGHT_RED : "";
+ return colors_enabled() ? ANSI_HIGHLIGHT_RED : "";
}
static inline const char *ansi_highlight_green(void) {
- return on_tty() ? ANSI_HIGHLIGHT_GREEN : "";
+ return colors_enabled() ? ANSI_HIGHLIGHT_GREEN : "";
}
static inline const char *ansi_highlight_yellow(void) {
- return on_tty() ? ANSI_HIGHLIGHT_YELLOW : "";
+ return colors_enabled() ? ANSI_HIGHLIGHT_YELLOW : "";
}
static inline const char *ansi_highlight_blue(void) {
- return on_tty() ? ANSI_HIGHLIGHT_BLUE : "";
+ return colors_enabled() ? ANSI_HIGHLIGHT_BLUE : "";
}
static inline const char *ansi_normal(void) {
- return on_tty() ? ANSI_NORMAL : "";
+ return colors_enabled() ? ANSI_NORMAL : "";
}
int get_ctty_devnr(pid_t pid, dev_t *d);
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
index 56e1a3be48..70a6e1f5e4 100644
--- a/src/basic/user-util.c
+++ b/src/basic/user-util.c
@@ -68,7 +68,7 @@ int parse_uid(const char *s, uid_t *ret) {
if (!uid_is_valid(uid))
return -ENXIO; /* we return ENXIO instead of EINVAL
* here, to make it easy to distuingish
- * invalid numeric uids invalid
+ * invalid numeric uids from invalid
* strings. */
if (ret)
diff --git a/src/basic/util.c b/src/basic/util.c
index 9e0b576283..4434ecfdf6 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -513,7 +513,7 @@ int on_ac_power(void) {
errno = 0;
de = readdir(d);
- if (!de && errno != 0)
+ if (!de && errno > 0)
return -errno;
if (!de)