return r;
}
-int iovw_append(struct iovec_wrapper *iovw, const void *data, size_t len) {
+int iovw_extend(struct iovec_wrapper *iovw, const void *data, size_t len) {
if (len == 0)
return 0;
return iovw_consume(iovw, c, len);
}
+int iovw_extend_iov(struct iovec_wrapper *iovw, const struct iovec *iov) {
+ assert(iovw);
+
+ if (!iovec_is_set(iov))
+ return 0;
+
+ return iovw_extend(iovw, iov->iov_base, iov->iov_len);
+}
+
+int iovw_extend_iovw(struct iovec_wrapper *iovw, const struct iovec_wrapper *source) {
+ int r;
+
+ assert(iovw);
+
+ /* This duplicates the source and merges it into the iovw. */
+
+ if (iovw_isempty(source))
+ return 0;
+
+ /* iovw->iovec will be reallocated in the loop below, hence source cannot point to the same object. */
+ if (iovw == source)
+ return -EINVAL;
+
+ if (iovw->count > SIZE_MAX - source->count)
+ return -E2BIG;
+ if (iovw->count + source->count > IOV_MAX)
+ return -E2BIG;
+
+ size_t original_count = iovw->count;
+
+ FOREACH_ARRAY(iovec, source->iovec, source->count) {
+ r = iovw_extend_iov(iovw, iovec);
+ if (r < 0)
+ goto rollback;
+ }
+
+ return 0;
+
+rollback:
+ for (size_t i = original_count; i < iovw->count; i++)
+ iovec_done(iovw->iovec + i);
+
+ iovw->count = original_count;
+ return r;
+}
+
int iovw_put_string_field_full(struct iovec_wrapper *iovw, bool replace, const char *field, const char *value) {
_cleanup_free_ char *x = NULL;
int r;
return iovec_total_size(iovw->iovec, iovw->count);
}
-int iovw_append_iovw(struct iovec_wrapper *target, const struct iovec_wrapper *source) {
- int r;
-
- assert(target);
-
- /* This duplicates the source and merges it into the target. */
-
- if (iovw_isempty(source))
- return 0;
-
- size_t original_count = target->count;
-
- FOREACH_ARRAY(iovec, source->iovec, source->count) {
- r = iovw_append(target, iovec->iov_base, iovec->iov_len);
- if (r < 0)
- goto rollback;
- }
-
- return 0;
-
-rollback:
- for (size_t i = original_count; i < target->count; i++)
- iovec_done(target->iovec + i);
-
- target->count = original_count;
- return r;
-}
-
int iovw_concat(const struct iovec_wrapper *iovw, struct iovec *ret) {
assert(iovw);
assert(ret);
ASSERT_EQ(memcmp(iovw.iovec[2].iov_base, "q", 1), 0);
}
-TEST(iovw_append) {
+TEST(iovw_extend) {
_cleanup_(iovw_done_free) struct iovec_wrapper iovw = {};
- /* iovw_append copies the data; the wrapper owns the copies. */
+ /* Appending an empty/NULL source is a no-op */
+ ASSERT_OK_ZERO(iovw_extend(&iovw, NULL, 0));
+ ASSERT_OK_ZERO(iovw_extend(&iovw, "foo", 0));
+ ASSERT_EQ(iovw.count, 0U);
+
+ /* iovw_extend() copies the data; the wrapper owns the copies. */
char buf[4] = { 'o', 'n', 'e', '\0' };
- ASSERT_OK(iovw_append(&iovw, buf, 3));
+ ASSERT_OK(iovw_extend(&iovw, buf, 3));
ASSERT_EQ(iovw.count, 1U);
ASSERT_EQ(iovw.iovec[0].iov_len, 3U);
ASSERT_EQ(memcmp(iovw.iovec[0].iov_base, "one", 3), 0);
/* Insert with a NUL */
- ASSERT_OK(iovw_append(&iovw, buf, 4));
+ ASSERT_OK(iovw_extend(&iovw, buf, 4));
ASSERT_EQ(iovw.count, 2U);
ASSERT_EQ(iovw.iovec[1].iov_len, 4U);
ASSERT_EQ(memcmp(iovw.iovec[1].iov_base, "one\0", 4), 0);
ASSERT_EQ(memcmp(iovw.iovec[0].iov_base, "one", 3), 0);
}
+TEST(iovw_extend_iov) {
+ _cleanup_(iovw_done_free) struct iovec_wrapper iovw = {};
+
+ /* Appending an empty/NULL source is a no-op */
+ ASSERT_OK_ZERO(iovw_extend_iov(&iovw, NULL));
+ ASSERT_OK_ZERO(iovw_extend_iov(&iovw, &(struct iovec) {}));
+ ASSERT_EQ(iovw.count, 0U);
+
+ ASSERT_OK(iovw_extend_iov(&iovw, &IOVEC_MAKE_STRING("aaa")));
+ ASSERT_OK(iovw_extend_iov(&iovw, &IOVEC_MAKE_STRING("bbb")));
+ ASSERT_OK(iovw_extend_iov(&iovw, &IOVEC_MAKE_STRING("ccc")));
+ ASSERT_EQ(iovw.count, 3U);
+ ASSERT_EQ(iovec_memcmp(&iovw.iovec[0], &IOVEC_MAKE_STRING("aaa")), 0);
+ ASSERT_EQ(iovec_memcmp(&iovw.iovec[1], &IOVEC_MAKE_STRING("bbb")), 0);
+ ASSERT_EQ(iovec_memcmp(&iovw.iovec[2], &IOVEC_MAKE_STRING("ccc")), 0);
+}
+
+TEST(iovw_extend_iovw) {
+ _cleanup_(iovw_done_free) struct iovec_wrapper target = {};
+ _cleanup_(iovw_done) struct iovec_wrapper source = {};
+
+ /* Appending an empty/NULL source is a no-op */
+ ASSERT_OK_ZERO(iovw_extend_iovw(&target, NULL));
+ ASSERT_OK_ZERO(iovw_extend_iovw(&target, &source));
+ ASSERT_EQ(target.count, 0U);
+
+ ASSERT_OK(iovw_put(&source, (char*) "one", 3));
+ ASSERT_OK(iovw_put(&source, (char*) "twotwo", 6));
+ ASSERT_EQ(source.count, 2U);
+
+ /* Pre-seed target with one entry to check that append adds on top rather than replacing */
+ char *seed = strdup("zero");
+ ASSERT_NOT_NULL(seed);
+ ASSERT_OK(iovw_put(&target, seed, strlen(seed)));
+
+ ASSERT_OK(iovw_extend_iovw(&target, &source));
+ ASSERT_EQ(target.count, 3U);
+
+ /* Appended entries must be fresh copies, not aliases of the source entries */
+ ASSERT_TRUE(target.iovec[1].iov_base != source.iovec[0].iov_base);
+ ASSERT_TRUE(target.iovec[2].iov_base != source.iovec[1].iov_base);
+
+ ASSERT_EQ(target.iovec[1].iov_len, 3U);
+ ASSERT_EQ(memcmp(target.iovec[1].iov_base, "one", 3), 0);
+ ASSERT_EQ(target.iovec[2].iov_len, 6U);
+ ASSERT_EQ(memcmp(target.iovec[2].iov_base, "twotwo", 6), 0);
+
+ /* Source is unchanged */
+ ASSERT_EQ(source.count, 2U);
+
+ /* Cannot pass the same objects */
+ ASSERT_ERROR(iovw_extend_iovw(&target, &target), EINVAL);
+}
+
TEST(iovw_consume) {
_cleanup_(iovw_done_free) struct iovec_wrapper iovw = {};
ASSERT_EQ(iovw_size(&iovw), 12U);
}
-TEST(iovw_append_iovw) {
- _cleanup_(iovw_done_free) struct iovec_wrapper target = {};
- _cleanup_(iovw_done) struct iovec_wrapper source = {};
-
- /* Appending an empty/NULL source is a no-op */
- ASSERT_OK_ZERO(iovw_append_iovw(&target, NULL));
- ASSERT_OK_ZERO(iovw_append_iovw(&target, &source));
- ASSERT_EQ(target.count, 0U);
-
- ASSERT_OK(iovw_put(&source, (char*) "one", 3));
- ASSERT_OK(iovw_put(&source, (char*) "twotwo", 6));
- ASSERT_EQ(source.count, 2U);
-
- /* Pre-seed target with one entry to check that append adds on top rather than replacing */
- char *seed = strdup("zero");
- ASSERT_NOT_NULL(seed);
- ASSERT_OK(iovw_put(&target, seed, strlen(seed)));
-
- ASSERT_OK(iovw_append_iovw(&target, &source));
- ASSERT_EQ(target.count, 3U);
-
- /* Appended entries must be fresh copies, not aliases of the source entries */
- ASSERT_TRUE(target.iovec[1].iov_base != source.iovec[0].iov_base);
- ASSERT_TRUE(target.iovec[2].iov_base != source.iovec[1].iov_base);
-
- ASSERT_EQ(target.iovec[1].iov_len, 3U);
- ASSERT_EQ(memcmp(target.iovec[1].iov_base, "one", 3), 0);
- ASSERT_EQ(target.iovec[2].iov_len, 6U);
- ASSERT_EQ(memcmp(target.iovec[2].iov_base, "twotwo", 6), 0);
-
- /* Source is unchanged */
- ASSERT_EQ(source.count, 2U);
-}
-
TEST(iovw_concat) {
_cleanup_(iovw_done) struct iovec_wrapper iovw = {};