summaryrefslogtreecommitdiffstats
path: root/src/basic/iovec-wrapper.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2023-10-19 16:24:20 +0200
committerLennart Poettering <lennart@poettering.net>2023-10-20 10:43:50 +0200
commitea1f38146a3d3e2d2217e1430ab6874ea0281abe (patch)
tree5984a4d2399485b88a09195eb13f158d2d80c925 /src/basic/iovec-wrapper.c
parentiovec-util: make IOVEC_INCREMENT a regular function too (diff)
downloadsystemd-ea1f38146a3d3e2d2217e1430ab6874ea0281abe.tar.xz
systemd-ea1f38146a3d3e2d2217e1430ab6874ea0281abe.zip
io-util: split out iovw_xyz into iovec-wrapper.h
Let's split these APIs out, they are kinda their own thing.
Diffstat (limited to 'src/basic/iovec-wrapper.c')
-rw-r--r--src/basic/iovec-wrapper.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/src/basic/iovec-wrapper.c b/src/basic/iovec-wrapper.c
new file mode 100644
index 0000000000..b335acd108
--- /dev/null
+++ b/src/basic/iovec-wrapper.c
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "alloc-util.h"
+#include "iovec-util.h"
+#include "iovec-wrapper.h"
+#include "string-util.h"
+
+struct iovec_wrapper *iovw_new(void) {
+ return new0(struct iovec_wrapper, 1);
+}
+
+void iovw_free_contents(struct iovec_wrapper *iovw, bool free_vectors) {
+ assert(iovw);
+
+ if (free_vectors)
+ for (size_t i = 0; i < iovw->count; i++)
+ free(iovw->iovec[i].iov_base);
+
+ iovw->iovec = mfree(iovw->iovec);
+ iovw->count = 0;
+}
+
+struct iovec_wrapper *iovw_free_free(struct iovec_wrapper *iovw) {
+ if (!iovw)
+ return NULL;
+
+ iovw_free_contents(iovw, /* free_vectors= */ true);
+ return mfree(iovw);
+}
+
+struct iovec_wrapper *iovw_free(struct iovec_wrapper *iovw) {
+ if (!iovw)
+ return NULL;
+
+ iovw_free_contents(iovw, /* free_vectors= */ false);
+ return mfree(iovw);
+}
+
+int iovw_put(struct iovec_wrapper *iovw, void *data, size_t len) {
+ assert(iovw);
+
+ if (len == 0)
+ return 0;
+
+ assert(data);
+
+ if (iovw->count >= IOV_MAX)
+ return -E2BIG;
+
+ if (!GREEDY_REALLOC(iovw->iovec, iovw->count + 1))
+ return -ENOMEM;
+
+ iovw->iovec[iovw->count++] = IOVEC_MAKE(data, len);
+ return 0;
+}
+
+int iovw_put_string_field(struct iovec_wrapper *iovw, const char *field, const char *value) {
+ _cleanup_free_ char *x = NULL;
+ int r;
+
+ assert(iovw);
+
+ x = strjoin(field, value);
+ if (!x)
+ return -ENOMEM;
+
+ r = iovw_put(iovw, x, strlen(x));
+ if (r >= 0)
+ TAKE_PTR(x);
+
+ return r;
+}
+
+int iovw_put_string_field_free(struct iovec_wrapper *iovw, const char *field, char *value) {
+ _cleanup_free_ _unused_ char *free_ptr = value;
+
+ return iovw_put_string_field(iovw, field, value);
+}
+
+void iovw_rebase(struct iovec_wrapper *iovw, void *old, void *new) {
+ assert(iovw);
+
+ FOREACH_ARRAY(i, iovw->iovec, iovw->count) {
+ assert(i->iov_base >= old);
+ i->iov_base = (uint8_t*) i->iov_base - (uint8_t*) old + (uint8_t*) new;
+ }
+}
+
+size_t iovw_size(const struct iovec_wrapper *iovw) {
+ if (!iovw)
+ return 0;
+
+ return iovec_total_size(iovw->iovec, iovw->count);
+}
+
+int iovw_append(struct iovec_wrapper *target, const struct iovec_wrapper *source) {
+ size_t original_count;
+ int r;
+
+ assert(target);
+
+ /* This duplicates the source and merges it into the target. */
+
+ if (iovw_isempty(source))
+ return 0;
+
+ original_count = target->count;
+
+ FOREACH_ARRAY(iovec, source->iovec, source->count) {
+ void *dup;
+
+ dup = memdup(iovec->iov_base, iovec->iov_len);
+ if (!dup) {
+ r = -ENOMEM;
+ goto rollback;
+ }
+
+ r = iovw_consume(target, dup, iovec->iov_len);
+ if (r < 0)
+ goto rollback;
+ }
+
+ return 0;
+
+rollback:
+ for (size_t i = original_count; i < target->count; i++)
+ free(target->iovec[i].iov_base);
+
+ target->count = original_count;
+ return r;
+}