xref: /illumos-gate/usr/src/cmd/bhyve/common/iov.c (revision 5c4a5fe16715fb423db76577a6883b5bbecdbe45)
1*5c4a5fe1SAndy Fiddaman /*-
2*5c4a5fe1SAndy Fiddaman  * SPDX-License-Identifier: BSD-2-Clause
3*5c4a5fe1SAndy Fiddaman  *
4*5c4a5fe1SAndy Fiddaman  * Copyright (c) 2016 Jakub Klama <jceel@FreeBSD.org>.
5*5c4a5fe1SAndy Fiddaman  * Copyright (c) 2018 Alexander Motin <mav@FreeBSD.org>
6*5c4a5fe1SAndy Fiddaman  * All rights reserved.
7*5c4a5fe1SAndy Fiddaman  *
8*5c4a5fe1SAndy Fiddaman  * Redistribution and use in source and binary forms, with or without
9*5c4a5fe1SAndy Fiddaman  * modification, are permitted provided that the following conditions
10*5c4a5fe1SAndy Fiddaman  * are met:
11*5c4a5fe1SAndy Fiddaman  * 1. Redistributions of source code must retain the above copyright
12*5c4a5fe1SAndy Fiddaman  *    notice, this list of conditions and the following disclaimer
13*5c4a5fe1SAndy Fiddaman  *    in this position and unchanged.
14*5c4a5fe1SAndy Fiddaman  * 2. Redistributions in binary form must reproduce the above copyright
15*5c4a5fe1SAndy Fiddaman  *    notice, this list of conditions and the following disclaimer in the
16*5c4a5fe1SAndy Fiddaman  *    documentation and/or other materials provided with the distribution.
17*5c4a5fe1SAndy Fiddaman  *
18*5c4a5fe1SAndy Fiddaman  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19*5c4a5fe1SAndy Fiddaman  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*5c4a5fe1SAndy Fiddaman  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*5c4a5fe1SAndy Fiddaman  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22*5c4a5fe1SAndy Fiddaman  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23*5c4a5fe1SAndy Fiddaman  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24*5c4a5fe1SAndy Fiddaman  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25*5c4a5fe1SAndy Fiddaman  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26*5c4a5fe1SAndy Fiddaman  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27*5c4a5fe1SAndy Fiddaman  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28*5c4a5fe1SAndy Fiddaman  * SUCH DAMAGE.
29*5c4a5fe1SAndy Fiddaman  */
30*5c4a5fe1SAndy Fiddaman 
31*5c4a5fe1SAndy Fiddaman 
32*5c4a5fe1SAndy Fiddaman #include <sys/param.h>
33*5c4a5fe1SAndy Fiddaman #include <sys/types.h>
34*5c4a5fe1SAndy Fiddaman #include <sys/uio.h>
35*5c4a5fe1SAndy Fiddaman 
36*5c4a5fe1SAndy Fiddaman #include <stdlib.h>
37*5c4a5fe1SAndy Fiddaman #include <string.h>
38*5c4a5fe1SAndy Fiddaman #include "iov.h"
39*5c4a5fe1SAndy Fiddaman 
40*5c4a5fe1SAndy Fiddaman void
seek_iov(const struct iovec * iov1,int niov1,struct iovec * iov2,int * niov2,size_t seek)41*5c4a5fe1SAndy Fiddaman seek_iov(const struct iovec *iov1, int niov1, struct iovec *iov2, int *niov2,
42*5c4a5fe1SAndy Fiddaman     size_t seek)
43*5c4a5fe1SAndy Fiddaman {
44*5c4a5fe1SAndy Fiddaman 	size_t remainder = 0;
45*5c4a5fe1SAndy Fiddaman 	size_t left = seek;
46*5c4a5fe1SAndy Fiddaman 	int i, j;
47*5c4a5fe1SAndy Fiddaman 
48*5c4a5fe1SAndy Fiddaman 	for (i = 0; i < niov1; i++) {
49*5c4a5fe1SAndy Fiddaman 		size_t toseek = MIN(left, iov1[i].iov_len);
50*5c4a5fe1SAndy Fiddaman 		left -= toseek;
51*5c4a5fe1SAndy Fiddaman 
52*5c4a5fe1SAndy Fiddaman 		if (toseek == iov1[i].iov_len)
53*5c4a5fe1SAndy Fiddaman 			continue;
54*5c4a5fe1SAndy Fiddaman 
55*5c4a5fe1SAndy Fiddaman 		if (left == 0) {
56*5c4a5fe1SAndy Fiddaman 			remainder = toseek;
57*5c4a5fe1SAndy Fiddaman 			break;
58*5c4a5fe1SAndy Fiddaman 		}
59*5c4a5fe1SAndy Fiddaman 	}
60*5c4a5fe1SAndy Fiddaman 
61*5c4a5fe1SAndy Fiddaman 	for (j = i; j < niov1; j++) {
62*5c4a5fe1SAndy Fiddaman 		iov2[j - i].iov_base = (char *)iov1[j].iov_base + remainder;
63*5c4a5fe1SAndy Fiddaman 		iov2[j - i].iov_len = iov1[j].iov_len - remainder;
64*5c4a5fe1SAndy Fiddaman 		remainder = 0;
65*5c4a5fe1SAndy Fiddaman 	}
66*5c4a5fe1SAndy Fiddaman 
67*5c4a5fe1SAndy Fiddaman 	*niov2 = j - i;
68*5c4a5fe1SAndy Fiddaman }
69*5c4a5fe1SAndy Fiddaman 
70*5c4a5fe1SAndy Fiddaman size_t
count_iov(const struct iovec * iov,int niov)71*5c4a5fe1SAndy Fiddaman count_iov(const struct iovec *iov, int niov)
72*5c4a5fe1SAndy Fiddaman {
73*5c4a5fe1SAndy Fiddaman 	size_t total = 0;
74*5c4a5fe1SAndy Fiddaman 	int i;
75*5c4a5fe1SAndy Fiddaman 
76*5c4a5fe1SAndy Fiddaman 	for (i = 0; i < niov; i++)
77*5c4a5fe1SAndy Fiddaman 		total += iov[i].iov_len;
78*5c4a5fe1SAndy Fiddaman 
79*5c4a5fe1SAndy Fiddaman 	return (total);
80*5c4a5fe1SAndy Fiddaman }
81*5c4a5fe1SAndy Fiddaman 
82*5c4a5fe1SAndy Fiddaman void
truncate_iov(struct iovec * iov,int * niov,size_t length)83*5c4a5fe1SAndy Fiddaman truncate_iov(struct iovec *iov, int *niov, size_t length)
84*5c4a5fe1SAndy Fiddaman {
85*5c4a5fe1SAndy Fiddaman 	size_t done = 0;
86*5c4a5fe1SAndy Fiddaman 	int i;
87*5c4a5fe1SAndy Fiddaman 
88*5c4a5fe1SAndy Fiddaman 	for (i = 0; i < *niov; i++) {
89*5c4a5fe1SAndy Fiddaman 		size_t toseek = MIN(length - done, iov[i].iov_len);
90*5c4a5fe1SAndy Fiddaman 		done += toseek;
91*5c4a5fe1SAndy Fiddaman 
92*5c4a5fe1SAndy Fiddaman 		if (toseek <= iov[i].iov_len) {
93*5c4a5fe1SAndy Fiddaman 			iov[i].iov_len = toseek;
94*5c4a5fe1SAndy Fiddaman 			*niov = i + 1;
95*5c4a5fe1SAndy Fiddaman 			return;
96*5c4a5fe1SAndy Fiddaman 		}
97*5c4a5fe1SAndy Fiddaman 	}
98*5c4a5fe1SAndy Fiddaman }
99*5c4a5fe1SAndy Fiddaman 
100*5c4a5fe1SAndy Fiddaman ssize_t
iov_to_buf(const struct iovec * iov,int niov,void ** buf)101*5c4a5fe1SAndy Fiddaman iov_to_buf(const struct iovec *iov, int niov, void **buf)
102*5c4a5fe1SAndy Fiddaman {
103*5c4a5fe1SAndy Fiddaman 	size_t ptr, total;
104*5c4a5fe1SAndy Fiddaman 	int i;
105*5c4a5fe1SAndy Fiddaman 
106*5c4a5fe1SAndy Fiddaman 	total = count_iov(iov, niov);
107*5c4a5fe1SAndy Fiddaman 	*buf = realloc(*buf, total);
108*5c4a5fe1SAndy Fiddaman 	if (*buf == NULL)
109*5c4a5fe1SAndy Fiddaman 		return (-1);
110*5c4a5fe1SAndy Fiddaman 
111*5c4a5fe1SAndy Fiddaman 	for (i = 0, ptr = 0; i < niov; i++) {
112*5c4a5fe1SAndy Fiddaman 		memcpy((uint8_t *)*buf + ptr, iov[i].iov_base, iov[i].iov_len);
113*5c4a5fe1SAndy Fiddaman 		ptr += iov[i].iov_len;
114*5c4a5fe1SAndy Fiddaman 	}
115*5c4a5fe1SAndy Fiddaman 
116*5c4a5fe1SAndy Fiddaman 	return (total);
117*5c4a5fe1SAndy Fiddaman }
118*5c4a5fe1SAndy Fiddaman 
119*5c4a5fe1SAndy Fiddaman ssize_t
buf_to_iov(const void * buf,size_t buflen,const struct iovec * iov,int niov,size_t seek)120*5c4a5fe1SAndy Fiddaman buf_to_iov(const void *buf, size_t buflen, const struct iovec *iov, int niov,
121*5c4a5fe1SAndy Fiddaman     size_t seek)
122*5c4a5fe1SAndy Fiddaman {
123*5c4a5fe1SAndy Fiddaman 	struct iovec *diov;
124*5c4a5fe1SAndy Fiddaman 	size_t off = 0, len;
125*5c4a5fe1SAndy Fiddaman 	int  i;
126*5c4a5fe1SAndy Fiddaman 
127*5c4a5fe1SAndy Fiddaman #ifndef __FreeBSD__
128*5c4a5fe1SAndy Fiddaman 	diov = NULL;
129*5c4a5fe1SAndy Fiddaman #endif
130*5c4a5fe1SAndy Fiddaman 
131*5c4a5fe1SAndy Fiddaman 	if (seek > 0) {
132*5c4a5fe1SAndy Fiddaman 		int ndiov;
133*5c4a5fe1SAndy Fiddaman 
134*5c4a5fe1SAndy Fiddaman 		diov = malloc(sizeof(struct iovec) * niov);
135*5c4a5fe1SAndy Fiddaman 		seek_iov(iov, niov, diov, &ndiov, seek);
136*5c4a5fe1SAndy Fiddaman 		iov = diov;
137*5c4a5fe1SAndy Fiddaman 		niov = ndiov;
138*5c4a5fe1SAndy Fiddaman 	}
139*5c4a5fe1SAndy Fiddaman 
140*5c4a5fe1SAndy Fiddaman 	for (i = 0; i < niov && off < buflen; i++) {
141*5c4a5fe1SAndy Fiddaman 		len = MIN(iov[i].iov_len, buflen - off);
142*5c4a5fe1SAndy Fiddaman 		memcpy(iov[i].iov_base, (const uint8_t *)buf + off, len);
143*5c4a5fe1SAndy Fiddaman 		off += len;
144*5c4a5fe1SAndy Fiddaman 	}
145*5c4a5fe1SAndy Fiddaman 
146*5c4a5fe1SAndy Fiddaman 	if (seek > 0)
147*5c4a5fe1SAndy Fiddaman 		free(diov);
148*5c4a5fe1SAndy Fiddaman 
149*5c4a5fe1SAndy Fiddaman 	return ((ssize_t)off);
150*5c4a5fe1SAndy Fiddaman }
151*5c4a5fe1SAndy Fiddaman 
152