return r;
}
-char* iovw_to_cstring(const struct iovec_wrapper *iovw) {
- size_t size;
- char *p, *ans;
-
+int iovw_concat(const struct iovec_wrapper *iovw, struct iovec *ret) {
assert(iovw);
+ assert(ret);
- /* Squish a series of iovecs into a C string. Embedded NULs are not allowed.
- * The caller is expected to filter them out when populating the data. */
+ /* Squish a series of iovecs into a single iovec. */
- size = iovw_size(iovw);
- if (size == SIZE_MAX)
- return NULL; /* Prevent theoretical overflow */
- size ++;
+ size_t len = iovw_size(iovw);
+ if (len == SIZE_MAX)
+ return -E2BIG; /* Prevent theoretical overflow */
- p = ans = new(char, size);
- if (!ans)
- return NULL;
+ /* Always allocate one more byte to make the result usable as a NUL-terminated string. */
+ _cleanup_free_ uint8_t *buf = malloc(len + 1);
+ if (!buf)
+ return -ENOMEM;
+
+ uint8_t *p = buf;
+ FOREACH_ARRAY(i, iovw->iovec, iovw->count)
+ p = mempcpy(p, i->iov_base, i->iov_len);
- FOREACH_ARRAY(iovec, iovw->iovec, iovw->count) {
- assert(!memchr(iovec->iov_base, 0, iovec->iov_len));
+ *p = 0;
- p = mempcpy(p, iovec->iov_base, iovec->iov_len);
- }
+ *ret = IOVEC_MAKE(TAKE_PTR(buf), len);
+ return 0;
+}
+
+char* iovw_to_cstring(const struct iovec_wrapper *iovw) {
+ assert(iovw);
- *p = '\0';
+ /* Squish a series of iovecs into a C string. Embedded NULs are not allowed.
+ * The caller is expected to filter them out when populating the data. */
+
+ _cleanup_(iovec_done) struct iovec iov = {};
+ if (iovw_concat(iovw, &iov) < 0)
+ return NULL;
- return ans;
+ assert(!memchr(iov.iov_base, 0, iov.iov_len));
+ return TAKE_PTR(iov.iov_base);
}
void iovw_rebase(struct iovec_wrapper *iovw, void *old, void *new);
size_t iovw_size(const struct iovec_wrapper *iovw);
int iovw_append_iovw(struct iovec_wrapper *target, const struct iovec_wrapper *source);
+int iovw_concat(const struct iovec_wrapper *iovw, struct iovec *ret);
char* iovw_to_cstring(const struct iovec_wrapper *iovw);
ASSERT_EQ(source.count, 2U);
}
+TEST(iovw_concat) {
+ _cleanup_(iovw_done) struct iovec_wrapper iovw = {};
+
+ /* Empty wrapper -> empty string with 0 length */
+ _cleanup_(iovec_done) struct iovec iov = {};
+ ASSERT_OK(iovw_concat(&iovw, &iov));
+ ASSERT_FALSE(iovec_is_set(&iov));
+ ASSERT_STREQ(iov.iov_base, "");
+ iovec_done(&iov);
+
+ ASSERT_OK(iovw_put(&iovw, (char*) "foo", 3));
+ ASSERT_OK(iovw_put(&iovw, (char*) "\0", 1));
+ ASSERT_OK(iovw_put(&iovw, (char*) "bar", 4));
+
+ ASSERT_OK(iovw_concat(&iovw, &iov));
+ ASSERT_EQ(iovec_memcmp(&iov, &IOVEC_MAKE("foo\0bar\0", 8)), 0);
+}
+
TEST(iovw_to_cstring) {
_cleanup_(iovw_done) struct iovec_wrapper iovw = {};
_cleanup_free_ char *s;