/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2016 Jakub Klama <[email protected]>.4* Copyright (c) 2018 Alexander Motin <[email protected]>5* All rights reserved.6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted provided that the following conditions9* are met:10* 1. Redistributions of source code must retain the above copyright11* notice, this list of conditions and the following disclaimer12* in this position and unchanged.13* 2. Redistributions in binary form must reproduce the above copyright14* notice, this list of conditions and the following disclaimer in the15* documentation and/or other materials provided with the distribution.16*17* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND18* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE19* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE20* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE21* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL22* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS23* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)24* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT25* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY26* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF27* SUCH DAMAGE.28*/2930#include <sys/param.h>31#include <sys/types.h>32#include <sys/uio.h>3334#include <stdlib.h>35#include <string.h>36#include "iov.h"3738void39seek_iov(const struct iovec *iov1, int niov1, struct iovec *iov2, int *niov2,40size_t seek)41{42size_t remainder = 0;43size_t left = seek;44int i, j;4546for (i = 0; i < niov1; i++) {47size_t toseek = MIN(left, iov1[i].iov_len);48left -= toseek;4950if (toseek == iov1[i].iov_len)51continue;5253if (left == 0) {54remainder = toseek;55break;56}57}5859for (j = i; j < niov1; j++) {60iov2[j - i].iov_base = (char *)iov1[j].iov_base + remainder;61iov2[j - i].iov_len = iov1[j].iov_len - remainder;62remainder = 0;63}6465*niov2 = j - i;66}6768size_t69count_iov(const struct iovec *iov, int niov)70{71size_t total = 0;72int i;7374for (i = 0; i < niov; i++)75total += iov[i].iov_len;7677return (total);78}7980void81truncate_iov(struct iovec *iov, int *niov, size_t length)82{83size_t done = 0;84int i;8586for (i = 0; i < *niov; i++) {87size_t toseek = MIN(length - done, iov[i].iov_len);88done += toseek;8990if (toseek <= iov[i].iov_len) {91iov[i].iov_len = toseek;92*niov = i + 1;93return;94}95}96}9798ssize_t99iov_to_buf(const struct iovec *iov, int niov, void **buf)100{101size_t ptr, total;102int i;103104total = count_iov(iov, niov);105*buf = realloc(*buf, total);106if (*buf == NULL)107return (-1);108109for (i = 0, ptr = 0; i < niov; i++) {110memcpy((uint8_t *)*buf + ptr, iov[i].iov_base, iov[i].iov_len);111ptr += iov[i].iov_len;112}113114return (total);115}116117ssize_t118buf_to_iov(const void *buf, size_t buflen, const struct iovec *iov, int niov,119size_t seek)120{121struct iovec *diov;122size_t off = 0, len;123int i;124125if (seek > 0) {126int ndiov;127128diov = malloc(sizeof(struct iovec) * niov);129seek_iov(iov, niov, diov, &ndiov, seek);130iov = diov;131niov = ndiov;132}133134for (i = 0; i < niov && off < buflen; i++) {135len = MIN(iov[i].iov_len, buflen - off);136memcpy(iov[i].iov_base, (const uint8_t *)buf + off, len);137off += len;138}139140if (seek > 0)141free(diov);142143return ((ssize_t)off);144}145146147148