summaryrefslogtreecommitdiff
path: root/src/libsystemd/src
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2016-12-17 03:11:52 -0500
committerLuke Shumaker <lukeshu@sbcglobal.net>2016-12-17 03:11:52 -0500
commitb849891b5dde5ee14ab8b7b7db74e65a4a38d993 (patch)
tree29bb0e6fda9b4b170041913de495da057bbe3621 /src/libsystemd/src
parent004efebf9cc559ea131bb9460ee0ee198e2d5da7 (diff)
parent881228ff72434a0e3401a16bd87f179ef0ab1619 (diff)
Merge branch 'notsystemd/postmove' into notsystemd/master
# Conflicts: # src/grp-journal/libjournal-core/.gitignore # src/grp-system/libcore/include/core/mount.h
Diffstat (limited to 'src/libsystemd/src')
-rw-r--r--src/libsystemd/src/sd-bus/bus-common-errors.c25
-rw-r--r--src/libsystemd/src/sd-bus/bus-common-errors.h3
-rw-r--r--src/libsystemd/src/sd-bus/bus-error.c8
-rw-r--r--src/libsystemd/src/sd-bus/bus-internal.h8
-rw-r--r--src/libsystemd/src/sd-bus/bus-slot.c4
-rw-r--r--src/libsystemd/src/sd-bus/bus-track.c262
-rw-r--r--src/libsystemd/src/sd-bus/bus-track.h1
-rw-r--r--src/libsystemd/src/sd-bus/bus-util.c95
-rw-r--r--src/libsystemd/src/sd-bus/bus-util.h1
-rw-r--r--src/libsystemd/src/sd-bus/sd-bus.c144
-rw-r--r--src/libsystemd/src/sd-bus/test-bus-chat.c2
-rw-r--r--src/libsystemd/src/sd-bus/test-bus-creds.c9
-rw-r--r--src/libsystemd/src/sd-bus/test-bus-track.c113
-rw-r--r--src/libsystemd/src/sd-device/sd-device.c5
-rw-r--r--src/libsystemd/src/sd-hwdb/hwdb-internal.h8
-rw-r--r--src/libsystemd/src/sd-hwdb/sd-hwdb.c58
-rw-r--r--src/libsystemd/src/sd-id128/id128-util.c13
-rw-r--r--src/libsystemd/src/sd-id128/id128-util.h5
-rw-r--r--src/libsystemd/src/sd-id128/sd-id128.c22
-rw-r--r--src/libsystemd/src/sd-journal/journal-file.c190
-rw-r--r--src/libsystemd/src/sd-journal/journal-vacuum.c2
-rw-r--r--src/libsystemd/src/sd-journal/journal-verify.c15
-rw-r--r--src/libsystemd/src/sd-journal/lookup3.c6
-rw-r--r--src/libsystemd/src/sd-journal/mmap-cache.c6
-rw-r--r--src/libsystemd/src/sd-journal/sd-journal.c51
-rw-r--r--src/libsystemd/src/sd-netlink/netlink-types.c74
-rw-r--r--src/libsystemd/src/sd-netlink/netlink-types.h1
-rw-r--r--src/libsystemd/src/test.mk9
28 files changed, 863 insertions, 277 deletions
diff --git a/src/libsystemd/src/sd-bus/bus-common-errors.c b/src/libsystemd/src/sd-bus/bus-common-errors.c
index a19e98e94b..be589f8582 100644
--- a/src/libsystemd/src/sd-bus/bus-common-errors.c
+++ b/src/libsystemd/src/sd-bus/bus-common-errors.c
@@ -27,6 +27,7 @@
BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_UNIT, ENOENT),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_PID, ESRCH),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, ENOENT),
SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_EXISTS, EEXIST),
SD_BUS_ERROR_MAP(BUS_ERROR_LOAD_FAILED, EIO),
SD_BUS_ERROR_MAP(BUS_ERROR_JOB_FAILED, EREMOTEIO),
@@ -44,12 +45,16 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_NO_ISOLATION, EPERM),
SD_BUS_ERROR_MAP(BUS_ERROR_SHUTTING_DOWN, ECANCELED),
SD_BUS_ERROR_MAP(BUS_ERROR_SCOPE_NOT_RUNNING, EHOSTDOWN),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DYNAMIC_USER, ESRCH),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NOT_REFERENCED, EUNATCH),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_MACHINE, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_IMAGE, ENOENT),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_MACHINE_FOR_PID, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_MACHINE_EXISTS, EEXIST),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_PRIVATE_NETWORKING, ENOSYS),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_USER_MAPPING, ENXIO),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_GROUP_MAPPING, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SESSION, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SESSION_FOR_PID, ENXIO),
@@ -62,6 +67,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_DEVICE_NOT_TAKEN, EINVAL),
SD_BUS_ERROR_MAP(BUS_ERROR_OPERATION_IN_PROGRESS, EINPROGRESS),
SD_BUS_ERROR_MAP(BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, EOPNOTSUPP),
+ SD_BUS_ERROR_MAP(BUS_ERROR_SESSION_BUSY, EBUSY),
SD_BUS_ERROR_MAP(BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, EALREADY),
@@ -80,6 +86,25 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_LINK_BUSY, EBUSY),
SD_BUS_ERROR_MAP(BUS_ERROR_NETWORK_DOWN, ENETDOWN),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "FORMERR", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "SERVFAIL", EHOSTDOWN),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NXDOMAIN", ENXIO),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTIMP", ENOSYS),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "REFUSED", EACCES),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "YXDOMAIN", EEXIST),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "YRRSET", EEXIST),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NXRRSET", ENOENT),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTAUTH", EACCES),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTZONE", EREMOTE),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADVERS", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADKEY", EKEYREJECTED),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADTIME", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADMODE", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADNAME", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADALG", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADTRUNC", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADCOOKIE", EBADR),
+
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_TRANSFER, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_TRANSFER_IN_PROGRESS, EBUSY),
diff --git a/src/libsystemd/src/sd-bus/bus-common-errors.h b/src/libsystemd/src/sd-bus/bus-common-errors.h
index c8f369cb78..525b79fa77 100644
--- a/src/libsystemd/src/sd-bus/bus-common-errors.h
+++ b/src/libsystemd/src/sd-bus/bus-common-errors.h
@@ -23,6 +23,7 @@
#define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit"
#define BUS_ERROR_NO_UNIT_FOR_PID "org.freedesktop.systemd1.NoUnitForPID"
+#define BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID "org.freedesktop.systemd1.NoUnitForInvocationID"
#define BUS_ERROR_UNIT_EXISTS "org.freedesktop.systemd1.UnitExists"
#define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed"
#define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed"
@@ -40,6 +41,8 @@
#define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation"
#define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown"
#define BUS_ERROR_SCOPE_NOT_RUNNING "org.freedesktop.systemd1.ScopeNotRunning"
+#define BUS_ERROR_NO_SUCH_DYNAMIC_USER "org.freedesktop.systemd1.NoSuchDynamicUser"
+#define BUS_ERROR_NOT_REFERENCED "org.freedesktop.systemd1.NotReferenced"
#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
#define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage"
diff --git a/src/libsystemd/src/sd-bus/bus-error.c b/src/libsystemd/src/sd-bus/bus-error.c
index d6b45c47bc..f07560c4e5 100644
--- a/src/libsystemd/src/sd-bus/bus-error.c
+++ b/src/libsystemd/src/sd-bus/bus-error.c
@@ -71,11 +71,9 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_standard_errors[] = {
SD_BUS_ERROR_MAP_END
};
-/* GCC maps this magically to the beginning and end of the BUS_ERROR_MAP section.
- * Hide them; for currently unknown reasons they get exported to the shared libries
- * even without being listed in the sym file. */
-extern const sd_bus_error_map __start_BUS_ERROR_MAP[] _hidden_;
-extern const sd_bus_error_map __stop_BUS_ERROR_MAP[] _hidden_;
+/* GCC maps this magically to the beginning and end of the BUS_ERROR_MAP section */
+extern const sd_bus_error_map __start_BUS_ERROR_MAP[];
+extern const sd_bus_error_map __stop_BUS_ERROR_MAP[];
/* Additional maps registered with sd_bus_error_add_map() are in this
* NULL terminated array */
diff --git a/src/libsystemd/src/sd-bus/bus-internal.h b/src/libsystemd/src/sd-bus/bus-internal.h
index 6e74da3283..4b313fd24d 100644
--- a/src/libsystemd/src/sd-bus/bus-internal.h
+++ b/src/libsystemd/src/sd-bus/bus-internal.h
@@ -210,6 +210,9 @@ struct sd_bus {
bool is_system:1;
bool is_user:1;
bool allow_interactive_authorization:1;
+ bool exit_on_disconnect:1;
+ bool exited:1;
+ bool exit_triggered:1;
int use_memfd;
@@ -321,12 +324,13 @@ struct sd_bus {
sd_bus_track *track_queue;
LIST_HEAD(sd_bus_slot, slots);
+ LIST_HEAD(sd_bus_track, tracks);
};
#define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
-#define BUS_WQUEUE_MAX 1024
-#define BUS_RQUEUE_MAX 64*1024
+#define BUS_WQUEUE_MAX (192*1024)
+#define BUS_RQUEUE_MAX (192*1024)
#define BUS_MESSAGE_SIZE_MAX (64*1024*1024)
#define BUS_AUTH_SIZE_MAX (64*1024)
diff --git a/src/libsystemd/src/sd-bus/bus-slot.c b/src/libsystemd/src/sd-bus/bus-slot.c
index ffe992013a..c9c7a1c96e 100644
--- a/src/libsystemd/src/sd-bus/bus-slot.c
+++ b/src/libsystemd/src/sd-bus/bus-slot.c
@@ -213,9 +213,7 @@ _public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) {
bus_slot_disconnect(slot);
free(slot->description);
- free(slot);
-
- return NULL;
+ return mfree(slot);
}
_public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) {
diff --git a/src/libsystemd/src/sd-bus/bus-track.c b/src/libsystemd/src/sd-bus/bus-track.c
index 86b321bdea..73cecfe543 100644
--- a/src/libsystemd/src/sd-bus/bus-track.c
+++ b/src/libsystemd/src/sd-bus/bus-track.c
@@ -25,16 +25,27 @@
#include "bus-track.h"
#include "bus-util.h"
+struct track_item {
+ unsigned n_ref;
+ char *name;
+ sd_bus_slot *slot;
+};
+
struct sd_bus_track {
unsigned n_ref;
+ unsigned n_adding; /* are we in the process of adding a new name? */
sd_bus *bus;
sd_bus_track_handler_t handler;
void *userdata;
Hashmap *names;
LIST_FIELDS(sd_bus_track, queue);
Iterator iterator;
- bool in_queue;
- bool modified;
+ bool in_list:1; /* In bus->tracks? */
+ bool in_queue:1; /* In bus->track_queue? */
+ bool modified:1;
+ bool recursive:1;
+
+ LIST_FIELDS(sd_bus_track, tracks);
};
#define MATCH_PREFIX \
@@ -57,15 +68,45 @@ struct sd_bus_track {
_x; \
})
+static struct track_item* track_item_free(struct track_item *i) {
+
+ if (!i)
+ return NULL;
+
+ sd_bus_slot_unref(i->slot);
+ free(i->name);
+ return mfree(i);
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct track_item*, track_item_free);
+
static void bus_track_add_to_queue(sd_bus_track *track) {
assert(track);
+ /* Adds the bus track object to the queue of objects we should dispatch next, subject to a number of
+ * conditions. */
+
+ /* Already in the queue? */
if (track->in_queue)
return;
+ /* if we are currently in the process of adding a new name, then let's not enqueue this just yet, let's wait
+ * until the addition is complete. */
+ if (track->n_adding > 0)
+ return;
+
+ /* still referenced? */
+ if (hashmap_size(track->names) > 0)
+ return;
+
+ /* Nothing to call? */
if (!track->handler)
return;
+ /* Already closed? */
+ if (!track->in_list)
+ return;
+
LIST_PREPEND(queue, track->bus->track_queue, track);
track->in_queue = true;
}
@@ -80,6 +121,24 @@ static void bus_track_remove_from_queue(sd_bus_track *track) {
track->in_queue = false;
}
+static int bus_track_remove_name_fully(sd_bus_track *track, const char *name) {
+ struct track_item *i;
+
+ assert(track);
+ assert(name);
+
+ i = hashmap_remove(track->names, name);
+ if (!i)
+ return 0;
+
+ track_item_free(i);
+
+ bus_track_add_to_queue(track);
+
+ track->modified = true;
+ return 1;
+}
+
_public_ int sd_bus_track_new(
sd_bus *bus,
sd_bus_track **track,
@@ -103,6 +162,9 @@ _public_ int sd_bus_track_new(
t->userdata = userdata;
t->bus = sd_bus_ref(bus);
+ LIST_PREPEND(tracks, bus->tracks, t);
+ t->in_list = true;
+
bus_track_add_to_queue(t);
*track = t;
@@ -122,7 +184,7 @@ _public_ sd_bus_track* sd_bus_track_ref(sd_bus_track *track) {
}
_public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) {
- const char *n;
+ struct track_item *i;
if (!track)
return NULL;
@@ -134,15 +196,16 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) {
return NULL;
}
- while ((n = hashmap_first_key(track->names)))
- sd_bus_track_remove_name(track, n);
+ while ((i = hashmap_steal_first(track->names)))
+ track_item_free(i);
+
+ if (track->in_list)
+ LIST_REMOVE(tracks, track->bus->tracks, track);
bus_track_remove_from_queue(track);
hashmap_free(track->names);
sd_bus_unref(track->bus);
- free(track);
-
- return NULL;
+ return mfree(track);
}
static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
@@ -157,49 +220,76 @@ static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus
if (r < 0)
return 0;
- sd_bus_track_remove_name(track, name);
+ bus_track_remove_name_fully(track, name);
return 0;
}
_public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
- _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
- _cleanup_free_ char *n = NULL;
+ _cleanup_(track_item_freep) struct track_item *n = NULL;
+ struct track_item *i;
const char *match;
int r;
assert_return(track, -EINVAL);
assert_return(service_name_is_valid(name), -EINVAL);
+ i = hashmap_get(track->names, name);
+ if (i) {
+ if (track->recursive) {
+ unsigned k = track->n_ref + 1;
+
+ if (k < track->n_ref) /* Check for overflow */
+ return -EOVERFLOW;
+
+ track->n_ref = k;
+ }
+
+ bus_track_remove_from_queue(track);
+ return 0;
+ }
+
r = hashmap_ensure_allocated(&track->names, &string_hash_ops);
if (r < 0)
return r;
- n = strdup(name);
+ n = new0(struct track_item, 1);
if (!n)
return -ENOMEM;
+ n->name = strdup(name);
+ if (!n->name)
+ return -ENOMEM;
/* First, subscribe to this name */
- match = MATCH_FOR_NAME(n);
- r = sd_bus_add_match(track->bus, &slot, match, on_name_owner_changed, track);
- if (r < 0)
+ match = MATCH_FOR_NAME(name);
+
+ bus_track_remove_from_queue(track); /* don't dispatch this while we work in it */
+
+ track->n_adding++; /* make sure we aren't dispatched while we synchronously add this match */
+ r = sd_bus_add_match(track->bus, &n->slot, match, on_name_owner_changed, track);
+ track->n_adding--;
+ if (r < 0) {
+ bus_track_add_to_queue(track);
return r;
+ }
- r = hashmap_put(track->names, n, slot);
- if (r == -EEXIST)
- return 0;
- if (r < 0)
+ r = hashmap_put(track->names, n->name, n);
+ if (r < 0) {
+ bus_track_add_to_queue(track);
return r;
+ }
- /* Second, check if it is currently existing, or maybe
- * doesn't, or maybe disappeared already. */
- r = sd_bus_get_name_creds(track->bus, n, 0, NULL);
+ /* Second, check if it is currently existing, or maybe doesn't, or maybe disappeared already. */
+ track->n_adding++; /* again, make sure this isn't dispatch while we are working in it */
+ r = sd_bus_get_name_creds(track->bus, name, 0, NULL);
+ track->n_adding--;
if (r < 0) {
- hashmap_remove(track->names, n);
+ hashmap_remove(track->names, name);
+ bus_track_add_to_queue(track);
return r;
}
+ n->n_ref = 1;
n = NULL;
- slot = NULL;
bus_track_remove_from_queue(track);
track->modified = true;
@@ -208,37 +298,48 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
}
_public_ int sd_bus_track_remove_name(sd_bus_track *track, const char *name) {
- _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
- _cleanup_free_ char *n = NULL;
+ struct track_item *i;
assert_return(name, -EINVAL);
- if (!track)
+ if (!track) /* Treat a NULL track object as an empty track object */
return 0;
- slot = hashmap_remove2(track->names, (char*) name, (void**) &n);
- if (!slot)
- return 0;
+ if (!track->recursive)
+ return bus_track_remove_name_fully(track, name);
- if (hashmap_isempty(track->names))
- bus_track_add_to_queue(track);
+ i = hashmap_get(track->names, name);
+ if (!i)
+ return -EUNATCH;
+ if (i->n_ref <= 0)
+ return -EUNATCH;
- track->modified = true;
+ i->n_ref--;
+
+ if (i->n_ref <= 0)
+ return bus_track_remove_name_fully(track, name);
return 1;
}
_public_ unsigned sd_bus_track_count(sd_bus_track *track) {
- if (!track)
+
+ if (!track) /* Let's consider a NULL object equivalent to an empty object */
return 0;
+ /* This signature really should have returned an int, so that we can propagate errors. But well, ... Also, note
+ * that this returns the number of names being watched, and multiple references to the same name are not
+ * counted. */
+
return hashmap_size(track->names);
}
_public_ const char* sd_bus_track_contains(sd_bus_track *track, const char *name) {
- assert_return(track, NULL);
assert_return(name, NULL);
+ if (!track) /* Let's consider a NULL object equivalent to an empty object */
+ return NULL;
+
return hashmap_get(track->names, (void*) name) ? name : NULL;
}
@@ -274,6 +375,9 @@ _public_ int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m) {
assert_return(track, -EINVAL);
assert_return(m, -EINVAL);
+ if (sd_bus_message_get_bus(m) != track->bus)
+ return -EINVAL;
+
sender = sd_bus_message_get_sender(m);
if (!sender)
return -EINVAL;
@@ -284,9 +388,14 @@ _public_ int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m) {
_public_ int sd_bus_track_remove_sender(sd_bus_track *track, sd_bus_message *m) {
const char *sender;
- assert_return(track, -EINVAL);
assert_return(m, -EINVAL);
+ if (!track) /* Treat a NULL track object as an empty track object */
+ return 0;
+
+ if (sd_bus_message_get_bus(m) != track->bus)
+ return -EINVAL;
+
sender = sd_bus_message_get_sender(m);
if (!sender)
return -EINVAL;
@@ -304,7 +413,6 @@ void bus_track_dispatch(sd_bus_track *track) {
int r;
assert(track);
- assert(track->in_queue);
assert(track->handler);
bus_track_remove_from_queue(track);
@@ -320,6 +428,34 @@ void bus_track_dispatch(sd_bus_track *track) {
sd_bus_track_unref(track);
}
+void bus_track_close(sd_bus_track *track) {
+ struct track_item *i;
+
+ assert(track);
+
+ /* Called whenever our bus connected is closed. If so, and our track object is non-empty, dispatch it
+ * immediately, as we are closing now, but first flush out all names. */
+
+ if (!track->in_list)
+ return; /* We already closed this one, don't close it again. */
+
+ /* Remember that this one is closed now */
+ LIST_REMOVE(tracks, track->bus->tracks, track);
+ track->in_list = false;
+
+ /* If there's no name in this one anyway, we don't have to dispatch */
+ if (hashmap_isempty(track->names))
+ return;
+
+ /* Let's flush out all names */
+ while ((i = hashmap_steal_first(track->names)))
+ track_item_free(i);
+
+ /* Invoke handler */
+ if (track->handler)
+ bus_track_dispatch(track);
+}
+
_public_ void *sd_bus_track_get_userdata(sd_bus_track *track) {
assert_return(track, NULL);
@@ -336,3 +472,55 @@ _public_ void *sd_bus_track_set_userdata(sd_bus_track *track, void *userdata) {
return ret;
}
+
+_public_ int sd_bus_track_set_recursive(sd_bus_track *track, int b) {
+ assert_return(track, -EINVAL);
+
+ if (track->recursive == !!b)
+ return 0;
+
+ if (!hashmap_isempty(track->names))
+ return -EBUSY;
+
+ track->recursive = b;
+ return 0;
+}
+
+_public_ int sd_bus_track_get_recursive(sd_bus_track *track) {
+ assert_return(track, -EINVAL);
+
+ return track->recursive;
+}
+
+_public_ int sd_bus_track_count_sender(sd_bus_track *track, sd_bus_message *m) {
+ const char *sender;
+
+ assert_return(m, -EINVAL);
+
+ if (!track) /* Let's consider a NULL object equivalent to an empty object */
+ return 0;
+
+ if (sd_bus_message_get_bus(m) != track->bus)
+ return -EINVAL;
+
+ sender = sd_bus_message_get_sender(m);
+ if (!sender)
+ return -EINVAL;
+
+ return sd_bus_track_count_name(track, sender);
+}
+
+_public_ int sd_bus_track_count_name(sd_bus_track *track, const char *name) {
+ struct track_item *i;
+
+ assert_return(service_name_is_valid(name), -EINVAL);
+
+ if (!track) /* Let's consider a NULL object equivalent to an empty object */
+ return 0;
+
+ i = hashmap_get(track->names, name);
+ if (!i)
+ return 0;
+
+ return i->n_ref;
+}
diff --git a/src/libsystemd/src/sd-bus/bus-track.h b/src/libsystemd/src/sd-bus/bus-track.h
index 73b7503ae5..68398281ae 100644
--- a/src/libsystemd/src/sd-bus/bus-track.h
+++ b/src/libsystemd/src/sd-bus/bus-track.h
@@ -22,3 +22,4 @@
#include <systemd/sd-bus.h>
void bus_track_dispatch(sd_bus_track *track);
+void bus_track_close(sd_bus_track *track);
diff --git a/src/libsystemd/src/sd-bus/bus-util.c b/src/libsystemd/src/sd-bus/bus-util.c
index c82390634e..af44c0f9a4 100644
--- a/src/libsystemd/src/sd-bus/bus-util.c
+++ b/src/libsystemd/src/sd-bus/bus-util.c
@@ -1017,19 +1017,19 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
return r;
switch (type) {
+
case SD_BUS_TYPE_STRING: {
- const char *s;
char **p = userdata;
+ const char *s;
r = sd_bus_message_read_basic(m, type, &s);
if (r < 0)
- break;
+ return r;
if (isempty(s))
- break;
+ s = NULL;
- r = free_and_strdup(p, s);
- break;
+ return free_and_strdup(p, s);
}
case SD_BUS_TYPE_ARRAY: {
@@ -1038,13 +1038,12 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
r = bus_message_read_strv_extend(m, &l);
if (r < 0)
- break;
+ return r;
strv_free(*p);
*p = l;
l = NULL;
-
- break;
+ return 0;
}
case SD_BUS_TYPE_BOOLEAN: {
@@ -1053,57 +1052,48 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
r = sd_bus_message_read_basic(m, type, &b);
if (r < 0)
- break;
+ return r;
*p = b;
-
- break;
+ return 0;
}
+ case SD_BUS_TYPE_INT32:
case SD_BUS_TYPE_UINT32: {
- uint32_t u;
- uint32_t *p = userdata;
+ uint32_t u, *p = userdata;
r = sd_bus_message_read_basic(m, type, &u);
if (r < 0)
- break;
+ return r;
*p = u;
-
- break;
+ return 0;
}
+ case SD_BUS_TYPE_INT64:
case SD_BUS_TYPE_UINT64: {
- uint64_t t;
- uint64_t *p = userdata;
+ uint64_t t, *p = userdata;
r = sd_bus_message_read_basic(m, type, &t);
if (r < 0)
- break;
+ return r;
*p = t;
-
- break;
+ return 0;
}
case SD_BUS_TYPE_DOUBLE: {
- double d;
- double *p = userdata;
+ double d, *p = userdata;
r = sd_bus_message_read_basic(m, type, &d);
if (r < 0)
- break;
+ return r;
*p = d;
+ return 0;
+ }}
- break;
- }
-
- default:
- break;
- }
-
- return r;
+ return -EOPNOTSUPP;
}
int bus_message_map_all_properties(
@@ -1241,12 +1231,13 @@ int bus_map_all_properties(
return bus_message_map_all_properties(m, map, userdata);
}
-int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
+int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) {
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
int r;
assert(transport >= 0);
assert(transport < _BUS_TRANSPORT_MAX);
- assert(bus);
+ assert(ret);
assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
@@ -1255,25 +1246,34 @@ int bus_connect_transport(BusTransport transport, const char *host, bool user, s
case BUS_TRANSPORT_LOCAL:
if (user)
- r = sd_bus_default_user(bus);
+ r = sd_bus_default_user(&bus);
else
- r = sd_bus_default_system(bus);
+ r = sd_bus_default_system(&bus);
break;
case BUS_TRANSPORT_REMOTE:
- r = sd_bus_open_system_remote(bus, host);
+ r = sd_bus_open_system_remote(&bus, host);
break;
case BUS_TRANSPORT_MACHINE:
- r = sd_bus_open_system_machine(bus, host);
+ r = sd_bus_open_system_machine(&bus, host);
break;
default:
assert_not_reached("Hmm, unknown transport type.");
}
+ if (r < 0)
+ return r;
- return r;
+ r = sd_bus_set_exit_on_disconnect(bus, true);
+ if (r < 0)
+ return r;
+
+ *ret = bus;
+ bus = NULL;
+
+ return 0;
}
int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
@@ -1325,6 +1325,23 @@ int bus_property_get_bool(
return sd_bus_message_append_basic(reply, 'b', &b);
}
+int bus_property_get_id128(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ sd_id128_t *id = userdata;
+
+ if (sd_id128_is_null(*id)) /* Add an empty array if the ID is zero */
+ return sd_bus_message_append(reply, "ay", 0);
+ else
+ return sd_bus_message_append_array(reply, 'y', id->bytes, 16);
+}
+
#if __SIZEOF_SIZE_T__ != 8
int bus_property_get_size(
sd_bus *bus,
diff --git a/src/libsystemd/src/sd-bus/bus-util.h b/src/libsystemd/src/sd-bus/bus-util.h
index 6b45fad3ce..01dba4807d 100644
--- a/src/libsystemd/src/sd-bus/bus-util.h
+++ b/src/libsystemd/src/sd-bus/bus-util.h
@@ -79,6 +79,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all);
int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
+int bus_property_get_id128(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
#define bus_property_get_usec ((sd_bus_property_get_t) NULL)
#define bus_property_set_usec ((sd_bus_property_set_t) NULL)
diff --git a/src/libsystemd/src/sd-bus/sd-bus.c b/src/libsystemd/src/sd-bus/sd-bus.c
index 52d3e8f2b3..e9b2bac003 100644
--- a/src/libsystemd/src/sd-bus/sd-bus.c
+++ b/src/libsystemd/src/sd-bus/sd-bus.c
@@ -108,6 +108,7 @@ static void bus_free(sd_bus *b) {
assert(b);
assert(!b->track_queue);
+ assert(!b->tracks);
b->state = BUS_CLOSED;
@@ -2641,62 +2642,101 @@ null_message:
return r;
}
-static int process_closing(sd_bus *bus, sd_bus_message **ret) {
+static int bus_exit_now(sd_bus *bus) {
+ assert(bus);
+
+ /* Exit due to close, if this is requested. If this is bus object is attached to an event source, invokes
+ * sd_event_exit(), otherwise invokes libc exit(). */
+
+ if (bus->exited) /* did we already exit? */
+ return 0;
+ if (!bus->exit_triggered) /* was the exit condition triggered? */
+ return 0;
+ if (!bus->exit_on_disconnect) /* Shall we actually exit on disconnection? */
+ return 0;
+
+ bus->exited = true; /* never exit more than once */
+
+ log_debug("Bus connection disconnected, exiting.");
+
+ if (bus->event)
+ return sd_event_exit(bus->event, EXIT_FAILURE);
+ else
+ exit(EXIT_FAILURE);
+
+ assert_not_reached("exit() didn't exit?");
+}
+
+static int process_closing_reply_callback(sd_bus *bus, struct reply_callback *c) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- struct reply_callback *c;
+ sd_bus_slot *slot;
int r;
assert(bus);
- assert(bus->state == BUS_CLOSING);
+ assert(c);
- c = ordered_hashmap_first(bus->reply_callbacks);
- if (c) {
- _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
- sd_bus_slot *slot;
+ r = bus_message_new_synthetic_error(
+ bus,
+ c->cookie,
+ &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"),
+ &m);
+ if (r < 0)
+ return r;
- /* First, fail all outstanding method calls */
- r = bus_message_new_synthetic_error(
- bus,
- c->cookie,
- &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"),
- &m);
- if (r < 0)
- return r;
+ r = bus_seal_synthetic_message(bus, m);
+ if (r < 0)
+ return r;
- r = bus_seal_synthetic_message(bus, m);
- if (r < 0)
- return r;
+ if (c->timeout != 0) {
+ prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
+ c->timeout = 0;
+ }
- if (c->timeout != 0) {
- prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
- c->timeout = 0;
- }
+ ordered_hashmap_remove(bus->reply_callbacks, &c->cookie);
+ c->cookie = 0;
- ordered_hashmap_remove(bus->reply_callbacks, &c->cookie);
- c->cookie = 0;
+ slot = container_of(c, sd_bus_slot, reply_callback);
- slot = container_of(c, sd_bus_slot, reply_callback);
+ bus->iteration_counter++;
- bus->iteration_counter++;
+ bus->current_message = m;
+ bus->current_slot = sd_bus_slot_ref(slot);
+ bus->current_handler = c->callback;
+ bus->current_userdata = slot->userdata;
+ r = c->callback(m, slot->userdata, &error_buffer);
+ bus->current_userdata = NULL;
+ bus->current_handler = NULL;
+ bus->current_slot = NULL;
+ bus->current_message = NULL;
- bus->current_message = m;
- bus->current_slot = sd_bus_slot_ref(slot);
- bus->current_handler = c->callback;
- bus->current_userdata = slot->userdata;
- r = c->callback(m, slot->userdata, &error_buffer);
- bus->current_userdata = NULL;
- bus->current_handler = NULL;
- bus->current_slot = NULL;
- bus->current_message = NULL;
+ if (slot->floating) {
+ bus_slot_disconnect(slot);
+ sd_bus_slot_unref(slot);
+ }
- if (slot->floating) {
- bus_slot_disconnect(slot);
- sd_bus_slot_unref(slot);
- }
+ sd_bus_slot_unref(slot);
- sd_bus_slot_unref(slot);
+ return bus_maybe_reply_error(m, r, &error_buffer);
+}
- return bus_maybe_reply_error(m, r, &error_buffer);
+static int process_closing(sd_bus *bus, sd_bus_message **ret) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ struct reply_callback *c;
+ int r;
+
+ assert(bus);
+ assert(bus->state == BUS_CLOSING);
+
+ /* First, fail all outstanding method calls */
+ c = ordered_hashmap_first(bus->reply_callbacks);
+ if (c)
+ return process_closing_reply_callback(bus, c);
+
+ /* Then, fake-drop all remaining bus tracking references */
+ if (bus->tracks) {
+ bus_track_close(bus->tracks);
+ return 1;
}
/* Then, synthesize a Disconnected message */
@@ -2728,6 +2768,10 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) {
if (r != 0)
goto finish;
+ /* Nothing else to do, exit now, if the condition holds */
+ bus->exit_triggered = true;
+ (void) bus_exit_now(bus);
+
if (ret) {
*ret = m;
m = NULL;
@@ -3790,3 +3834,21 @@ _public_ void sd_bus_default_flush_close(void) {
flush_close(default_user_bus);
flush_close(default_system_bus);
}
+
+_public_ int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b) {
+ assert_return(bus, -EINVAL);
+
+ /* Turns on exit-on-disconnect, and triggers it immediately if the bus connection was already
+ * disconnected. Note that this is triggered exclusively on disconnections triggered by the server side, never
+ * from the client side. */
+ bus->exit_on_disconnect = b;
+
+ /* If the exit condition was triggered already, exit immediately. */
+ return bus_exit_now(bus);
+}
+
+_public_ int sd_bus_get_exit_on_disconnect(sd_bus *bus) {
+ assert_return(bus, -EINVAL);
+
+ return bus->exit_on_disconnect;
+}
diff --git a/src/libsystemd/src/sd-bus/test-bus-chat.c b/src/libsystemd/src/sd-bus/test-bus-chat.c
index 6dc643c173..2e394c56e2 100644
--- a/src/libsystemd/src/sd-bus/test-bus-chat.c
+++ b/src/libsystemd/src/sd-bus/test-bus-chat.c
@@ -352,7 +352,7 @@ finish:
static int quit_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
bool *x = userdata;
- log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m)));
+ log_error_errno(sd_bus_message_get_errno(m), "Quit callback: %m");
*x = 1;
return 1;
diff --git a/src/libsystemd/src/sd-bus/test-bus-creds.c b/src/libsystemd/src/sd-bus/test-bus-creds.c
index fd226e06d2..ae4f4804d4 100644
--- a/src/libsystemd/src/sd-bus/test-bus-creds.c
+++ b/src/libsystemd/src/sd-bus/test-bus-creds.c
@@ -28,12 +28,17 @@ int main(int argc, char *argv[]) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
int r;
- if (cg_unified() == -ENOMEDIUM) {
- puts("Skipping test: /sys/fs/cgroup/ not available");
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+ log_open();
+
+ if (cg_all_unified() == -ENOMEDIUM) {
+ log_info("Skipping test: /sys/fs/cgroup/ not available");
return EXIT_TEST_SKIP;
}
r = sd_bus_creds_new_from_pid(&creds, 0, _SD_BUS_CREDS_ALL);
+ log_full_errno(r < 0 ? LOG_ERR : LOG_DEBUG, r, "sd_bus_creds_new_from_pid: %m");
assert_se(r >= 0);
bus_creds_dump(creds, NULL, true);
diff --git a/src/libsystemd/src/sd-bus/test-bus-track.c b/src/libsystemd/src/sd-bus/test-bus-track.c
new file mode 100644
index 0000000000..ad87e7f8e0
--- /dev/null
+++ b/src/libsystemd/src/sd-bus/test-bus-track.c
@@ -0,0 +1,113 @@
+/***
+ 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 <systemd/sd-bus.h>
+
+#include "systemd-basic/macro.h"
+
+static bool track_cb_called_x = false;
+static bool track_cb_called_y = false;
+
+static int track_cb_x(sd_bus_track *t, void *userdata) {
+
+ log_error("TRACK CB X");
+
+ assert_se(!track_cb_called_x);
+ track_cb_called_x = true;
+
+ /* This means b's name disappeared. Let's now disconnect, to make sure the track handling on disconnect works
+ * as it should. */
+
+ assert_se(shutdown(sd_bus_get_fd(sd_bus_track_get_bus(t)), SHUT_RDWR) >= 0);
+ return 1;
+}
+
+static int track_cb_y(sd_bus_track *t, void *userdata) {
+ int r;
+
+ log_error("TRACK CB Y");
+
+ assert_se(!track_cb_called_y);
+ track_cb_called_y = true;
+
+ /* We got disconnected, let's close everything */
+
+ r = sd_event_exit(sd_bus_get_event(sd_bus_track_get_bus(t)), EXIT_SUCCESS);
+ assert_se(r >= 0);
+
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ _cleanup_(sd_event_unrefp) sd_event *event = NULL;
+ _cleanup_(sd_bus_track_unrefp) sd_bus_track *x = NULL, *y = NULL;
+ _cleanup_(sd_bus_unrefp) sd_bus *a = NULL, *b = NULL;
+ const char *unique;
+ int r;
+
+ r = sd_event_default(&event);
+ assert_se(r >= 0);
+
+ r = sd_bus_open_system(&a);
+ if (IN_SET(r, -ECONNREFUSED, -ENOENT)) {
+ log_info("Failed to connect to bus, skipping tests.");
+ return EXIT_TEST_SKIP;
+ }
+ assert_se(r >= 0);
+
+ r = sd_bus_attach_event(a, event, SD_EVENT_PRIORITY_NORMAL);
+ assert_se(r >= 0);
+
+ r = sd_bus_open_system(&b);
+ assert_se(r >= 0);
+
+ r = sd_bus_attach_event(b, event, SD_EVENT_PRIORITY_NORMAL);
+ assert_se(r >= 0);
+
+ /* Watch b's name from a */
+ r = sd_bus_track_new(a, &x, track_cb_x, NULL);
+ assert_se(r >= 0);
+
+ r = sd_bus_get_unique_name(b, &unique);
+ assert_se(r >= 0);
+
+ r = sd_bus_track_add_name(x, unique);
+ assert_se(r >= 0);
+
+ /* Watch's a's own name from a */
+ r = sd_bus_track_new(a, &y, track_cb_y, NULL);
+ assert_se(r >= 0);
+
+ r = sd_bus_get_unique_name(a, &unique);
+ assert_se(r >= 0);
+
+ r = sd_bus_track_add_name(y, unique);
+ assert_se(r >= 0);
+
+ /* Now make b's name disappear */
+ sd_bus_close(b);
+
+ r = sd_event_loop(event);
+ assert_se(r >= 0);
+
+ assert_se(track_cb_called_x);
+ assert_se(track_cb_called_y);
+
+ return 0;
+}
diff --git a/src/libsystemd/src/sd-device/sd-device.c b/src/libsystemd/src/sd-device/sd-device.c
index 3f7e21af96..ba654eac14 100644
--- a/src/libsystemd/src/sd-device/sd-device.c
+++ b/src/libsystemd/src/sd-device/sd-device.c
@@ -31,6 +31,7 @@
#include "systemd-basic/parse-util.h"
#include "systemd-basic/path-util.h"
#include "systemd-basic/set.h"
+#include "systemd-basic/socket-util.h"
#include "systemd-basic/stat-util.h"
#include "systemd-basic/string-util.h"
#include "systemd-basic/strv.h"
@@ -629,9 +630,9 @@ _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
if (r < 0)
return r;
- sk = socket(PF_INET, SOCK_DGRAM, 0);
+ sk = socket_ioctl_fd();
if (sk < 0)
- return -errno;
+ return sk;
r = ioctl(sk, SIOCGIFNAME, &ifr);
if (r < 0)
diff --git a/src/libsystemd/src/sd-hwdb/hwdb-internal.h b/src/libsystemd/src/sd-hwdb/hwdb-internal.h
index 35d4378122..78f430e869 100644
--- a/src/libsystemd/src/sd-hwdb/hwdb-internal.h
+++ b/src/libsystemd/src/sd-hwdb/hwdb-internal.h
@@ -70,3 +70,11 @@ struct trie_value_entry_f {
le64_t key_off;
le64_t value_off;
} _packed_;
+
+/* v2 extends v1 with filename and line-number */
+struct trie_value_entry2_f {
+ le64_t key_off;
+ le64_t value_off;
+ le64_t filename_off;
+ le64_t line_number;
+} _packed_;
diff --git a/src/libsystemd/src/sd-hwdb/sd-hwdb.c b/src/libsystemd/src/sd-hwdb/sd-hwdb.c
index 0891719604..8303879455 100644
--- a/src/libsystemd/src/sd-hwdb/sd-hwdb.c
+++ b/src/libsystemd/src/sd-hwdb/sd-hwdb.c
@@ -97,15 +97,20 @@ static void linebuf_rem_char(struct linebuf *buf) {
linebuf_rem(buf, 1);
}
-static const struct trie_child_entry_f *trie_node_children(sd_hwdb *hwdb, const struct trie_node_f *node) {
- return (const struct trie_child_entry_f *)((const char *)node + le64toh(hwdb->head->node_size));
+static const struct trie_child_entry_f *trie_node_child(sd_hwdb *hwdb, const struct trie_node_f *node, size_t idx) {
+ const char *base = (const char *)node;
+
+ base += le64toh(hwdb->head->node_size);
+ base += idx * le64toh(hwdb->head->child_entry_size);
+ return (const struct trie_child_entry_f *)base;
}
-static const struct trie_value_entry_f *trie_node_values(sd_hwdb *hwdb, const struct trie_node_f *node) {
+static const struct trie_value_entry_f *trie_node_value(sd_hwdb *hwdb, const struct trie_node_f *node, size_t idx) {
const char *base = (const char *)node;
base += le64toh(hwdb->head->node_size);
base += node->children_count * le64toh(hwdb->head->child_entry_size);
+ base += idx * le64toh(hwdb->head->value_entry_size);
return (const struct trie_value_entry_f *)base;
}
@@ -129,19 +134,20 @@ static const struct trie_node_f *node_lookup_f(sd_hwdb *hwdb, const struct trie_
struct trie_child_entry_f search;
search.c = c;
- child = bsearch(&search, trie_node_children(hwdb, node), node->children_count,
+ child = bsearch(&search, (const char *)node + le64toh(hwdb->head->node_size), node->children_count,
le64toh(hwdb->head->child_entry_size), trie_children_cmp_f);
if (child)
return trie_node_from_off(hwdb, child->child_off);
return NULL;
}
-static int hwdb_add_property(sd_hwdb *hwdb, const char *key, const char *value) {
+static int hwdb_add_property(sd_hwdb *hwdb, const struct trie_value_entry_f *entry) {
+ const char *key;
int r;
assert(hwdb);
- assert(key);
- assert(value);
+
+ key = trie_string(hwdb, entry->key_off);
/*
* Silently ignore all properties which do not start with a
@@ -152,11 +158,25 @@ static int hwdb_add_property(sd_hwdb *hwdb, const char *key, const char *value)
key++;
+ if (le64toh(hwdb->head->value_entry_size) >= sizeof(struct trie_value_entry2_f)) {
+ const struct trie_value_entry2_f *old, *entry2;
+
+ entry2 = (const struct trie_value_entry2_f *)entry;
+ old = ordered_hashmap_get(hwdb->properties, key);
+ if (old) {
+ /* on duplicates, we order by filename and line-number */
+ r = strcmp(trie_string(hwdb, entry2->filename_off), trie_string(hwdb, old->filename_off));
+ if (r < 0 ||
+ (r == 0 && entry2->line_number < old->line_number))
+ return 0;
+ }
+ }
+
r = ordered_hashmap_ensure_allocated(&hwdb->properties, &string_hash_ops);
if (r < 0)
return r;
- r = ordered_hashmap_replace(hwdb->properties, key, (char*)value);
+ r = ordered_hashmap_replace(hwdb->properties, key, (void *)entry);
if (r < 0)
return r;
@@ -177,7 +197,7 @@ static int trie_fnmatch_f(sd_hwdb *hwdb, const struct trie_node_f *node, size_t
linebuf_add(buf, prefix + p, len);
for (i = 0; i < node->children_count; i++) {
- const struct trie_child_entry_f *child = &trie_node_children(hwdb, node)[i];
+ const struct trie_child_entry_f *child = trie_node_child(hwdb, node, i);
linebuf_add_char(buf, child->c);
err = trie_fnmatch_f(hwdb, trie_node_from_off(hwdb, child->child_off), 0, buf, search);
@@ -188,8 +208,7 @@ static int trie_fnmatch_f(sd_hwdb *hwdb, const struct trie_node_f *node, size_t
if (le64toh(node->values_count) && fnmatch(linebuf_get(buf), search, 0) == 0)
for (i = 0; i < le64toh(node->values_count); i++) {
- err = hwdb_add_property(hwdb, trie_string(hwdb, trie_node_values(hwdb, node)[i].key_off),
- trie_string(hwdb, trie_node_values(hwdb, node)[i].value_off));
+ err = hwdb_add_property(hwdb, trie_node_value(hwdb, node, i));
if (err < 0)
return err;
}
@@ -254,8 +273,7 @@ static int trie_search_f(sd_hwdb *hwdb, const char *search) {
size_t n;
for (n = 0; n < le64toh(node->values_count); n++) {
- err = hwdb_add_property(hwdb, trie_string(hwdb, trie_node_values(hwdb, node)[n].key_off),
- trie_string(hwdb, trie_node_values(hwdb, node)[n].value_off));
+ err = hwdb_add_property(hwdb, trie_node_value(hwdb, node, n));
if (err < 0)
return err;
}
@@ -410,7 +428,7 @@ static int properties_prepare(sd_hwdb *hwdb, const char *modalias) {
}
_public_ int sd_hwdb_get(sd_hwdb *hwdb, const char *modalias, const char *key, const char **_value) {
- const char *value;
+ const struct trie_value_entry_f *entry;
int r;
assert_return(hwdb, -EINVAL);
@@ -422,11 +440,11 @@ _public_ int sd_hwdb_get(sd_hwdb *hwdb, const char *modalias, const char *key, c
if (r < 0)
return r;
- value = ordered_hashmap_get(hwdb->properties, key);
- if (!value)
+ entry = ordered_hashmap_get(hwdb->properties, key);
+ if (!entry)
return -ENOENT;
- *_value = value;
+ *_value = trie_string(hwdb, entry->value_off);
return 0;
}
@@ -449,8 +467,8 @@ _public_ int sd_hwdb_seek(sd_hwdb *hwdb, const char *modalias) {
}
_public_ int sd_hwdb_enumerate(sd_hwdb *hwdb, const char **key, const char **value) {
+ const struct trie_value_entry_f *entry;
const void *k;
- void *v;
assert_return(hwdb, -EINVAL);
assert_return(key, -EINVAL);
@@ -459,12 +477,12 @@ _public_ int sd_hwdb_enumerate(sd_hwdb *hwdb, const char **key, const char **val
if (hwdb->properties_modified)
return -EAGAIN;
- ordered_hashmap_iterate(hwdb->properties, &hwdb->properties_iterator, &v, &k);
+ ordered_hashmap_iterate(hwdb->properties, &hwdb->properties_iterator, (void **)&entry, &k);
if (!k)
return 0;
*key = k;
- *value = v;
+ *value = trie_string(hwdb, entry->value_off);
return 1;
}
diff --git a/src/libsystemd/src/sd-id128/id128-util.c b/src/libsystemd/src/sd-id128/id128-util.c
index cd32543d0c..0314127684 100644
--- a/src/libsystemd/src/sd-id128/id128-util.c
+++ b/src/libsystemd/src/sd-id128/id128-util.c
@@ -193,3 +193,16 @@ int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync) {
return id128_write_fd(fd, f, id, do_sync);
}
+
+void id128_hash_func(const void *p, struct siphash *state) {
+ siphash24_compress(p, 16, state);
+}
+
+int id128_compare_func(const void *a, const void *b) {
+ return memcmp(a, b, 16);
+}
+
+const struct hash_ops id128_hash_ops = {
+ .hash = id128_hash_func,
+ .compare = id128_compare_func,
+};
diff --git a/src/libsystemd/src/sd-id128/id128-util.h b/src/libsystemd/src/sd-id128/id128-util.h
index 0c57d693e5..7ca482a727 100644
--- a/src/libsystemd/src/sd-id128/id128-util.h
+++ b/src/libsystemd/src/sd-id128/id128-util.h
@@ -23,6 +23,7 @@
#include <systemd/sd-id128.h>
+#include "systemd-basic/hash-funcs.h"
#include "systemd-basic/macro.h"
char *id128_to_uuid_string(sd_id128_t id, char s[37]);
@@ -44,3 +45,7 @@ int id128_read(const char *p, Id128Format f, sd_id128_t *ret);
int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync);
int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync);
+
+void id128_hash_func(const void *p, struct siphash *state);
+int id128_compare_func(const void *a, const void *b) _pure_;
+extern const struct hash_ops id128_hash_ops;
diff --git a/src/libsystemd/src/sd-id128/sd-id128.c b/src/libsystemd/src/sd-id128/sd-id128.c
index 9c036fb4cb..275949c651 100644
--- a/src/libsystemd/src/sd-id128/sd-id128.c
+++ b/src/libsystemd/src/sd-id128/sd-id128.c
@@ -130,6 +130,28 @@ _public_ int sd_id128_get_boot(sd_id128_t *ret) {
return 0;
}
+_public_ int sd_id128_get_invocation(sd_id128_t *ret) {
+ static thread_local sd_id128_t saved_invocation_id = {};
+ int r;
+
+ assert_return(ret, -EINVAL);
+
+ if (sd_id128_is_null(saved_invocation_id)) {
+ const char *e;
+
+ e = secure_getenv("INVOCATION_ID");
+ if (!e)
+ return -ENXIO;
+
+ r = sd_id128_from_string(e, &saved_invocation_id);
+ if (r < 0)
+ return r;
+ }
+
+ *ret = saved_invocation_id;
+ return 0;
+}
+
static sd_id128_t make_v4_uuid(sd_id128_t id) {
/* Stolen from generate_random_uuid() of drivers/char/random.c
* in the kernel sources */
diff --git a/src/libsystemd/src/sd-journal/journal-file.c b/src/libsystemd/src/sd-journal/journal-file.c
index 7910270925..10972869c8 100644
--- a/src/libsystemd/src/sd-journal/journal-file.c
+++ b/src/libsystemd/src/sd-journal/journal-file.c
@@ -336,8 +336,13 @@ JournalFile* journal_file_close(JournalFile *f) {
#ifdef HAVE_GCRYPT
/* Write the final tag */
- if (f->seal && f->writable)
- journal_file_append_tag(f);
+ if (f->seal && f->writable) {
+ int r;
+
+ r = journal_file_append_tag(f);
+ if (r < 0)
+ log_error_errno(r, "Failed to append tag when closing journal: %m");
+ }
#endif
if (f->post_change_timer) {
@@ -392,8 +397,7 @@ JournalFile* journal_file_close(JournalFile *f) {
gcry_md_close(f->hmac);
#endif
- free(f);
- return NULL;
+ return mfree(f);
}
void journal_file_close_set(Set *s) {
@@ -566,8 +570,8 @@ static int journal_file_verify_header(JournalFile *f) {
return -ENODATA;
if (f->writable) {
- uint8_t state;
sd_id128_t machine_id;
+ uint8_t state;
int r;
r = sd_id128_get_machine(&machine_id);
@@ -588,6 +592,14 @@ static int journal_file_verify_header(JournalFile *f) {
log_debug("Journal file %s has unknown state %i.", f->path, state);
return -EBUSY;
}
+
+ /* Don't permit appending to files from the future. Because otherwise the realtime timestamps wouldn't
+ * be strictly ordered in the entries in the file anymore, and we can't have that since it breaks
+ * bisection. */
+ if (le64toh(f->header->tail_entry_realtime) > now(CLOCK_REALTIME)) {
+ log_debug("Journal file %s is from the future, refusing to append new data to it that'd be older.", f->path);
+ return -ETXTBSY;
+ }
}
f->compress_xz = JOURNAL_HEADER_COMPRESSED_XZ(f->header);
@@ -745,12 +757,16 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset
assert(ret);
/* Objects may only be located at multiple of 64 bit */
- if (!VALID64(offset))
+ if (!VALID64(offset)) {
+ log_debug("Attempt to move to object at non-64bit boundary: %" PRIu64, offset);
return -EBADMSG;
+ }
/* Object may not be located in the file header */
- if (offset < le64toh(f->header->header_size))
+ if (offset < le64toh(f->header->header_size)) {
+ log_debug("Attempt to move to object located in file header: %" PRIu64, offset);
return -EBADMSG;
+ }
r = journal_file_move_to(f, type, false, offset, sizeof(ObjectHeader), &t);
if (r < 0)
@@ -759,17 +775,29 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset
o = (Object*) t;
s = le64toh(o->object.size);
- if (s < sizeof(ObjectHeader))
+ if (s == 0) {
+ log_debug("Attempt to move to uninitialized object: %" PRIu64, offset);
return -EBADMSG;
+ }
+ if (s < sizeof(ObjectHeader)) {
+ log_debug("Attempt to move to overly short object: %" PRIu64, offset);
+ return -EBADMSG;
+ }
- if (o->object.type <= OBJECT_UNUSED)
+ if (o->object.type <= OBJECT_UNUSED) {
+ log_debug("Attempt to move to object with invalid type: %" PRIu64, offset);
return -EBADMSG;
+ }
- if (s < minimum_header_size(o))
+ if (s < minimum_header_size(o)) {
+ log_debug("Attempt to move to truncated object: %" PRIu64, offset);
return -EBADMSG;
+ }
- if (type > OBJECT_UNUSED && o->object.type != type)
+ if (type > OBJECT_UNUSED && o->object.type != type) {
+ log_debug("Attempt to move to object of unexpected type: %" PRIu64, offset);
return -EBADMSG;
+ }
if (s > sizeof(ObjectHeader)) {
r = journal_file_move_to(f, type, false, offset, s, &t);
@@ -1372,6 +1400,12 @@ static int journal_file_append_data(
if (r < 0)
return r;
+#ifdef HAVE_GCRYPT
+ r = journal_file_hmac_put_object(f, OBJECT_DATA, o, p);
+ if (r < 0)
+ return r;
+#endif
+
/* The linking might have altered the window, so let's
* refresh our pointer */
r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
@@ -1396,12 +1430,6 @@ static int journal_file_append_data(
fo->field.head_data_offset = le64toh(p);
}
-#ifdef HAVE_GCRYPT
- r = journal_file_hmac_put_object(f, OBJECT_DATA, o, p);
- if (r < 0)
- return r;
-#endif
-
if (ret)
*ret = o;
@@ -2470,6 +2498,37 @@ int journal_file_compare_locations(JournalFile *af, JournalFile *bf) {
return 0;
}
+static int bump_array_index(uint64_t *i, direction_t direction, uint64_t n) {
+
+ /* Increase or decrease the specified index, in the right direction. */
+
+ if (direction == DIRECTION_DOWN) {
+ if (*i >= n - 1)
+ return 0;
+
+ (*i) ++;
+ } else {
+ if (*i <= 0)
+ return 0;
+
+ (*i) --;
+ }
+
+ return 1;
+}
+
+static bool check_properly_ordered(uint64_t new_offset, uint64_t old_offset, direction_t direction) {
+
+ /* Consider it an error if any of the two offsets is uninitialized */
+ if (old_offset == 0 || new_offset == 0)
+ return false;
+
+ /* If we go down, the new offset must be larger than the old one. */
+ return direction == DIRECTION_DOWN ?
+ new_offset > old_offset :
+ new_offset < old_offset;
+}
+
int journal_file_next_entry(
JournalFile *f,
uint64_t p,
@@ -2500,36 +2559,34 @@ int journal_file_next_entry(
if (r <= 0)
return r;
- if (direction == DIRECTION_DOWN) {
- if (i >= n - 1)
- return 0;
-
- i++;
- } else {
- if (i <= 0)
- return 0;
-
- i--;
- }
+ r = bump_array_index(&i, direction, n);
+ if (r <= 0)
+ return r;
}
/* And jump to it */
- r = generic_array_get(f,
- le64toh(f->header->entry_array_offset),
- i,
- ret, &ofs);
- if (r == -EBADMSG && direction == DIRECTION_DOWN) {
- /* Special case: when we iterate throught the journal file linearly, and hit an entry we can't read,
- * consider this the end of the journal file. */
- log_debug_errno(r, "Encountered entry we can't read while iterating through journal file. Considering this the end of the file.");
- return 0;
+ for (;;) {
+ r = generic_array_get(f,
+ le64toh(f->header->entry_array_offset),
+ i,
+ ret, &ofs);
+ if (r > 0)
+ break;
+ if (r != -EBADMSG)
+ return r;
+
+ /* OK, so this entry is borked. Most likely some entry didn't get synced to disk properly, let's see if
+ * the next one might work for us instead. */
+ log_debug_errno(r, "Entry item %" PRIu64 " is bad, skipping over it.", i);
+
+ r = bump_array_index(&i, direction, n);
+ if (r <= 0)
+ return r;
}
- if (r <= 0)
- return r;
- if (p > 0 &&
- (direction == DIRECTION_DOWN ? ofs <= p : ofs >= p)) {
- log_debug("%s: entry array corrupted at entry %" PRIu64, f->path, i);
+ /* Ensure our array is properly ordered. */
+ if (p > 0 && !check_properly_ordered(ofs, p, direction)) {
+ log_debug("%s: entry array not properly ordered at entry %" PRIu64, f->path, i);
return -EBADMSG;
}
@@ -2546,9 +2603,9 @@ int journal_file_next_entry_for_data(
direction_t direction,
Object **ret, uint64_t *offset) {
- uint64_t n, i;
- int r;
+ uint64_t i, n, ofs;
Object *d;
+ int r;
assert(f);
assert(p > 0 || !o);
@@ -2580,25 +2637,39 @@ int journal_file_next_entry_for_data(
if (r <= 0)
return r;
- if (direction == DIRECTION_DOWN) {
- if (i >= n - 1)
- return 0;
+ r = bump_array_index(&i, direction, n);
+ if (r <= 0)
+ return r;
+ }
- i++;
- } else {
- if (i <= 0)
- return 0;
+ for (;;) {
+ r = generic_array_get_plus_one(f,
+ le64toh(d->data.entry_offset),
+ le64toh(d->data.entry_array_offset),
+ i,
+ ret, &ofs);
+ if (r > 0)
+ break;
+ if (r != -EBADMSG)
+ return r;
- i--;
- }
+ log_debug_errno(r, "Data entry item %" PRIu64 " is bad, skipping over it.", i);
+
+ r = bump_array_index(&i, direction, n);
+ if (r <= 0)
+ return r;
+ }
+ /* Ensure our array is properly ordered. */
+ if (p > 0 && check_properly_ordered(ofs, p, direction)) {
+ log_debug("%s data entry array not properly ordered at entry %" PRIu64, f->path, i);
+ return -EBADMSG;
}
- return generic_array_get_plus_one(f,
- le64toh(d->data.entry_offset),
- le64toh(d->data.entry_array_offset),
- i,
- ret, offset);
+ if (offset)
+ *offset = ofs;
+
+ return 1;
}
int journal_file_move_to_entry_by_offset_for_data(
@@ -3269,7 +3340,8 @@ int journal_file_open_reliably(
-EBUSY, /* unclean shutdown */
-ESHUTDOWN, /* already archived */
-EIO, /* IO error, including SIGBUS on mmap */
- -EIDRM /* File has been deleted */))
+ -EIDRM, /* File has been deleted */
+ -ETXTBSY)) /* File is from the future */
return r;
if ((flags & O_ACCMODE) == O_RDONLY)
diff --git a/src/libsystemd/src/sd-journal/journal-vacuum.c b/src/libsystemd/src/sd-journal/journal-vacuum.c
index 4bbe3ee800..e5d49f0b5d 100644
--- a/src/libsystemd/src/sd-journal/journal-vacuum.c
+++ b/src/libsystemd/src/sd-journal/journal-vacuum.c
@@ -344,7 +344,7 @@ finish:
free(list[i].filename);
free(list);
- log_full(verbose ? LOG_INFO : LOG_DEBUG, "Vacuuming done, freed %s of archived journals on disk.", format_bytes(sbytes, sizeof(sbytes), freed));
+ log_full(verbose ? LOG_INFO : LOG_DEBUG, "Vacuuming done, freed %s of archived journals from %s.", format_bytes(sbytes, sizeof(sbytes), freed), directory);
return r;
}
diff --git a/src/libsystemd/src/sd-journal/journal-verify.c b/src/libsystemd/src/sd-journal/journal-verify.c
index de75cc94ef..756dbdaa76 100644
--- a/src/libsystemd/src/sd-journal/journal-verify.c
+++ b/src/libsystemd/src/sd-journal/journal-verify.c
@@ -119,6 +119,11 @@ static void flush_progress(void) {
log_error(OFSfmt": " _fmt, (uint64_t)_offset, ##__VA_ARGS__); \
} while (0)
+#define error_errno(_offset, error, _fmt, ...) do { \
+ flush_progress(); \
+ log_error_errno(error, OFSfmt": " _fmt, (uint64_t)_offset, ##__VA_ARGS__); \
+ } while (0)
+
static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o) {
uint64_t i;
@@ -169,8 +174,8 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
le64toh(o->object.size) - offsetof(Object, data.payload),
&b, &alloc, &b_size, 0);
if (r < 0) {
- error(offset, "%s decompression failed: %s",
- object_compressed_to_string(compression), strerror(-r));
+ error_errno(offset, r, "%s decompression failed: %m",
+ object_compressed_to_string(compression));
return r;
}
@@ -827,7 +832,7 @@ int journal_file_verify(
int data_fd = -1, entry_fd = -1, entry_array_fd = -1;
unsigned i;
bool found_last = false;
- _cleanup_free_ char *tmp_dir = NULL;
+ const char *tmp_dir = NULL;
#ifdef HAVE_GCRYPT
uint64_t last_tag = 0;
@@ -847,7 +852,7 @@ int journal_file_verify(
} else if (f->seal)
return -ENOKEY;
- r = var_tmp(&tmp_dir);
+ r = var_tmp_dir(&tmp_dir);
if (r < 0) {
log_error_errno(r, "Failed to determine temporary directory: %m");
goto fail;
@@ -913,7 +918,7 @@ int journal_file_verify(
r = journal_file_object_verify(f, p, o);
if (r < 0) {
- error(p, "Invalid object contents: %s", strerror(-r));
+ error_errno(p, r, "Invalid object contents: %m");
goto fail;
}
diff --git a/src/libsystemd/src/sd-journal/lookup3.c b/src/libsystemd/src/sd-journal/lookup3.c
index 3d791234f4..d8f1a4977d 100644
--- a/src/libsystemd/src/sd-journal/lookup3.c
+++ b/src/libsystemd/src/sd-journal/lookup3.c
@@ -317,7 +317,7 @@ uint32_t jenkins_hashlittle( const void *key, size_t length, uint32_t initval)
* still catch it and complain. The masking trick does make the hash
* noticeably faster for short strings (like English words).
*/
-#ifndef VALGRIND
+#if !defined(VALGRIND) && !defined(__SANITIZE_ADDRESS__)
switch(length)
{
@@ -503,7 +503,7 @@ void jenkins_hashlittle2(
* still catch it and complain. The masking trick does make the hash
* noticeably faster for short strings (like English words).
*/
-#ifndef VALGRIND
+#if !defined(VALGRIND) && !defined(__SANITIZE_ADDRESS__)
switch(length)
{
@@ -681,7 +681,7 @@ uint32_t jenkins_hashbig( const void *key, size_t length, uint32_t initval)
* still catch it and complain. The masking trick does make the hash
* noticeably faster for short strings (like English words).
*/
-#ifndef VALGRIND
+#if !defined(VALGRIND) && !defined(__SANITIZE_ADDRESS__)
switch(length)
{
diff --git a/src/libsystemd/src/sd-journal/mmap-cache.c b/src/libsystemd/src/sd-journal/mmap-cache.c
index 2fdb445f3f..3570aa1d44 100644
--- a/src/libsystemd/src/sd-journal/mmap-cache.c
+++ b/src/libsystemd/src/sd-journal/mmap-cache.c
@@ -326,10 +326,8 @@ static FileDescriptor* fd_add(MMapCache *m, int fd) {
f->fd = fd;
r = hashmap_put(m->fds, FD_TO_PTR(fd), f);
- if (r < 0) {
- free(f);
- return NULL;
- }
+ if (r < 0)
+ return mfree(f);
return f;
}
diff --git a/src/libsystemd/src/sd-journal/sd-journal.c b/src/libsystemd/src/sd-journal/sd-journal.c
index 58307e1626..68ef58b79b 100644
--- a/src/libsystemd/src/sd-journal/sd-journal.c
+++ b/src/libsystemd/src/sd-journal/sd-journal.c
@@ -389,7 +389,7 @@ _public_ int sd_journal_add_disjunction(sd_journal *j) {
}
static char *match_make_string(Match *m) {
- char *p, *r;
+ char *p = NULL, *r;
Match *i;
bool enclose = false;
@@ -399,15 +399,12 @@ static char *match_make_string(Match *m) {
if (m->type == MATCH_DISCRETE)
return strndup(m->data, m->size);
- p = NULL;
LIST_FOREACH(matches, i, m->matches) {
char *t, *k;
t = match_make_string(i);
- if (!t) {
- free(p);
- return NULL;
- }
+ if (!t)
+ return mfree(p);
if (p) {
k = strjoin(p, m->type == MATCH_OR_TERM ? " OR " : " AND ", t, NULL);
@@ -1721,9 +1718,16 @@ static sd_journal *journal_new(int flags, const char *path) {
j->data_threshold = DEFAULT_DATA_THRESHOLD;
if (path) {
- j->path = strdup(path);
- if (!j->path)
+ char *t;
+
+ t = strdup(path);
+ if (!t)
goto fail;
+
+ if (flags & SD_JOURNAL_OS_ROOT)
+ j->prefix = t;
+ else
+ j->path = t;
}
j->files = ordered_hashmap_new(&string_hash_ops);
@@ -1739,12 +1743,17 @@ fail:
return NULL;
}
+#define OPEN_ALLOWED_FLAGS \
+ (SD_JOURNAL_LOCAL_ONLY | \
+ SD_JOURNAL_RUNTIME_ONLY | \
+ SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER)
+
_public_ int sd_journal_open(sd_journal **ret, int flags) {
sd_journal *j;
int r;
assert_return(ret, -EINVAL);
- assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_RUNTIME_ONLY|SD_JOURNAL_SYSTEM|SD_JOURNAL_CURRENT_USER)) == 0, -EINVAL);
+ assert_return((flags & ~OPEN_ALLOWED_FLAGS) == 0, -EINVAL);
j = journal_new(flags, NULL);
if (!j)
@@ -1763,6 +1772,9 @@ fail:
return r;
}
+#define OPEN_CONTAINER_ALLOWED_FLAGS \
+ (SD_JOURNAL_LOCAL_ONLY | SD_JOURNAL_SYSTEM)
+
_public_ int sd_journal_open_container(sd_journal **ret, const char *machine, int flags) {
_cleanup_free_ char *root = NULL, *class = NULL;
sd_journal *j;
@@ -1774,7 +1786,7 @@ _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, in
assert_return(machine, -EINVAL);
assert_return(ret, -EINVAL);
- assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM)) == 0, -EINVAL);
+ assert_return((flags & ~OPEN_CONTAINER_ALLOWED_FLAGS) == 0, -EINVAL);
assert_return(machine_name_is_valid(machine), -EINVAL);
p = strjoina("/run/systemd/machines/", machine);
@@ -1789,13 +1801,10 @@ _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, in
if (!streq_ptr(class, "container"))
return -EIO;
- j = journal_new(flags, NULL);
+ j = journal_new(flags, root);
if (!j)
return -ENOMEM;
- j->prefix = root;
- root = NULL;
-
r = add_search_paths(j);
if (r < 0)
goto fail;
@@ -1808,13 +1817,17 @@ fail:
return r;
}
+#define OPEN_DIRECTORY_ALLOWED_FLAGS \
+ (SD_JOURNAL_OS_ROOT | \
+ SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER )
+
_public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) {
sd_journal *j;
int r;
assert_return(ret, -EINVAL);
assert_return(path, -EINVAL);
- assert_return((flags & ~SD_JOURNAL_OS_ROOT) == 0, -EINVAL);
+ assert_return((flags & ~OPEN_DIRECTORY_ALLOWED_FLAGS) == 0, -EINVAL);
j = journal_new(flags, path);
if (!j)
@@ -1863,6 +1876,10 @@ fail:
return r;
}
+#define OPEN_DIRECTORY_FD_ALLOWED_FLAGS \
+ (SD_JOURNAL_OS_ROOT | \
+ SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER )
+
_public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
sd_journal *j;
struct stat st;
@@ -1870,7 +1887,7 @@ _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
assert_return(ret, -EINVAL);
assert_return(fd >= 0, -EBADF);
- assert_return((flags & ~SD_JOURNAL_OS_ROOT) == 0, -EINVAL);
+ assert_return((flags & ~OPEN_DIRECTORY_FD_ALLOWED_FLAGS) == 0, -EINVAL);
if (fstat(fd, &st) < 0)
return -errno;
@@ -2292,6 +2309,8 @@ _public_ int sd_journal_get_fd(sd_journal *j) {
* inotify */
if (j->no_new_files)
r = add_current_paths(j);
+ else if (j->flags & SD_JOURNAL_OS_ROOT)
+ r = add_search_paths(j);
else if (j->toplevel_fd >= 0)
r = add_root_directory(j, NULL, false);
else if (j->path)
diff --git a/src/libsystemd/src/sd-netlink/netlink-types.c b/src/libsystemd/src/sd-netlink/netlink-types.c
index c3f3789fe5..fb881846a5 100644
--- a/src/libsystemd/src/sd-netlink/netlink-types.c
+++ b/src/libsystemd/src/sd-netlink/netlink-types.c
@@ -22,6 +22,7 @@
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
+#include <linux/can/netlink.h>
#include <linux/in6.h>
#include <linux/veth.h>
#include <linux/if_bridge.h>
@@ -305,49 +306,48 @@ static const char* const nl_union_link_info_data_table[] = {
[NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = "vti6",
[NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = "ip6tnl",
[NL_UNION_LINK_INFO_DATA_VRF] = "vrf",
+ [NL_UNION_LINK_INFO_DATA_VCAN] = "vcan",
};
DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData);
static const NLTypeSystem rtnl_link_info_data_type_systems[] = {
- [NL_UNION_LINK_INFO_DATA_BOND] = { .count = ELEMENTSOF(rtnl_link_info_data_bond_types),
- .types = rtnl_link_info_data_bond_types },
- [NL_UNION_LINK_INFO_DATA_BRIDGE] = { .count = ELEMENTSOF(rtnl_link_info_data_bridge_types),
- .types = rtnl_link_info_data_bridge_types },
- [NL_UNION_LINK_INFO_DATA_VLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vlan_types),
- .types = rtnl_link_info_data_vlan_types },
- [NL_UNION_LINK_INFO_DATA_VETH] = { .count = ELEMENTSOF(rtnl_link_info_data_veth_types),
- .types = rtnl_link_info_data_veth_types },
- [NL_UNION_LINK_INFO_DATA_MACVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types),
- .types = rtnl_link_info_data_macvlan_types },
- [NL_UNION_LINK_INFO_DATA_MACVTAP] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types),
- .types = rtnl_link_info_data_macvlan_types },
- [NL_UNION_LINK_INFO_DATA_IPVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types),
- .types = rtnl_link_info_data_ipvlan_types },
- [NL_UNION_LINK_INFO_DATA_VXLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vxlan_types),
- .types = rtnl_link_info_data_vxlan_types },
- [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types),
- .types = rtnl_link_info_data_iptun_types },
- [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
- .types = rtnl_link_info_data_ipgre_types },
+ [NL_UNION_LINK_INFO_DATA_BOND] = { .count = ELEMENTSOF(rtnl_link_info_data_bond_types),
+ .types = rtnl_link_info_data_bond_types },
+ [NL_UNION_LINK_INFO_DATA_BRIDGE] = { .count = ELEMENTSOF(rtnl_link_info_data_bridge_types),
+ .types = rtnl_link_info_data_bridge_types },
+ [NL_UNION_LINK_INFO_DATA_VLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vlan_types),
+ .types = rtnl_link_info_data_vlan_types },
+ [NL_UNION_LINK_INFO_DATA_VETH] = { .count = ELEMENTSOF(rtnl_link_info_data_veth_types),
+ .types = rtnl_link_info_data_veth_types },
+ [NL_UNION_LINK_INFO_DATA_MACVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types),
+ .types = rtnl_link_info_data_macvlan_types },
+ [NL_UNION_LINK_INFO_DATA_MACVTAP] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types),
+ .types = rtnl_link_info_data_macvlan_types },
+ [NL_UNION_LINK_INFO_DATA_IPVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types),
+ .types = rtnl_link_info_data_ipvlan_types },
+ [NL_UNION_LINK_INFO_DATA_VXLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vxlan_types),
+ .types = rtnl_link_info_data_vxlan_types },
+ [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types),
+ .types = rtnl_link_info_data_iptun_types },
+ [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
+ .types = rtnl_link_info_data_ipgre_types },
[NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
- .types = rtnl_link_info_data_ipgre_types },
- [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
- .types = rtnl_link_info_data_ipgre_types },
- [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
- .types = rtnl_link_info_data_ipgre_types },
- [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types),
- .types = rtnl_link_info_data_iptun_types },
- [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types),
- .types = rtnl_link_info_data_ipvti_types },
- [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types),
- .types = rtnl_link_info_data_ipvti_types },
- [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types),
- .types = rtnl_link_info_data_ip6tnl_types },
-
- [NL_UNION_LINK_INFO_DATA_VRF] = { .count = ELEMENTSOF(rtnl_link_info_data_vrf_types),
- .types = rtnl_link_info_data_vrf_types },
-
+ .types = rtnl_link_info_data_ipgre_types },
+ [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
+ .types = rtnl_link_info_data_ipgre_types },
+ [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
+ .types = rtnl_link_info_data_ipgre_types },
+ [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types),
+ .types = rtnl_link_info_data_iptun_types },
+ [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types),
+ .types = rtnl_link_info_data_ipvti_types },
+ [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types),
+ .types = rtnl_link_info_data_ipvti_types },
+ [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types),
+ .types = rtnl_link_info_data_ip6tnl_types },
+ [NL_UNION_LINK_INFO_DATA_VRF] = { .count = ELEMENTSOF(rtnl_link_info_data_vrf_types),
+ .types = rtnl_link_info_data_vrf_types },
};
static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = {
diff --git a/src/libsystemd/src/sd-netlink/netlink-types.h b/src/libsystemd/src/sd-netlink/netlink-types.h
index 3cd57715c3..df4ddcaf92 100644
--- a/src/libsystemd/src/sd-netlink/netlink-types.h
+++ b/src/libsystemd/src/sd-netlink/netlink-types.h
@@ -87,6 +87,7 @@ typedef enum NLUnionLinkInfoData {
NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL,
NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL,
NL_UNION_LINK_INFO_DATA_VRF,
+ NL_UNION_LINK_INFO_DATA_VCAN,
_NL_UNION_LINK_INFO_DATA_MAX,
_NL_UNION_LINK_INFO_DATA_INVALID = -1
} NLUnionLinkInfoData;
diff --git a/src/libsystemd/src/test.mk b/src/libsystemd/src/test.mk
index 1a5917121e..a4d107ba6b 100644
--- a/src/libsystemd/src/test.mk
+++ b/src/libsystemd/src/test.mk
@@ -54,6 +54,15 @@ test_bus_cleanup_CFLAGS = \
test_bus_cleanup_LDADD = \
libsystemd-shared.la
+test_bus_track_SOURCES = \
+ src/libsystemd/sd-bus/test-bus-track.c
+
+test_bus_track_CFLAGS = \
+ $(SECCOMP_CFLAGS)
+
+test_bus_track_LDADD = \
+ libsystemd-shared.la
+
test_bus_server_SOURCES = \
src/libsystemd/sd-bus/test-bus-server.c