summaryrefslogtreecommitdiff
path: root/src/basic
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic')
-rw-r--r--src/basic/af-list.c6
-rw-r--r--src/basic/arphrd-list.c4
-rw-r--r--src/basic/async.c4
-rw-r--r--src/basic/audit-util.h2
-rw-r--r--src/basic/bitmap.h2
-rw-r--r--src/basic/btrfs-util.c71
-rw-r--r--src/basic/btrfs-util.h4
-rw-r--r--src/basic/calendarspec.c238
-rw-r--r--src/basic/calendarspec.h3
-rw-r--r--src/basic/cap-list.c2
-rw-r--r--src/basic/cgroup-util.h6
-rw-r--r--src/basic/env-util.c15
-rw-r--r--src/basic/env-util.h1
-rw-r--r--src/basic/errno-list.c4
-rw-r--r--src/basic/escape.c16
-rw-r--r--src/basic/escape.h3
-rw-r--r--src/basic/exit-status.c4
-rw-r--r--src/basic/extract-word.c4
-rw-r--r--src/basic/extract-word.h9
-rw-r--r--src/basic/fd-util.h6
-rw-r--r--src/basic/fdset.c6
-rw-r--r--src/basic/fileio-label.c4
-rw-r--r--src/basic/fileio-label.h1
-rw-r--r--src/basic/fileio.c119
-rw-r--r--src/basic/fileio.h7
-rw-r--r--src/basic/fs-util.c24
-rw-r--r--src/basic/fs-util.h3
-rw-r--r--src/basic/gunicode.h2
-rw-r--r--src/basic/hashmap.c2
-rw-r--r--src/basic/hostname-util.c2
-rw-r--r--src/basic/in-addr-util.c15
-rw-r--r--src/basic/in-addr-util.h1
-rw-r--r--src/basic/ioprio.h2
-rw-r--r--src/basic/json.c2
-rw-r--r--src/basic/json.h1
-rw-r--r--src/basic/label.c2
-rw-r--r--src/basic/lockfile-util.c8
-rw-r--r--src/basic/login-util.c2
-rw-r--r--src/basic/memfd-util.h2
-rw-r--r--src/basic/mempool.c2
-rw-r--r--src/basic/missing.h23
-rw-r--r--src/basic/mkdir-label.c2
-rw-r--r--src/basic/mkdir.c2
-rw-r--r--src/basic/ordered-set.h11
-rw-r--r--src/basic/parse-util.c36
-rw-r--r--src/basic/parse-util.h2
-rw-r--r--src/basic/process-util.h6
-rw-r--r--src/basic/selinux-util.c6
-rw-r--r--src/basic/selinux-util.h2
-rw-r--r--src/basic/set.h1
-rw-r--r--src/basic/sigbus.c2
-rw-r--r--src/basic/siphash24.c112
-rw-r--r--src/basic/siphash24.h16
-rw-r--r--src/basic/socket-util.h4
-rw-r--r--src/basic/stat-util.h5
-rw-r--r--src/basic/strv.c2
-rw-r--r--src/basic/strxcpyx.c1
-rw-r--r--src/basic/terminal-util.h2
-rw-r--r--src/basic/time-util.c93
-rw-r--r--src/basic/unaligned.h47
-rw-r--r--src/basic/unit-name.c13
-rw-r--r--src/basic/unit-name.h15
-rw-r--r--src/basic/user-util.c2
-rw-r--r--src/basic/user-util.h2
-rw-r--r--src/basic/utf8.c4
-rw-r--r--src/basic/util.c12
-rw-r--r--src/basic/virt.c13
67 files changed, 695 insertions, 352 deletions
diff --git a/src/basic/af-list.c b/src/basic/af-list.c
index f396115a34..07dfff6ad4 100644
--- a/src/basic/af-list.c
+++ b/src/basic/af-list.c
@@ -19,16 +19,16 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/socket.h>
#include <string.h>
+#include <sys/socket.h>
-#include "util.h"
#include "af-list.h"
+#include "util.h"
static const struct af_name* lookup_af(register const char *str, register unsigned int len);
-#include "af-to-name.h"
#include "af-from-name.h"
+#include "af-to-name.h"
const char *af_to_name(int id) {
diff --git a/src/basic/arphrd-list.c b/src/basic/arphrd-list.c
index 284043cd90..03d8ad7403 100644
--- a/src/basic/arphrd-list.c
+++ b/src/basic/arphrd-list.c
@@ -22,13 +22,13 @@
#include <net/if_arp.h>
#include <string.h>
-#include "util.h"
#include "arphrd-list.h"
+#include "util.h"
static const struct arphrd_name* lookup_arphrd(register const char *str, register unsigned int len);
-#include "arphrd-to-name.h"
#include "arphrd-from-name.h"
+#include "arphrd-to-name.h"
const char *arphrd_to_name(int id) {
diff --git a/src/basic/async.c b/src/basic/async.c
index c3135f0efe..cfc5d224e1 100644
--- a/src/basic/async.c
+++ b/src/basic/async.c
@@ -68,7 +68,7 @@ int asynchronous_sync(void) {
}
static void *close_thread(void *p) {
- assert_se(close_nointr(PTR_TO_INT(p)) != -EBADF);
+ assert_se(close_nointr(PTR_TO_FD(p)) != -EBADF);
return NULL;
}
@@ -84,7 +84,7 @@ int asynchronous_close(int fd) {
if (fd >= 0) {
PROTECT_ERRNO;
- r = asynchronous_job(close_thread, INT_TO_PTR(fd));
+ r = asynchronous_job(close_thread, FD_TO_PTR(fd));
if (r < 0)
assert_se(close_nointr(fd) != -EBADF);
}
diff --git a/src/basic/audit-util.h b/src/basic/audit-util.h
index 6de331c73e..026d3cd9b1 100644
--- a/src/basic/audit-util.h
+++ b/src/basic/audit-util.h
@@ -21,8 +21,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdint.h>
#include <stdbool.h>
+#include <stdint.h>
#include <sys/types.h>
#define AUDIT_SESSION_INVALID ((uint32_t) -1)
diff --git a/src/basic/bitmap.h b/src/basic/bitmap.h
index 2874bc99f7..9ce7b42d00 100644
--- a/src/basic/bitmap.h
+++ b/src/basic/bitmap.h
@@ -21,8 +21,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "macro.h"
#include "hashmap.h"
+#include "macro.h"
typedef struct Bitmap Bitmap;
diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c
index 4c90bc0c80..be40dc5702 100644
--- a/src/basic/btrfs-util.c
+++ b/src/basic/btrfs-util.c
@@ -105,7 +105,7 @@ int btrfs_is_filesystem(int fd) {
return F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC);
}
-int btrfs_is_subvol(int fd) {
+int btrfs_is_subvol_fd(int fd) {
struct stat st;
assert(fd >= 0);
@@ -121,6 +121,18 @@ int btrfs_is_subvol(int fd) {
return btrfs_is_filesystem(fd);
}
+int btrfs_is_subvol(const char *path) {
+ _cleanup_close_ int fd = -1;
+
+ assert(path);
+
+ fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
+ if (fd < 0)
+ return -errno;
+
+ return btrfs_is_subvol_fd(fd);
+}
+
int btrfs_subvol_make(const char *path) {
struct btrfs_ioctl_vol_args args = {};
_cleanup_close_ int fd = -1;
@@ -575,8 +587,12 @@ int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *ret) {
unsigned i;
args.key.nr_items = 256;
- if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
+ if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) {
+ if (errno == ENOENT) /* quota tree is missing: quota disabled */
+ break;
+
return -errno;
+ }
if (args.key.nr_items <= 0)
break;
@@ -1006,6 +1022,10 @@ static int qgroup_create_or_destroy(int fd, bool b, uint64_t qgroupid) {
for (c = 0;; c++) {
if (ioctl(fd, BTRFS_IOC_QGROUP_CREATE, &args) < 0) {
+ /* If quota is not enabled, we get EINVAL. Turn this into a recognizable error */
+ if (errno == EINVAL)
+ return -ENOPROTOOPT;
+
if (errno == EBUSY && c < 10) {
(void) btrfs_quota_scan_wait(fd);
continue;
@@ -1335,8 +1355,12 @@ int btrfs_qgroup_copy_limits(int fd, uint64_t old_qgroupid, uint64_t new_qgroupi
unsigned i;
args.key.nr_items = 256;
- if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
+ if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) {
+ if (errno == ENOENT) /* quota tree missing: quota is not enabled, hence nothing to copy */
+ break;
+
return -errno;
+ }
if (args.key.nr_items <= 0)
break;
@@ -1411,12 +1435,16 @@ static int copy_quota_hierarchy(int fd, uint64_t old_subvol_id, uint64_t new_sub
return n_old_qgroups;
r = btrfs_subvol_get_parent(fd, old_subvol_id, &old_parent_id);
- if (r < 0)
+ if (r == -ENXIO)
+ /* We have no parent, hence nothing to copy. */
+ n_old_parent_qgroups = 0;
+ else if (r < 0)
return r;
-
- n_old_parent_qgroups = btrfs_qgroup_find_parents(fd, old_parent_id, &old_parent_qgroups);
- if (n_old_parent_qgroups < 0)
- return n_old_parent_qgroups;
+ else {
+ n_old_parent_qgroups = btrfs_qgroup_find_parents(fd, old_parent_id, &old_parent_qgroups);
+ if (n_old_parent_qgroups < 0)
+ return n_old_parent_qgroups;
+ }
for (i = 0; i < n_old_qgroups; i++) {
uint64_t id;
@@ -1670,7 +1698,7 @@ int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlag
assert(old_fd >= 0);
assert(new_path);
- r = btrfs_is_subvol(old_fd);
+ r = btrfs_is_subvol_fd(old_fd);
if (r < 0)
return r;
if (r == 0) {
@@ -1766,8 +1794,12 @@ int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret) {
unsigned i;
args.key.nr_items = 256;
- if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
+ if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) {
+ if (errno == ENOENT) /* quota tree missing: quota is disabled */
+ break;
+
return -errno;
+ }
if (args.key.nr_items <= 0)
break;
@@ -1852,7 +1884,7 @@ int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool insert_intermed
*/
if (subvol_id == 0) {
- r = btrfs_is_subvol(fd);
+ r = btrfs_is_subvol_fd(fd);
if (r < 0)
return r;
if (!r)
@@ -1869,14 +1901,19 @@ int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool insert_intermed
if (n > 0) /* already parent qgroups set up, let's bail */
return 0;
+ qgroups = mfree(qgroups);
+
r = btrfs_subvol_get_parent(fd, subvol_id, &parent_subvol);
- if (r < 0)
+ if (r == -ENXIO)
+ /* No parent, hence no qgroup memberships */
+ n = 0;
+ else if (r < 0)
return r;
-
- qgroups = mfree(qgroups);
- n = btrfs_qgroup_find_parents(fd, parent_subvol, &qgroups);
- if (n < 0)
- return n;
+ else {
+ n = btrfs_qgroup_find_parents(fd, parent_subvol, &qgroups);
+ if (n < 0)
+ return n;
+ }
if (insert_intermediary_qgroup) {
uint64_t lowest = 256, new_qgroupid;
diff --git a/src/basic/btrfs-util.h b/src/basic/btrfs-util.h
index fc9efd72d5..8c11ce35d2 100644
--- a/src/basic/btrfs-util.h
+++ b/src/basic/btrfs-util.h
@@ -56,7 +56,9 @@ typedef enum BtrfsRemoveFlags {
} BtrfsRemoveFlags;
int btrfs_is_filesystem(int fd);
-int btrfs_is_subvol(int fd);
+
+int btrfs_is_subvol_fd(int fd);
+int btrfs_is_subvol(const char *path);
int btrfs_reflink(int infd, int outfd);
int btrfs_clone_range(int infd, uint64_t in_offset, int ofd, uint64_t out_offset, uint64_t sz);
diff --git a/src/basic/calendarspec.c b/src/basic/calendarspec.c
index 7151fc3d0c..8f60561ede 100644
--- a/src/basic/calendarspec.c
+++ b/src/basic/calendarspec.c
@@ -23,9 +23,10 @@
#include <string.h>
#include "alloc-util.h"
-#include "string-util.h"
#include "calendarspec.h"
#include "fileio.h"
+#include "parse-util.h"
+#include "string-util.h"
#define BITS_WEEKDAYS 127
@@ -49,7 +50,7 @@ void calendar_spec_free(CalendarSpec *c) {
free_chain(c->day);
free_chain(c->hour);
free_chain(c->minute);
- free_chain(c->second);
+ free_chain(c->microsecond);
free(c);
}
@@ -135,7 +136,7 @@ int calendar_spec_normalize(CalendarSpec *c) {
sort_chain(&c->day);
sort_chain(&c->hour);
sort_chain(&c->minute);
- sort_chain(&c->second);
+ sort_chain(&c->microsecond);
return 0;
}
@@ -177,7 +178,7 @@ _pure_ bool calendar_spec_valid(CalendarSpec *c) {
if (!chain_valid(c->minute, 0, 59))
return false;
- if (!chain_valid(c->second, 0, 59))
+ if (!chain_valid(c->microsecond, 0, 60*USEC_PER_SEC-1))
return false;
return true;
@@ -232,7 +233,7 @@ static void format_weekdays(FILE *f, const CalendarSpec *c) {
}
}
-static void format_chain(FILE *f, int space, const CalendarComponent *c) {
+static void format_chain(FILE *f, int space, const CalendarComponent *c, bool usec) {
assert(f);
if (!c) {
@@ -241,14 +242,25 @@ static void format_chain(FILE *f, int space, const CalendarComponent *c) {
}
assert(c->value >= 0);
- fprintf(f, "%0*i", space, c->value);
-
- if (c->repeat > 0)
- fprintf(f, "/%i", c->repeat);
+ if (!usec)
+ fprintf(f, "%0*i", space, c->value);
+ else if (c->value % USEC_PER_SEC == 0)
+ fprintf(f, "%0*i", space, (int) (c->value / USEC_PER_SEC));
+ else
+ fprintf(f, "%0*i.%06i", space, (int) (c->value / USEC_PER_SEC), (int) (c->value % USEC_PER_SEC));
+
+ if (c->repeat > 0) {
+ if (!usec)
+ fprintf(f, "/%i", c->repeat);
+ else if (c->repeat % USEC_PER_SEC == 0)
+ fprintf(f, "/%i", (int) (c->repeat / USEC_PER_SEC));
+ else
+ fprintf(f, "/%i.%06i", (int) (c->repeat / USEC_PER_SEC), (int) (c->repeat % USEC_PER_SEC));
+ }
if (c->next) {
fputc(',', f);
- format_chain(f, space, c->next);
+ format_chain(f, space, c->next, usec);
}
}
@@ -270,17 +282,17 @@ int calendar_spec_to_string(const CalendarSpec *c, char **p) {
fputc(' ', f);
}
- format_chain(f, 4, c->year);
+ format_chain(f, 4, c->year, false);
fputc('-', f);
- format_chain(f, 2, c->month);
+ format_chain(f, 2, c->month, false);
fputc('-', f);
- format_chain(f, 2, c->day);
+ format_chain(f, 2, c->day, false);
fputc(' ', f);
- format_chain(f, 2, c->hour);
+ format_chain(f, 2, c->hour, false);
fputc(':', f);
- format_chain(f, 2, c->minute);
+ format_chain(f, 2, c->minute, false);
fputc(':', f);
- format_chain(f, 2, c->second);
+ format_chain(f, 2, c->microsecond, true);
if (c->utc)
fputs(" UTC", f);
@@ -391,35 +403,70 @@ static int parse_weekdays(const char **p, CalendarSpec *c) {
}
}
-static int prepend_component(const char **p, CalendarComponent **c) {
- unsigned long value, repeat = 0;
- char *e = NULL, *ee = NULL;
- CalendarComponent *cc;
-
- assert(p);
- assert(c);
+static int parse_component_decimal(const char **p, bool usec, unsigned long *res) {
+ unsigned long value;
+ const char *e = NULL;
+ char *ee = NULL;
+ int r;
errno = 0;
- value = strtoul(*p, &e, 10);
+ value = strtoul(*p, &ee, 10);
if (errno > 0)
return -errno;
- if (e == *p)
+ if (ee == *p)
return -EINVAL;
if ((unsigned long) (int) value != value)
return -ERANGE;
+ e = ee;
- if (*e == '/') {
- repeat = strtoul(e+1, &ee, 10);
- if (errno > 0)
- return -errno;
- if (ee == e+1)
- return -EINVAL;
- if ((unsigned long) (int) repeat != repeat)
- return -ERANGE;
- if (repeat <= 0)
+ if (usec) {
+ if (value * USEC_PER_SEC / USEC_PER_SEC != value)
return -ERANGE;
- e = ee;
+ value *= USEC_PER_SEC;
+ if (*e == '.') {
+ unsigned add;
+
+ e++;
+ r = parse_fractional_part_u(&e, 6, &add);
+ if (r < 0)
+ return r;
+
+ if (add + value < value)
+ return -ERANGE;
+ value += add;
+ }
+ }
+
+ *p = e;
+ *res = value;
+
+ return 0;
+}
+
+static int prepend_component(const char **p, bool usec, CalendarComponent **c) {
+ unsigned long value, repeat = 0;
+ CalendarComponent *cc;
+ int r;
+ const char *e;
+
+ assert(p);
+ assert(c);
+
+ e = *p;
+
+ r = parse_component_decimal(&e, usec, &value);
+ if (r < 0)
+ return r;
+
+ if (*e == '/') {
+ e++;
+ r = parse_component_decimal(&e, usec, &repeat);
+ if (r < 0)
+ return r;
+
+ if (repeat == 0)
+ return -ERANGE;
}
if (*e != 0 && *e != ' ' && *e != ',' && *e != '-' && *e != ':')
@@ -438,13 +485,31 @@ static int prepend_component(const char **p, CalendarComponent **c) {
if (*e ==',') {
*p += 1;
- return prepend_component(p, c);
+ return prepend_component(p, usec, c);
}
return 0;
}
-static int parse_chain(const char **p, CalendarComponent **c) {
+static int const_chain(int value, CalendarComponent **c) {
+ CalendarComponent *cc = NULL;
+
+ assert(c);
+
+ cc = new0(CalendarComponent, 1);
+ if (!cc)
+ return -ENOMEM;
+
+ cc->value = value;
+ cc->repeat = 0;
+ cc->next = *c;
+
+ *c = cc;
+
+ return 0;
+}
+
+static int parse_chain(const char **p, bool usec, CalendarComponent **c) {
const char *t;
CalendarComponent *cc = NULL;
int r;
@@ -455,12 +520,19 @@ static int parse_chain(const char **p, CalendarComponent **c) {
t = *p;
if (t[0] == '*') {
+ if (usec) {
+ r = const_chain(0, c);
+ if (r < 0)
+ return r;
+ (*c)->repeat = USEC_PER_SEC;
+ } else
+ *c = NULL;
+
*p = t + 1;
- *c = NULL;
return 0;
}
- r = prepend_component(&t, &cc);
+ r = prepend_component(&t, usec, &cc);
if (r < 0) {
free_chain(cc);
return r;
@@ -471,24 +543,6 @@ static int parse_chain(const char **p, CalendarComponent **c) {
return 0;
}
-static int const_chain(int value, CalendarComponent **c) {
- CalendarComponent *cc = NULL;
-
- assert(c);
-
- cc = new0(CalendarComponent, 1);
- if (!cc)
- return -ENOMEM;
-
- cc->value = value;
- cc->repeat = 0;
- cc->next = *c;
-
- *c = cc;
-
- return 0;
-}
-
static int parse_date(const char **p, CalendarSpec *c) {
const char *t;
int r;
@@ -503,7 +557,7 @@ static int parse_date(const char **p, CalendarSpec *c) {
if (*t == 0)
return 0;
- r = parse_chain(&t, &first);
+ r = parse_chain(&t, false, &first);
if (r < 0)
return r;
@@ -519,7 +573,7 @@ static int parse_date(const char **p, CalendarSpec *c) {
}
t++;
- r = parse_chain(&t, &second);
+ r = parse_chain(&t, false, &second);
if (r < 0) {
free_chain(first);
return r;
@@ -540,7 +594,7 @@ static int parse_date(const char **p, CalendarSpec *c) {
}
t++;
- r = parse_chain(&t, &third);
+ r = parse_chain(&t, false, &third);
if (r < 0) {
free_chain(first);
free_chain(second);
@@ -582,7 +636,7 @@ static int parse_calendar_time(const char **p, CalendarSpec *c) {
goto finish;
}
- r = parse_chain(&t, &h);
+ r = parse_chain(&t, false, &h);
if (r < 0)
goto fail;
@@ -592,7 +646,7 @@ static int parse_calendar_time(const char **p, CalendarSpec *c) {
}
t++;
- r = parse_chain(&t, &m);
+ r = parse_chain(&t, false, &m);
if (r < 0)
goto fail;
@@ -610,7 +664,7 @@ static int parse_calendar_time(const char **p, CalendarSpec *c) {
}
t++;
- r = parse_chain(&t, &s);
+ r = parse_chain(&t, true, &s);
if (r < 0)
goto fail;
@@ -639,7 +693,8 @@ finish:
*p = t;
c->hour = h;
c->minute = m;
- c->second = s;
+ c->microsecond = s;
+
return 0;
fail:
@@ -671,7 +726,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
}
if (strcaseeq(p, "minutely")) {
- r = const_chain(0, &c->second);
+ r = const_chain(0, &c->microsecond);
if (r < 0)
goto fail;
@@ -679,7 +734,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
r = const_chain(0, &c->minute);
if (r < 0)
goto fail;
- r = const_chain(0, &c->second);
+ r = const_chain(0, &c->microsecond);
if (r < 0)
goto fail;
@@ -690,7 +745,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
r = const_chain(0, &c->minute);
if (r < 0)
goto fail;
- r = const_chain(0, &c->second);
+ r = const_chain(0, &c->microsecond);
if (r < 0)
goto fail;
@@ -704,7 +759,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
r = const_chain(0, &c->minute);
if (r < 0)
goto fail;
- r = const_chain(0, &c->second);
+ r = const_chain(0, &c->microsecond);
if (r < 0)
goto fail;
@@ -724,7 +779,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
r = const_chain(0, &c->minute);
if (r < 0)
goto fail;
- r = const_chain(0, &c->second);
+ r = const_chain(0, &c->microsecond);
if (r < 0)
goto fail;
@@ -738,7 +793,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
r = const_chain(0, &c->minute);
if (r < 0)
goto fail;
- r = const_chain(0, &c->second);
+ r = const_chain(0, &c->microsecond);
if (r < 0)
goto fail;
@@ -765,7 +820,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
r = const_chain(0, &c->minute);
if (r < 0)
goto fail;
- r = const_chain(0, &c->second);
+ r = const_chain(0, &c->microsecond);
if (r < 0)
goto fail;
@@ -789,7 +844,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
r = const_chain(0, &c->minute);
if (r < 0)
goto fail;
- r = const_chain(0, &c->second);
+ r = const_chain(0, &c->microsecond);
if (r < 0)
goto fail;
@@ -906,14 +961,16 @@ static bool matches_weekday(int weekdays_bits, const struct tm *tm, bool utc) {
return (weekdays_bits & (1 << k));
}
-static int find_next(const CalendarSpec *spec, struct tm *tm) {
+static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) {
struct tm c;
+ int tm_usec;
int r;
assert(spec);
assert(tm);
c = *tm;
+ tm_usec = *usec;
for (;;) {
/* Normalize the current date */
@@ -927,7 +984,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
if (r > 0) {
c.tm_mon = 0;
c.tm_mday = 1;
- c.tm_hour = c.tm_min = c.tm_sec = 0;
+ c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
}
if (r < 0 || tm_out_of_bounds(&c, spec->utc))
return r;
@@ -938,29 +995,29 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
if (r > 0) {
c.tm_mday = 1;
- c.tm_hour = c.tm_min = c.tm_sec = 0;
+ c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
}
if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
c.tm_year ++;
c.tm_mon = 0;
c.tm_mday = 1;
- c.tm_hour = c.tm_min = c.tm_sec = 0;
+ c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
continue;
}
r = find_matching_component(spec->day, &c.tm_mday);
if (r > 0)
- c.tm_hour = c.tm_min = c.tm_sec = 0;
+ c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
c.tm_mon ++;
c.tm_mday = 1;
- c.tm_hour = c.tm_min = c.tm_sec = 0;
+ c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
continue;
}
if (!matches_weekday(spec->weekdays_bits, &c, spec->utc)) {
c.tm_mday++;
- c.tm_hour = c.tm_min = c.tm_sec = 0;
+ c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
continue;
}
@@ -969,7 +1026,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
c.tm_min = c.tm_sec = 0;
if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
c.tm_mday ++;
- c.tm_hour = c.tm_min = c.tm_sec = 0;
+ c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
continue;
}
@@ -978,19 +1035,23 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
c.tm_sec = 0;
if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
c.tm_hour ++;
- c.tm_min = c.tm_sec = 0;
+ c.tm_min = c.tm_sec = tm_usec = 0;
continue;
}
- r = find_matching_component(spec->second, &c.tm_sec);
+ c.tm_sec = c.tm_sec * USEC_PER_SEC + tm_usec;
+ r = find_matching_component(spec->microsecond, &c.tm_sec);
+ tm_usec = c.tm_sec % USEC_PER_SEC;
+ c.tm_sec /= USEC_PER_SEC;
+
if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
c.tm_min ++;
- c.tm_sec = 0;
+ c.tm_sec = tm_usec = 0;
continue;
}
-
*tm = c;
+ *usec = tm_usec;
return 0;
}
}
@@ -999,14 +1060,17 @@ int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next)
struct tm tm;
time_t t;
int r;
+ usec_t tm_usec;
assert(spec);
assert(next);
- t = (time_t) (usec / USEC_PER_SEC) + 1;
+ usec++;
+ t = (time_t) (usec / USEC_PER_SEC);
assert_se(localtime_or_gmtime_r(&t, &tm, spec->utc));
+ tm_usec = usec % USEC_PER_SEC;
- r = find_next(spec, &tm);
+ r = find_next(spec, &tm, &tm_usec);
if (r < 0)
return r;
@@ -1014,6 +1078,6 @@ int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next)
if (t == (time_t) -1)
return -EINVAL;
- *next = (usec_t) t * USEC_PER_SEC;
+ *next = (usec_t) t * USEC_PER_SEC + tm_usec;
return 0;
}
diff --git a/src/basic/calendarspec.h b/src/basic/calendarspec.h
index 56dc02f391..75b699682a 100644
--- a/src/basic/calendarspec.h
+++ b/src/basic/calendarspec.h
@@ -25,6 +25,7 @@
* time, a la cron */
#include <stdbool.h>
+
#include "util.h"
typedef struct CalendarComponent {
@@ -44,7 +45,7 @@ typedef struct CalendarSpec {
CalendarComponent *hour;
CalendarComponent *minute;
- CalendarComponent *second;
+ CalendarComponent *microsecond;
} CalendarSpec;
void calendar_spec_free(CalendarSpec *c);
diff --git a/src/basic/cap-list.c b/src/basic/cap-list.c
index 4d391510bc..f0974900cd 100644
--- a/src/basic/cap-list.c
+++ b/src/basic/cap-list.c
@@ -28,8 +28,8 @@
static const struct capability_name* lookup_capability(register const char *str, register unsigned int len);
-#include "cap-to-name.h"
#include "cap-from-name.h"
+#include "cap-to-name.h"
const char *capability_to_name(int id) {
diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h
index 01359fa7cb..a80ee60bd3 100644
--- a/src/basic/cgroup-util.h
+++ b/src/basic/cgroup-util.h
@@ -21,12 +21,12 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
-#include <stdio.h>
#include <dirent.h>
+#include <stdio.h>
+#include <sys/types.h>
-#include "set.h"
#include "def.h"
+#include "set.h"
/* An enum of well known cgroup controllers */
typedef enum CGroupController {
diff --git a/src/basic/env-util.c b/src/basic/env-util.c
index 9ddac5d6a1..441169db31 100644
--- a/src/basic/env-util.c
+++ b/src/basic/env-util.c
@@ -138,6 +138,21 @@ bool strv_env_is_valid(char **e) {
return true;
}
+bool strv_env_name_is_valid(char **l) {
+ char **p, **q;
+
+ STRV_FOREACH(p, l) {
+ if (!env_name_is_valid(*p))
+ return false;
+
+ STRV_FOREACH(q, p + 1)
+ if (streq(*p, *q))
+ return false;
+ }
+
+ return true;
+}
+
bool strv_env_name_or_assignment_is_valid(char **l) {
char **p, **q;
diff --git a/src/basic/env-util.h b/src/basic/env-util.h
index 6485dade18..5efffa3dc7 100644
--- a/src/basic/env-util.h
+++ b/src/basic/env-util.h
@@ -36,6 +36,7 @@ bool strv_env_is_valid(char **e);
#define strv_env_clean(l) strv_env_clean_with_callback(l, NULL, NULL)
char **strv_env_clean_with_callback(char **l, void (*invalid_callback)(const char *p, void *userdata), void *userdata);
+bool strv_env_name_is_valid(char **l);
bool strv_env_name_or_assignment_is_valid(char **l);
char **strv_env_merge(unsigned n_lists, ...);
diff --git a/src/basic/errno-list.c b/src/basic/errno-list.c
index 34d1331486..22869e4136 100644
--- a/src/basic/errno-list.c
+++ b/src/basic/errno-list.c
@@ -21,14 +21,14 @@
#include <string.h>
-#include "util.h"
#include "errno-list.h"
+#include "util.h"
static const struct errno_name* lookup_errno(register const char *str,
register unsigned int len);
-#include "errno-to-name.h"
#include "errno-from-name.h"
+#include "errno-to-name.h"
const char *errno_to_name(int id) {
diff --git a/src/basic/escape.c b/src/basic/escape.c
index 4815161b09..42a84c9317 100644
--- a/src/basic/escape.c
+++ b/src/basic/escape.c
@@ -89,20 +89,20 @@ size_t cescape_char(char c, char *buf) {
return buf - buf_old;
}
-char *cescape(const char *s) {
- char *r, *t;
+char *cescape_length(const char *s, size_t n) {
const char *f;
+ char *r, *t;
- assert(s);
+ assert(s || n == 0);
/* Does C style string escaping. May be reversed with
* cunescape(). */
- r = new(char, strlen(s)*4 + 1);
+ r = new(char, n*4 + 1);
if (!r)
return NULL;
- for (f = s, t = r; *f; f++)
+ for (f = s, t = r; f < s + n; f++)
t += cescape_char(*f, t);
*t = 0;
@@ -110,6 +110,12 @@ char *cescape(const char *s) {
return r;
}
+char *cescape(const char *s) {
+ assert(s);
+
+ return cescape_length(s, strlen(s));
+}
+
int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode) {
int r = 1;
diff --git a/src/basic/escape.h b/src/basic/escape.h
index 85ba909081..52ebf11c4a 100644
--- a/src/basic/escape.h
+++ b/src/basic/escape.h
@@ -21,8 +21,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
#include <inttypes.h>
+#include <sys/types.h>
/* What characters are special in the shell? */
/* must be escaped outside and inside double-quotes */
@@ -35,6 +35,7 @@ typedef enum UnescapeFlags {
} UnescapeFlags;
char *cescape(const char *s);
+char *cescape_length(const char *s, size_t n);
size_t cescape_char(char c, char *buf);
int cunescape(const char *s, UnescapeFlags flags, char **ret);
diff --git a/src/basic/exit-status.c b/src/basic/exit-status.c
index fcff753ada..4c83731540 100644
--- a/src/basic/exit-status.c
+++ b/src/basic/exit-status.c
@@ -19,12 +19,12 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
#include <signal.h>
+#include <stdlib.h>
#include "exit-status.h"
-#include "set.h"
#include "macro.h"
+#include "set.h"
const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) {
diff --git a/src/basic/extract-word.c b/src/basic/extract-word.c
index ff6d211ef4..fd495692fa 100644
--- a/src/basic/extract-word.c
+++ b/src/basic/extract-word.c
@@ -128,7 +128,7 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
} else if (c == quote) { /* found the end quote */
quote = 0;
break;
- } else if (c == '\\') {
+ } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
backslash = true;
break;
} else {
@@ -146,7 +146,7 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES)) {
quote = c;
break;
- } else if (c == '\\') {
+ } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
backslash = true;
break;
} else if (strchr(separators, c)) {
diff --git a/src/basic/extract-word.h b/src/basic/extract-word.h
index ddc1c4f463..9606ab64b3 100644
--- a/src/basic/extract-word.h
+++ b/src/basic/extract-word.h
@@ -24,11 +24,12 @@
#include "macro.h"
typedef enum ExtractFlags {
- EXTRACT_RELAX = 1,
- EXTRACT_CUNESCAPE = 2,
- EXTRACT_CUNESCAPE_RELAX = 4,
- EXTRACT_QUOTES = 8,
+ EXTRACT_RELAX = 1,
+ EXTRACT_CUNESCAPE = 2,
+ EXTRACT_CUNESCAPE_RELAX = 4,
+ EXTRACT_QUOTES = 8,
EXTRACT_DONT_COALESCE_SEPARATORS = 16,
+ EXTRACT_RETAIN_ESCAPE = 32,
} ExtractFlags;
int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags);
diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h
index 1ca10f0383..5ce1592eeb 100644
--- a/src/basic/fd-util.h
+++ b/src/basic/fd-util.h
@@ -21,13 +21,17 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
#include <dirent.h>
#include <stdbool.h>
+#include <stdio.h>
#include <sys/socket.h>
#include "macro.h"
+/* Make sure we can distinguish fd 0 and NULL */
+#define FD_TO_PTR(fd) INT_TO_PTR((fd)+1)
+#define PTR_TO_FD(p) (PTR_TO_INT(p)-1)
+
int close_nointr(int fd);
int safe_close(int fd);
void safe_close_pair(int p[]);
diff --git a/src/basic/fdset.c b/src/basic/fdset.c
index 42b0b2b98f..e5452f3bb0 100644
--- a/src/basic/fdset.c
+++ b/src/basic/fdset.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <errno.h>
#include <dirent.h>
+#include <errno.h>
#include <fcntl.h>
#include "sd-daemon.h"
@@ -36,10 +36,6 @@
#define MAKE_SET(s) ((Set*) s)
#define MAKE_FDSET(s) ((FDSet*) s)
-/* Make sure we can distinguish fd 0 and NULL */
-#define FD_TO_PTR(fd) INT_TO_PTR((fd)+1)
-#define PTR_TO_FD(p) (PTR_TO_INT(p)-1)
-
FDSet *fdset_new(void) {
return MAKE_FDSET(set_new(NULL));
}
diff --git a/src/basic/fileio-label.c b/src/basic/fileio-label.c
index f596f1d11f..0405822ce0 100644
--- a/src/basic/fileio-label.c
+++ b/src/basic/fileio-label.c
@@ -20,9 +20,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
-#include "selinux-util.h"
#include "fileio-label.h"
+#include "selinux-util.h"
+#include "util.h"
int write_string_file_atomic_label(const char *fn, const char *line) {
int r;
diff --git a/src/basic/fileio-label.h b/src/basic/fileio-label.h
index 25fa351be2..9feb3cccb5 100644
--- a/src/basic/fileio-label.h
+++ b/src/basic/fileio-label.h
@@ -23,6 +23,7 @@
***/
#include <stdio.h>
+
#include "fileio.h"
int write_string_file_atomic_label(const char *fn, const char *line);
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index 619dafb517..10aacdc56d 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -28,8 +28,10 @@
#include "fileio.h"
#include "fs-util.h"
#include "hexdecoct.h"
+#include "parse-util.h"
#include "path-util.h"
#include "random-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
#include "umask-util.h"
@@ -76,6 +78,7 @@ static int write_string_file_atomic(const char *fn, const char *line, bool enfor
int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) {
_cleanup_fclose_ FILE *f = NULL;
+ int q, r;
assert(fn);
assert(line);
@@ -83,30 +86,58 @@ int write_string_file(const char *fn, const char *line, WriteStringFileFlags fla
if (flags & WRITE_STRING_FILE_ATOMIC) {
assert(flags & WRITE_STRING_FILE_CREATE);
- return write_string_file_atomic(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
+ r = write_string_file_atomic(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
+ if (r < 0)
+ goto fail;
+
+ return r;
}
if (flags & WRITE_STRING_FILE_CREATE) {
f = fopen(fn, "we");
- if (!f)
- return -errno;
+ if (!f) {
+ r = -errno;
+ goto fail;
+ }
} else {
int fd;
/* We manually build our own version of fopen(..., "we") that
* works without O_CREAT */
fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0)
- return -errno;
+ if (fd < 0) {
+ r = -errno;
+ goto fail;
+ }
f = fdopen(fd, "we");
if (!f) {
+ r = -errno;
safe_close(fd);
- return -errno;
+ goto fail;
}
}
- return write_string_stream(f, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
+ r = write_string_stream(f, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
+ if (r < 0)
+ goto fail;
+
+ return 0;
+
+fail:
+ if (!(flags & WRITE_STRING_FILE_VERIFY_ON_FAILURE))
+ return r;
+
+ f = safe_fclose(f);
+
+ /* OK, the operation failed, but let's see if the right
+ * contents in place already. If so, eat up the error. */
+
+ q = verify_file(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
+ if (q <= 0)
+ return r;
+
+ return 0;
}
int read_one_line_file(const char *fn, char **line) {
@@ -137,15 +168,41 @@ int read_one_line_file(const char *fn, char **line) {
return 0;
}
-int verify_one_line_file(const char *fn, const char *line) {
- _cleanup_free_ char *value = NULL;
- int r;
+int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *buf = NULL;
+ size_t l, k;
- r = read_one_line_file(fn, &value);
- if (r < 0)
- return r;
+ assert(fn);
+ assert(blob);
- return streq(value, line);
+ l = strlen(blob);
+
+ if (accept_extra_nl && endswith(blob, "\n"))
+ accept_extra_nl = false;
+
+ buf = malloc(l + accept_extra_nl + 1);
+ if (!buf)
+ return -ENOMEM;
+
+ f = fopen(fn, "re");
+ if (!f)
+ return -errno;
+
+ /* We try to read one byte more than we need, so that we know whether we hit eof */
+ errno = 0;
+ k = fread(buf, 1, l + accept_extra_nl + 1, f);
+ if (ferror(f))
+ return errno > 0 ? -errno : -EIO;
+
+ if (k != l && k != l + accept_extra_nl)
+ return 0;
+ if (memcmp(buf, blob, l) != 0)
+ return 0;
+ if (k > l && buf[l] != '\n')
+ return 0;
+
+ return 1;
}
int read_full_stream(FILE *f, char **contents, size_t *size) {
@@ -1149,3 +1206,37 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) {
*ret = path_kill_slashes(t);
return 0;
}
+
+int write_timestamp_file_atomic(const char *fn, usec_t n) {
+ char ln[DECIMAL_STR_MAX(n)+2];
+
+ /* Creates a "timestamp" file, that contains nothing but a
+ * usec_t timestamp, formatted in ASCII. */
+
+ if (n <= 0 || n >= USEC_INFINITY)
+ return -ERANGE;
+
+ xsprintf(ln, USEC_FMT "\n", n);
+
+ return write_string_file(fn, ln, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
+}
+
+int read_timestamp_file(const char *fn, usec_t *ret) {
+ _cleanup_free_ char *ln = NULL;
+ uint64_t t;
+ int r;
+
+ r = read_one_line_file(fn, &ln);
+ if (r < 0)
+ return r;
+
+ r = safe_atou64(ln, &t);
+ if (r < 0)
+ return r;
+
+ if (t <= 0 || t >= (uint64_t) USEC_INFINITY)
+ return -ERANGE;
+
+ *ret = (usec_t) t;
+ return 0;
+}
diff --git a/src/basic/fileio.h b/src/basic/fileio.h
index fa7f192331..95e8698941 100644
--- a/src/basic/fileio.h
+++ b/src/basic/fileio.h
@@ -28,11 +28,13 @@
#include <sys/types.h>
#include "macro.h"
+#include "time-util.h"
typedef enum {
WRITE_STRING_FILE_CREATE = 1,
WRITE_STRING_FILE_ATOMIC = 2,
WRITE_STRING_FILE_AVOID_NEWLINE = 4,
+ WRITE_STRING_FILE_VERIFY_ON_FAILURE = 8,
} WriteStringFileFlags;
int write_string_stream(FILE *f, const char *line, bool enforce_newline);
@@ -42,7 +44,7 @@ int read_one_line_file(const char *fn, char **line);
int read_full_file(const char *fn, char **contents, size_t *size);
int read_full_stream(FILE *f, char **contents, size_t *size);
-int verify_one_line_file(const char *fn, const char *line);
+int verify_file(const char *fn, const char *blob, bool accept_extra_nl);
int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
int load_env_file(FILE *f, const char *fname, const char *separator, char ***l);
@@ -77,3 +79,6 @@ int open_tmpfile(const char *path, int flags);
int tempfn_xxxxxx(const char *p, const char *extra, char **ret);
int tempfn_random(const char *p, const char *extra, char **ret);
int tempfn_random_child(const char *p, const char *extra, char **ret);
+
+int write_timestamp_file_atomic(const char *fn, usec_t n);
+int read_timestamp_file(const char *fn, usec_t *ret);
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
index 7aee404bfc..2b6189ad90 100644
--- a/src/basic/fs-util.c
+++ b/src/basic/fs-util.c
@@ -233,6 +233,26 @@ int readlink_and_canonicalize(const char *p, char **r) {
return 0;
}
+int readlink_and_make_absolute_root(const char *root, const char *path, char **ret) {
+ _cleanup_free_ char *target = NULL, *t = NULL;
+ const char *full;
+ int r;
+
+ full = prefix_roota(root, path);
+ r = readlink_malloc(full, &target);
+ if (r < 0)
+ return r;
+
+ t = file_in_same_dir(path, target);
+ if (!t)
+ return -ENOMEM;
+
+ *ret = t;
+ t = NULL;
+
+ return 0;
+}
+
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
assert(path);
@@ -311,7 +331,7 @@ int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gi
if (fd < 0)
return -errno;
- if (mode > 0) {
+ if (mode != MODE_INVALID) {
r = fchmod(fd, mode);
if (r < 0)
return -errno;
@@ -338,7 +358,7 @@ int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gi
}
int touch(const char *path) {
- return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, 0);
+ return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID);
}
int symlink_idempotent(const char *from, const char *to) {
diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h
index b94873e65b..5fbb7bc4c3 100644
--- a/src/basic/fs-util.h
+++ b/src/basic/fs-util.h
@@ -22,10 +22,10 @@
***/
#include <fcntl.h>
+#include <limits.h>
#include <sys/inotify.h>
#include <sys/types.h>
#include <unistd.h>
-#include <limits.h>
#include "time-util.h"
@@ -40,6 +40,7 @@ int readlink_malloc(const char *p, char **r);
int readlink_value(const char *p, char **ret);
int readlink_and_make_absolute(const char *p, char **r);
int readlink_and_canonicalize(const char *p, char **r);
+int readlink_and_make_absolute_root(const char *root, const char *path, char **ret);
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid);
diff --git a/src/basic/gunicode.h b/src/basic/gunicode.h
index e70818fdd7..b03aa43160 100644
--- a/src/basic/gunicode.h
+++ b/src/basic/gunicode.h
@@ -6,8 +6,8 @@
#pragma once
-#include <stdint.h>
#include <stdbool.h>
+#include <stdint.h>
#include <stdlib.h>
char *utf8_prev_char (const char *p);
diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c
index 4109a08c6c..6e501ef6ff 100644
--- a/src/basic/hashmap.c
+++ b/src/basic/hashmap.c
@@ -380,7 +380,7 @@ static unsigned base_bucket_hash(HashmapBase *h, const void *p) {
h->hash_ops->hash(p, &state);
- siphash24_finalize((uint8_t*)&hash, &state);
+ hash = siphash24_finalize(&state);
return (unsigned) (hash % n_buckets(h));
}
diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c
index ea0528c6fc..c57a3cbd60 100644
--- a/src/basic/hostname-util.c
+++ b/src/basic/hostname-util.c
@@ -72,7 +72,7 @@ static bool hostname_valid_char(char c) {
* allow_trailing_dot is true and at least two components are present
* in the name. Note that due to the restricted charset and length
* this call is substantially more conservative than
- * dns_domain_is_valid().
+ * dns_name_is_valid().
*/
bool hostname_is_valid(const char *s, bool allow_trailing_dot) {
unsigned n_dots = 0;
diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c
index f4e24121e7..b75c39aac7 100644
--- a/src/basic/in-addr-util.c
+++ b/src/basic/in-addr-util.c
@@ -44,7 +44,7 @@ int in_addr_is_link_local(int family, const union in_addr_union *u) {
assert(u);
if (family == AF_INET)
- return (be32toh(u->in.s_addr) & 0xFFFF0000) == (169U << 24 | 254U << 16);
+ return (be32toh(u->in.s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
if (family == AF_INET6)
return IN6_IS_ADDR_LINKLOCAL(&u->in6);
@@ -52,6 +52,19 @@ int in_addr_is_link_local(int family, const union in_addr_union *u) {
return -EAFNOSUPPORT;
}
+int in_addr_is_localhost(int family, const union in_addr_union *u) {
+ assert(u);
+
+ if (family == AF_INET)
+ /* All of 127.x.x.x is localhost. */
+ return (be32toh(u->in.s_addr) & UINT32_C(0xFF000000)) == UINT32_C(127) << 24;
+
+ if (family == AF_INET6)
+ return IN6_IS_ADDR_LOOPBACK(&u->in6);
+
+ return -EAFNOSUPPORT;
+}
+
int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b) {
assert(a);
assert(b);
diff --git a/src/basic/in-addr-util.h b/src/basic/in-addr-util.h
index 51af08868c..58f55b3418 100644
--- a/src/basic/in-addr-util.h
+++ b/src/basic/in-addr-util.h
@@ -33,6 +33,7 @@ union in_addr_union {
int in_addr_is_null(int family, const union in_addr_union *u);
int in_addr_is_link_local(int family, const union in_addr_union *u);
+int in_addr_is_localhost(int family, const union in_addr_union *u);
int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b);
int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen);
int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen);
diff --git a/src/basic/ioprio.h b/src/basic/ioprio.h
index e5c71d0043..d8bb6eb497 100644
--- a/src/basic/ioprio.h
+++ b/src/basic/ioprio.h
@@ -4,8 +4,8 @@
/* This is minimal version of Linux' linux/ioprio.h header file, which
* is licensed GPL2 */
-#include <unistd.h>
#include <sys/syscall.h>
+#include <unistd.h>
/*
* Gives us 8 prio classes with 13-bits of data for each class
diff --git a/src/basic/json.c b/src/basic/json.c
index 716705e5ff..9d5dedb934 100644
--- a/src/basic/json.c
+++ b/src/basic/json.c
@@ -23,9 +23,9 @@
#include <sys/types.h>
#include "alloc-util.h"
+#include "hexdecoct.h"
#include "json.h"
#include "macro.h"
-#include "hexdecoct.h"
#include "string-util.h"
#include "utf8.h"
diff --git a/src/basic/json.h b/src/basic/json.h
index e0b4d810b5..8a7d79cb17 100644
--- a/src/basic/json.h
+++ b/src/basic/json.h
@@ -22,6 +22,7 @@
***/
#include <stdbool.h>
+
#include "util.h"
enum {
diff --git a/src/basic/label.c b/src/basic/label.c
index 82f10b21bd..f33502f90f 100644
--- a/src/basic/label.c
+++ b/src/basic/label.c
@@ -19,10 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "label.h"
#include "selinux-util.h"
#include "smack-util.h"
#include "util.h"
-#include "label.h"
int label_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
int r, q;
diff --git a/src/basic/lockfile-util.c b/src/basic/lockfile-util.c
index 87c3aef7af..0bdbae480b 100644
--- a/src/basic/lockfile-util.c
+++ b/src/basic/lockfile-util.c
@@ -19,12 +19,12 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
-#include <stdbool.h>
#include <errno.h>
-#include <string.h>
-#include <stdio.h>
#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/file.h>
#include "alloc-util.h"
diff --git a/src/basic/login-util.c b/src/basic/login-util.c
index 832f477bd2..41cef14e73 100644
--- a/src/basic/login-util.c
+++ b/src/basic/login-util.c
@@ -20,8 +20,8 @@
***/
#include "def.h"
-#include "string-util.h"
#include "login-util.h"
+#include "string-util.h"
bool session_id_valid(const char *id) {
diff --git a/src/basic/memfd-util.h b/src/basic/memfd-util.h
index 2cb404ea81..3e4de008a4 100644
--- a/src/basic/memfd-util.h
+++ b/src/basic/memfd-util.h
@@ -21,8 +21,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
#include <inttypes.h>
+#include <sys/types.h>
int memfd_new(const char *name);
int memfd_new_and_map(const char *name, size_t sz, void **p);
diff --git a/src/basic/mempool.c b/src/basic/mempool.c
index d5d98d8829..9ee6e6a76d 100644
--- a/src/basic/mempool.c
+++ b/src/basic/mempool.c
@@ -20,8 +20,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "mempool.h"
#include "macro.h"
+#include "mempool.h"
#include "util.h"
struct pool {
diff --git a/src/basic/missing.h b/src/basic/missing.h
index 306c56a156..d539ed00e4 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -23,19 +23,20 @@
/* Missing glibc definitions to access certain kernel APIs */
-#include <sys/resource.h>
-#include <sys/syscall.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
#include <errno.h>
-#include <linux/oom.h>
-#include <linux/input.h>
-#include <linux/if_link.h>
-#include <linux/loop.h>
+#include <fcntl.h>
#include <linux/audit.h>
#include <linux/capability.h>
+#include <linux/if_link.h>
+#include <linux/input.h>
+#include <linux/loop.h>
#include <linux/neighbour.h>
+#include <linux/oom.h>
+#include <linux/rtnetlink.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#include <unistd.h>
#ifdef HAVE_AUDIT
#include <libaudit.h>
@@ -900,6 +901,10 @@ static inline int setns(int fd, int nstype) {
#define NDA_MAX (__NDA_MAX - 1)
#endif
+#ifndef RTA_PREF
+#define RTA_PREF 20
+#endif
+
#ifndef IPV6_UNICAST_IF
#define IPV6_UNICAST_IF 76
#endif
diff --git a/src/basic/mkdir-label.c b/src/basic/mkdir-label.c
index 76bbc1edda..c241ef6064 100644
--- a/src/basic/mkdir-label.c
+++ b/src/basic/mkdir-label.c
@@ -20,8 +20,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <unistd.h>
#include <stdio.h>
+#include <unistd.h>
#include "label.h"
#include "mkdir.h"
diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c
index 0214c4627e..5d7fb9a12d 100644
--- a/src/basic/mkdir.c
+++ b/src/basic/mkdir.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <string.h>
#include <errno.h>
+#include <string.h>
#include "fs-util.h"
#include "mkdir.h"
diff --git a/src/basic/ordered-set.h b/src/basic/ordered-set.h
index 6c617ab305..da10e90ff2 100644
--- a/src/basic/ordered-set.h
+++ b/src/basic/ordered-set.h
@@ -29,6 +29,17 @@ static inline OrderedSet* ordered_set_new(const struct hash_ops *ops) {
return (OrderedSet*) ordered_hashmap_new(ops);
}
+static inline int ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops) {
+ if (*s)
+ return 0;
+
+ *s = ordered_set_new(ops);
+ if (!*s)
+ return -ENOMEM;
+
+ return 0;
+}
+
static inline OrderedSet* ordered_set_free(OrderedSet *s) {
ordered_hashmap_free((OrderedHashmap*) s);
return NULL;
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
index 151067e916..3ae99d9334 100644
--- a/src/basic/parse-util.c
+++ b/src/basic/parse-util.c
@@ -490,3 +490,39 @@ int safe_atod(const char *s, double *ret_d) {
*ret_d = (double) d;
return 0;
}
+
+int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
+ size_t i;
+ unsigned val = 0;
+ const char *s;
+
+ s = *p;
+
+ /* accept any number of digits, strtoull is limted to 19 */
+ for(i=0; i < digits; i++,s++) {
+ if (*s < '0' || *s > '9') {
+ if (i == 0)
+ return -EINVAL;
+
+ /* too few digits, pad with 0 */
+ for (; i < digits; i++)
+ val *= 10;
+
+ break;
+ }
+
+ val *= 10;
+ val += *s - '0';
+ }
+
+ /* maybe round up */
+ if (*s >= '5' && *s <= '9')
+ val++;
+
+ s += strspn(s, DIGITS);
+
+ *p = s;
+ *res = val;
+
+ return 0;
+}
diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h
index 408690d0b3..125de53d7a 100644
--- a/src/basic/parse-util.h
+++ b/src/basic/parse-util.h
@@ -90,3 +90,5 @@ static inline int safe_atoli(const char *s, long int *ret_u) {
#endif
int safe_atod(const char *s, double *ret_d);
+
+int parse_fractional_part_u(const char **s, size_t digits, unsigned *res);
diff --git a/src/basic/process-util.h b/src/basic/process-util.h
index 72633ebf70..fdc7e1bdef 100644
--- a/src/basic/process-util.h
+++ b/src/basic/process-util.h
@@ -19,12 +19,12 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdbool.h>
-#include <sys/types.h>
#include <alloca.h>
+#include <signal.h>
+#include <stdbool.h>
#include <stdio.h>
#include <string.h>
-#include <signal.h>
+#include <sys/types.h>
#include "formats-util.h"
#include "macro.h"
diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c
index a821a3d5bb..e8ce5cfd96 100644
--- a/src/basic/selinux-util.c
+++ b/src/basic/selinux-util.c
@@ -24,15 +24,15 @@
#include <sys/un.h>
#ifdef HAVE_SELINUX
-#include <selinux/selinux.h>
-#include <selinux/label.h>
#include <selinux/context.h>
+#include <selinux/label.h>
+#include <selinux/selinux.h>
#endif
#include "alloc-util.h"
-#include "strv.h"
#include "path-util.h"
#include "selinux-util.h"
+#include "strv.h"
#ifdef HAVE_SELINUX
DEFINE_TRIVIAL_CLEANUP_FUNC(security_context_t, freecon);
diff --git a/src/basic/selinux-util.h b/src/basic/selinux-util.h
index 2afcaec183..d19984c5fe 100644
--- a/src/basic/selinux-util.h
+++ b/src/basic/selinux-util.h
@@ -21,8 +21,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/socket.h>
#include <stdbool.h>
+#include <sys/socket.h>
#include "macro.h"
diff --git a/src/basic/set.h b/src/basic/set.h
index 4554ef2d49..5fd7de08f9 100644
--- a/src/basic/set.h
+++ b/src/basic/set.h
@@ -27,7 +27,6 @@
Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
#define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS)
-
static inline Set *set_free(Set *s) {
internal_hashmap_free(HASHMAP_BASE(s));
return NULL;
diff --git a/src/basic/sigbus.c b/src/basic/sigbus.c
index 0108603fe8..c535c89d52 100644
--- a/src/basic/sigbus.c
+++ b/src/basic/sigbus.c
@@ -23,8 +23,8 @@
#include <sys/mman.h>
#include "macro.h"
-#include "util.h"
#include "sigbus.h"
+#include "util.h"
#define SIGBUS_QUEUE_MAX 64
diff --git a/src/basic/siphash24.c b/src/basic/siphash24.c
index 3b61961389..10fc56da69 100644
--- a/src/basic/siphash24.c
+++ b/src/basic/siphash24.c
@@ -17,9 +17,9 @@
coding style)
*/
-#include "sparse-endian.h"
-
#include "siphash24.h"
+#include "sparse-endian.h"
+#include "unaligned.h"
#include "util.h"
static inline uint64_t rotate_left(uint64_t x, uint8_t b) {
@@ -53,37 +53,40 @@ void siphash24_init(struct siphash *state, const uint8_t k[16]) {
assert(state);
assert(k);
- k0 = le64toh(*(le64_t*) k);
- k1 = le64toh(*(le64_t*) (k + 8));
-
- /* "somepseudorandomlygeneratedbytes" */
- state->v0 = 0x736f6d6570736575ULL ^ k0;
- state->v1 = 0x646f72616e646f6dULL ^ k1;
- state->v2 = 0x6c7967656e657261ULL ^ k0;
- state->v3 = 0x7465646279746573ULL ^ k1;
- state->padding = 0;
- state->inlen = 0;
+ k0 = unaligned_read_le64(k);
+ k1 = unaligned_read_le64(k + 8);
+
+ *state = (struct siphash) {
+ /* "somepseudorandomlygeneratedbytes" */
+ .v0 = 0x736f6d6570736575ULL ^ k0,
+ .v1 = 0x646f72616e646f6dULL ^ k1,
+ .v2 = 0x6c7967656e657261ULL ^ k0,
+ .v3 = 0x7465646279746573ULL ^ k1,
+ .padding = 0,
+ .inlen = 0,
+ };
}
void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
- uint64_t m;
+
const uint8_t *in = _in;
const uint8_t *end = in + inlen;
- unsigned left = state->inlen & 7;
+ size_t left = state->inlen & 7;
+ uint64_t m;
assert(in);
assert(state);
- /* update total length */
+ /* Update total length */
state->inlen += inlen;
- /* if padding exists, fill it out */
+ /* If padding exists, fill it out */
if (left > 0) {
- for ( ; in < end && left < 8; in ++, left ++ )
- state->padding |= ( ( uint64_t )*in ) << (left * 8);
+ for ( ; in < end && left < 8; in ++, left ++)
+ state->padding |= ((uint64_t) *in) << (left * 8);
if (in == end && left < 8)
- /* we did not have enough input to fill out the padding completely */
+ /* We did not have enough input to fill out the padding completely */
return;
#ifdef DEBUG
@@ -93,6 +96,7 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
printf("(%3zu) compress padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t)state->padding);
#endif
+
state->v3 ^= state->padding;
sipround(state);
sipround(state);
@@ -101,10 +105,10 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
state->padding = 0;
}
- end -= ( state->inlen % sizeof (uint64_t) );
+ end -= (state->inlen % sizeof(uint64_t));
- for ( ; in < end; in += 8 ) {
- m = le64toh(*(le64_t*) in);
+ for ( ; in < end; in += 8) {
+ m = unaligned_read_le64(in);
#ifdef DEBUG
printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
@@ -119,38 +123,41 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
}
left = state->inlen & 7;
-
- switch(left)
- {
- case 7: state->padding |= ((uint64_t) in[6]) << 48;
-
- case 6: state->padding |= ((uint64_t) in[5]) << 40;
-
- case 5: state->padding |= ((uint64_t) in[4]) << 32;
-
- case 4: state->padding |= ((uint64_t) in[3]) << 24;
-
- case 3: state->padding |= ((uint64_t) in[2]) << 16;
-
- case 2: state->padding |= ((uint64_t) in[1]) << 8;
-
- case 1: state->padding |= ((uint64_t) in[0]); break;
-
- case 0: break;
+ switch (left) {
+ case 7:
+ state->padding |= ((uint64_t) in[6]) << 48;
+ case 6:
+ state->padding |= ((uint64_t) in[5]) << 40;
+ case 5:
+ state->padding |= ((uint64_t) in[4]) << 32;
+ case 4:
+ state->padding |= ((uint64_t) in[3]) << 24;
+ case 3:
+ state->padding |= ((uint64_t) in[2]) << 16;
+ case 2:
+ state->padding |= ((uint64_t) in[1]) << 8;
+ case 1:
+ state->padding |= ((uint64_t) in[0]);
+ case 0:
+ break;
}
}
-void siphash24_finalize(uint8_t out[8], struct siphash *state) {
+uint64_t siphash24_finalize(struct siphash *state) {
uint64_t b;
- b = state->padding | (( ( uint64_t )state->inlen ) << 56);
+ assert(state);
+
+ b = state->padding | (((uint64_t) state->inlen) << 56);
+
#ifdef DEBUG
- printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t)state->v0);
- printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t)state->v1);
- printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t)state->v2);
- printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t)state->v3);
+ printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
+ printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
+ printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
+ printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
printf("(%3zu) padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t) state->padding);
#endif
+
state->v3 ^= b;
sipround(state);
sipround(state);
@@ -169,14 +176,17 @@ void siphash24_finalize(uint8_t out[8], struct siphash *state) {
sipround(state);
sipround(state);
- *(le64_t*)out = htole64(state->v0 ^ state->v1 ^ state->v2 ^ state->v3);
+ return state->v0 ^ state->v1 ^ state->v2 ^ state->v3;
}
-/* SipHash-2-4 */
-void siphash24(uint8_t out[8], const void *_in, size_t inlen, const uint8_t k[16]) {
+uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]) {
struct siphash state;
+ assert(in);
+ assert(k);
+
siphash24_init(&state, k);
- siphash24_compress(_in, inlen, &state);
- siphash24_finalize(out, &state);
+ siphash24_compress(in, inlen, &state);
+
+ return siphash24_finalize(&state);
}
diff --git a/src/basic/siphash24.h b/src/basic/siphash24.h
index 6c5cd98ee8..ba4f7d01b6 100644
--- a/src/basic/siphash24.h
+++ b/src/basic/siphash24.h
@@ -4,16 +4,16 @@
#include <sys/types.h>
struct siphash {
- uint64_t v0;
- uint64_t v1;
- uint64_t v2;
- uint64_t v3;
- uint64_t padding;
- size_t inlen;
+ uint64_t v0;
+ uint64_t v1;
+ uint64_t v2;
+ uint64_t v3;
+ uint64_t padding;
+ size_t inlen;
};
void siphash24_init(struct siphash *state, const uint8_t k[16]);
void siphash24_compress(const void *in, size_t inlen, struct siphash *state);
-void siphash24_finalize(uint8_t out[8], struct siphash *state);
+uint64_t siphash24_finalize(struct siphash *state);
-void siphash24(uint8_t out[8], const void *in, size_t inlen, const uint8_t k[16]);
+uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]);
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
index c60f2556af..129ffa811c 100644
--- a/src/basic/socket-util.h
+++ b/src/basic/socket-util.h
@@ -21,9 +21,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/socket.h>
-#include <netinet/in.h>
#include <netinet/ether.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
#include <sys/un.h>
#include <linux/netlink.h>
#include <linux/if_packet.h>
diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h
index 909b220a24..fb92464274 100644
--- a/src/basic/stat-util.h
+++ b/src/basic/stat-util.h
@@ -52,9 +52,8 @@ int path_is_os_tree(const char *path);
int files_same(const char *filea, const char *fileb);
/* The .f_type field of struct statfs is really weird defined on
- * different archs. Let's use our own type we know is sufficiently
- * larger to store the possible values. */
-typedef long statfs_f_type_t;
+ * different archs. Let's give its type a name. */
+typedef typeof(((struct statfs*)NULL)->f_type) statfs_f_type_t;
bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) _pure_;
int fd_check_fstype(int fd, statfs_f_type_t magic_value);
diff --git a/src/basic/strv.c b/src/basic/strv.c
index ba6df716a7..771781f9fc 100644
--- a/src/basic/strv.c
+++ b/src/basic/strv.c
@@ -27,8 +27,8 @@
#include "alloc-util.h"
#include "escape.h"
#include "string-util.h"
-#include "util.h"
#include "strv.h"
+#include "util.h"
char *strv_find(char **l, const char *name) {
char **i;
diff --git a/src/basic/strxcpyx.c b/src/basic/strxcpyx.c
index 6542c0abf5..088ba53c29 100644
--- a/src/basic/strxcpyx.c
+++ b/src/basic/strxcpyx.c
@@ -27,6 +27,7 @@
#include <stdio.h>
#include <string.h>
+
#include "strxcpyx.h"
size_t strpcpy(char **dest, size_t size, const char *src) {
diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h
index f2185c1c11..b2c7a297ae 100644
--- a/src/basic/terminal-util.h
+++ b/src/basic/terminal-util.h
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdbool.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <stdio.h>
#include "macro.h"
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
index b36fbe4f09..b9da6991da 100644
--- a/src/basic/time-util.c
+++ b/src/basic/time-util.c
@@ -27,6 +27,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
+#include "parse-util.h"
#include "path-util.h"
#include "string-util.h"
#include "strv.h"
@@ -323,15 +324,15 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
const char *suffix;
usec_t usec;
} table[] = {
- { "y", USEC_PER_YEAR },
- { "month", USEC_PER_MONTH },
- { "w", USEC_PER_WEEK },
- { "d", USEC_PER_DAY },
- { "h", USEC_PER_HOUR },
- { "min", USEC_PER_MINUTE },
- { "s", USEC_PER_SEC },
- { "ms", USEC_PER_MSEC },
- { "us", 1 },
+ { "y", USEC_PER_YEAR },
+ { "month", USEC_PER_MONTH },
+ { "w", USEC_PER_WEEK },
+ { "d", USEC_PER_DAY },
+ { "h", USEC_PER_HOUR },
+ { "min", USEC_PER_MINUTE },
+ { "s", USEC_PER_SEC },
+ { "ms", USEC_PER_MSEC },
+ { "us", 1 },
};
unsigned i;
@@ -658,29 +659,18 @@ int parse_timestamp(const char *t, usec_t *usec) {
parse_usec:
{
- char *end;
- unsigned long long val;
- size_t l;
+ unsigned add;
k++;
- if (*k < '0' || *k > '9')
+ r = parse_fractional_part_u(&k, 6, &add);
+ if (r < 0)
return -EINVAL;
- /* base 10 instead of base 0, .09 is not base 8 */
- errno = 0;
- val = strtoull(k, &end, 10);
- if (*end || errno)
+ if (*k)
return -EINVAL;
- l = end-k;
-
- /* val has l digits, make them 6 */
- for (; l < 6; l++)
- val *= 10;
- for (; l > 6; l--)
- val /= 10;
+ x_usec = add;
- x_usec = val;
}
from_tm:
@@ -711,33 +701,34 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
const char *suffix;
usec_t usec;
} table[] = {
- { "seconds", USEC_PER_SEC },
- { "second", USEC_PER_SEC },
- { "sec", USEC_PER_SEC },
- { "s", USEC_PER_SEC },
+ { "seconds", USEC_PER_SEC },
+ { "second", USEC_PER_SEC },
+ { "sec", USEC_PER_SEC },
+ { "s", USEC_PER_SEC },
{ "minutes", USEC_PER_MINUTE },
- { "minute", USEC_PER_MINUTE },
- { "min", USEC_PER_MINUTE },
- { "months", USEC_PER_MONTH },
- { "month", USEC_PER_MONTH },
- { "msec", USEC_PER_MSEC },
- { "ms", USEC_PER_MSEC },
- { "m", USEC_PER_MINUTE },
- { "hours", USEC_PER_HOUR },
- { "hour", USEC_PER_HOUR },
- { "hr", USEC_PER_HOUR },
- { "h", USEC_PER_HOUR },
- { "days", USEC_PER_DAY },
- { "day", USEC_PER_DAY },
- { "d", USEC_PER_DAY },
- { "weeks", USEC_PER_WEEK },
- { "week", USEC_PER_WEEK },
- { "w", USEC_PER_WEEK },
- { "years", USEC_PER_YEAR },
- { "year", USEC_PER_YEAR },
- { "y", USEC_PER_YEAR },
- { "usec", 1ULL },
- { "us", 1ULL },
+ { "minute", USEC_PER_MINUTE },
+ { "min", USEC_PER_MINUTE },
+ { "months", USEC_PER_MONTH },
+ { "month", USEC_PER_MONTH },
+ { "M", USEC_PER_MONTH },
+ { "msec", USEC_PER_MSEC },
+ { "ms", USEC_PER_MSEC },
+ { "m", USEC_PER_MINUTE },
+ { "hours", USEC_PER_HOUR },
+ { "hour", USEC_PER_HOUR },
+ { "hr", USEC_PER_HOUR },
+ { "h", USEC_PER_HOUR },
+ { "days", USEC_PER_DAY },
+ { "day", USEC_PER_DAY },
+ { "d", USEC_PER_DAY },
+ { "weeks", USEC_PER_WEEK },
+ { "week", USEC_PER_WEEK },
+ { "w", USEC_PER_WEEK },
+ { "years", USEC_PER_YEAR },
+ { "year", USEC_PER_YEAR },
+ { "y", USEC_PER_YEAR },
+ { "usec", 1ULL },
+ { "us", 1ULL },
};
const char *p, *s;
diff --git a/src/basic/unaligned.h b/src/basic/unaligned.h
index d6181dd9a9..a8115eaa1f 100644
--- a/src/basic/unaligned.h
+++ b/src/basic/unaligned.h
@@ -21,8 +21,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <endian.h>
#include <stdint.h>
+/* BE */
+
static inline uint16_t unaligned_read_be16(const void *_u) {
const uint8_t *u = _u;
@@ -64,3 +67,47 @@ static inline void unaligned_write_be64(void *_u, uint64_t a) {
unaligned_write_be32(u, (uint32_t) (a >> 32));
unaligned_write_be32(u + 4, (uint32_t) a);
}
+
+/* LE */
+
+static inline uint16_t unaligned_read_le16(const void *_u) {
+ const uint8_t *u = _u;
+
+ return (((uint16_t) u[1]) << 8) |
+ ((uint16_t) u[0]);
+}
+
+static inline uint32_t unaligned_read_le32(const void *_u) {
+ const uint8_t *u = _u;
+
+ return (((uint32_t) unaligned_read_le16(u + 2)) << 16) |
+ ((uint32_t) unaligned_read_le16(u));
+}
+
+static inline uint64_t unaligned_read_le64(const void *_u) {
+ const uint8_t *u = _u;
+
+ return (((uint64_t) unaligned_read_le32(u + 4)) << 32) |
+ ((uint64_t) unaligned_read_le32(u));
+}
+
+static inline void unaligned_write_le16(void *_u, uint16_t a) {
+ uint8_t *u = _u;
+
+ u[0] = (uint8_t) a;
+ u[1] = (uint8_t) (a >> 8);
+}
+
+static inline void unaligned_write_le32(void *_u, uint32_t a) {
+ uint8_t *u = _u;
+
+ unaligned_write_le16(u, (uint16_t) a);
+ unaligned_write_le16(u + 2, (uint16_t) (a >> 16));
+}
+
+static inline void unaligned_write_le64(void *_u, uint64_t a) {
+ uint8_t *u = _u;
+
+ unaligned_write_le32(u, (uint32_t) a);
+ unaligned_write_le32(u + 4, (uint32_t) (a >> 32));
+}
diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c
index 710421508c..9a55eacbfb 100644
--- a/src/basic/unit-name.c
+++ b/src/basic/unit-name.c
@@ -597,7 +597,6 @@ const char* unit_dbus_interface_from_type(UnitType t) {
[UNIT_SOCKET] = "org.freedesktop.systemd1.Socket",
[UNIT_BUSNAME] = "org.freedesktop.systemd1.BusName",
[UNIT_TARGET] = "org.freedesktop.systemd1.Target",
- [UNIT_SNAPSHOT] = "org.freedesktop.systemd1.Snapshot",
[UNIT_DEVICE] = "org.freedesktop.systemd1.Device",
[UNIT_MOUNT] = "org.freedesktop.systemd1.Mount",
[UNIT_AUTOMOUNT] = "org.freedesktop.systemd1.Automount",
@@ -819,7 +818,6 @@ static const char* const unit_type_table[_UNIT_TYPE_MAX] = {
[UNIT_SOCKET] = "socket",
[UNIT_BUSNAME] = "busname",
[UNIT_TARGET] = "target",
- [UNIT_SNAPSHOT] = "snapshot",
[UNIT_DEVICE] = "device",
[UNIT_MOUNT] = "mount",
[UNIT_AUTOMOUNT] = "automount",
@@ -950,13 +948,6 @@ static const char* const slice_state_table[_SLICE_STATE_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
-static const char* const snapshot_state_table[_SNAPSHOT_STATE_MAX] = {
- [SNAPSHOT_DEAD] = "dead",
- [SNAPSHOT_ACTIVE] = "active"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(snapshot_state, SnapshotState);
-
static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
[SOCKET_DEAD] = "dead",
[SOCKET_START_PRE] = "start-pre",
@@ -1009,16 +1000,12 @@ DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
[UNIT_REQUIRES] = "Requires",
- [UNIT_REQUIRES_OVERRIDABLE] = "RequiresOverridable",
[UNIT_REQUISITE] = "Requisite",
- [UNIT_REQUISITE_OVERRIDABLE] = "RequisiteOverridable",
[UNIT_WANTS] = "Wants",
[UNIT_BINDS_TO] = "BindsTo",
[UNIT_PART_OF] = "PartOf",
[UNIT_REQUIRED_BY] = "RequiredBy",
- [UNIT_REQUIRED_BY_OVERRIDABLE] = "RequiredByOverridable",
[UNIT_REQUISITE_OF] = "RequisiteOf",
- [UNIT_REQUISITE_OF_OVERRIDABLE] = "RequisiteOfOverridable",
[UNIT_WANTED_BY] = "WantedBy",
[UNIT_BOUND_BY] = "BoundBy",
[UNIT_CONSISTS_OF] = "ConsistsOf",
diff --git a/src/basic/unit-name.h b/src/basic/unit-name.h
index 65b55d9554..03c1a6e4ac 100644
--- a/src/basic/unit-name.h
+++ b/src/basic/unit-name.h
@@ -32,7 +32,6 @@ typedef enum UnitType {
UNIT_SOCKET,
UNIT_BUSNAME,
UNIT_TARGET,
- UNIT_SNAPSHOT,
UNIT_DEVICE,
UNIT_MOUNT,
UNIT_AUTOMOUNT,
@@ -165,13 +164,6 @@ typedef enum SliceState {
_SLICE_STATE_INVALID = -1
} SliceState;
-typedef enum SnapshotState {
- SNAPSHOT_DEAD,
- SNAPSHOT_ACTIVE,
- _SNAPSHOT_STATE_MAX,
- _SNAPSHOT_STATE_INVALID = -1
-} SnapshotState;
-
typedef enum SocketState {
SOCKET_DEAD,
SOCKET_START_PRE,
@@ -226,18 +218,14 @@ typedef enum TimerState {
typedef enum UnitDependency {
/* Positive dependencies */
UNIT_REQUIRES,
- UNIT_REQUIRES_OVERRIDABLE,
UNIT_REQUISITE,
- UNIT_REQUISITE_OVERRIDABLE,
UNIT_WANTS,
UNIT_BINDS_TO,
UNIT_PART_OF,
/* Inverse of the above */
UNIT_REQUIRED_BY, /* inverse of 'requires' is 'required_by' */
- UNIT_REQUIRED_BY_OVERRIDABLE, /* inverse of 'requires_overridable' is 'required_by_overridable' */
UNIT_REQUISITE_OF, /* inverse of 'requisite' is 'requisite_of' */
- UNIT_REQUISITE_OF_OVERRIDABLE,/* inverse of 'requisite_overridable' is 'requisite_of_overridable' */
UNIT_WANTED_BY, /* inverse of 'wants' */
UNIT_BOUND_BY, /* inverse of 'binds_to' */
UNIT_CONSISTS_OF, /* inverse of 'part_of' */
@@ -366,9 +354,6 @@ ServiceState service_state_from_string(const char *s) _pure_;
const char* slice_state_to_string(SliceState i) _const_;
SliceState slice_state_from_string(const char *s) _pure_;
-const char* snapshot_state_to_string(SnapshotState i) _const_;
-SnapshotState snapshot_state_from_string(const char *s) _pure_;
-
const char* socket_state_to_string(SocketState i) _const_;
SocketState socket_state_from_string(const char *s) _pure_;
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
index d6c936db37..397880b0b1 100644
--- a/src/basic/user-util.c
+++ b/src/basic/user-util.c
@@ -19,8 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <pwd.h>
#include <grp.h>
+#include <pwd.h>
#include "alloc-util.h"
#include "fd-util.h"
diff --git a/src/basic/user-util.h b/src/basic/user-util.h
index 11ff6674cf..6106e138be 100644
--- a/src/basic/user-util.h
+++ b/src/basic/user-util.h
@@ -21,8 +21,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
#include <stdbool.h>
+#include <sys/types.h>
bool uid_is_valid(uid_t uid);
diff --git a/src/basic/utf8.c b/src/basic/utf8.c
index 7600d99903..b4063a4cec 100644
--- a/src/basic/utf8.c
+++ b/src/basic/utf8.c
@@ -44,10 +44,10 @@
*/
#include <errno.h>
-#include <stdlib.h>
#include <inttypes.h>
-#include <string.h>
#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
#include "alloc-util.h"
#include "hexdecoct.h"
diff --git a/src/basic/util.c b/src/basic/util.c
index 08bdcd28f2..58617b354a 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -73,6 +73,7 @@
#include "build.h"
#include "def.h"
#include "device-nodes.h"
+#include "dirent-util.h"
#include "env-util.h"
#include "escape.h"
#include "exit-status.h"
@@ -81,19 +82,20 @@
#include "formats-util.h"
#include "gunicode.h"
#include "hashmap.h"
+#include "hexdecoct.h"
#include "hostname-util.h"
#include "ioprio.h"
#include "log.h"
#include "macro.h"
#include "missing.h"
#include "mkdir.h"
-#include "hexdecoct.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "random-util.h"
#include "signal-util.h"
#include "sparse-endian.h"
+#include "stat-util.h"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
@@ -102,8 +104,6 @@
#include "utf8.h"
#include "util.h"
#include "virt.h"
-#include "dirent-util.h"
-#include "stat-util.h"
/* Put this test here for a lack of better place */
assert_cc(EAGAIN == EWOULDBLOCK);
@@ -206,7 +206,7 @@ static int do_execute(char **directories, usec_t timeout, char *argv[]) {
log_debug("Spawned %s as " PID_FMT ".", path, pid);
- r = hashmap_put(pids, UINT_TO_PTR(pid), path);
+ r = hashmap_put(pids, PID_TO_PTR(pid), path);
if (r < 0)
return log_oom();
path = NULL;
@@ -224,10 +224,10 @@ static int do_execute(char **directories, usec_t timeout, char *argv[]) {
_cleanup_free_ char *path = NULL;
pid_t pid;
- pid = PTR_TO_UINT(hashmap_first_key(pids));
+ pid = PTR_TO_PID(hashmap_first_key(pids));
assert(pid > 0);
- path = hashmap_remove(pids, UINT_TO_PTR(pid));
+ path = hashmap_remove(pids, PID_TO_PTR(pid));
assert(path);
wait_for_terminate_and_warn(path, pid, true);
diff --git a/src/basic/virt.c b/src/basic/virt.c
index d088b7a804..b82680a54b 100644
--- a/src/basic/virt.c
+++ b/src/basic/virt.c
@@ -24,6 +24,8 @@
#include <unistd.h>
#include "alloc-util.h"
+#include "dirent-util.h"
+#include "fd-util.h"
#include "fileio.h"
#include "process-util.h"
#include "stat-util.h"
@@ -267,13 +269,20 @@ int detect_vm(void) {
if (cached_found >= 0)
return cached_found;
- r = detect_vm_cpuid();
+ /* We have to use the correct order here:
+ * Some virtualization technologies do use KVM hypervisor but are
+ * expected to be detected as something else. So detect DMI first.
+ *
+ * An example is Virtualbox since version 5.0, which uses KVM backend.
+ * Detection via DMI works corretly, the CPU ID would find KVM
+ * only. */
+ r = detect_vm_dmi();
if (r < 0)
return r;
if (r != VIRTUALIZATION_NONE)
goto finish;
- r = detect_vm_dmi();
+ r = detect_vm_cpuid();
if (r < 0)
return r;
if (r != VIRTUALIZATION_NONE)