Statistics
| Branch: | Revision:

root / cutils.c @ e3e87df4

History | View | Annotate | Download (10.8 kB)

1 18607dcb bellard
/*
2 18607dcb bellard
 * Simple C functions to supplement the C library
3 5fafdf24 ths
 *
4 18607dcb bellard
 * Copyright (c) 2006 Fabrice Bellard
5 18607dcb bellard
 *
6 18607dcb bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 18607dcb bellard
 * of this software and associated documentation files (the "Software"), to deal
8 18607dcb bellard
 * in the Software without restriction, including without limitation the rights
9 18607dcb bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 18607dcb bellard
 * copies of the Software, and to permit persons to whom the Software is
11 18607dcb bellard
 * furnished to do so, subject to the following conditions:
12 18607dcb bellard
 *
13 18607dcb bellard
 * The above copyright notice and this permission notice shall be included in
14 18607dcb bellard
 * all copies or substantial portions of the Software.
15 18607dcb bellard
 *
16 18607dcb bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 18607dcb bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 18607dcb bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 18607dcb bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 18607dcb bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 18607dcb bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 18607dcb bellard
 * THE SOFTWARE.
23 18607dcb bellard
 */
24 faf07963 pbrook
#include "qemu-common.h"
25 8d371d4b aliguori
#include "host-utils.h"
26 9f9b17a4 Jes Sorensen
#include <math.h>
27 18607dcb bellard
28 8c5135f9 Paolo Bonzini
#include "qemu_socket.h"
29 3d9b4925 Michael Tokarev
#include "iov.h"
30 8c5135f9 Paolo Bonzini
31 18607dcb bellard
void pstrcpy(char *buf, int buf_size, const char *str)
32 18607dcb bellard
{
33 18607dcb bellard
    int c;
34 18607dcb bellard
    char *q = buf;
35 18607dcb bellard
36 18607dcb bellard
    if (buf_size <= 0)
37 18607dcb bellard
        return;
38 18607dcb bellard
39 18607dcb bellard
    for(;;) {
40 18607dcb bellard
        c = *str++;
41 18607dcb bellard
        if (c == 0 || q >= buf + buf_size - 1)
42 18607dcb bellard
            break;
43 18607dcb bellard
        *q++ = c;
44 18607dcb bellard
    }
45 18607dcb bellard
    *q = '\0';
46 18607dcb bellard
}
47 18607dcb bellard
48 18607dcb bellard
/* strcat and truncate. */
49 18607dcb bellard
char *pstrcat(char *buf, int buf_size, const char *s)
50 18607dcb bellard
{
51 18607dcb bellard
    int len;
52 18607dcb bellard
    len = strlen(buf);
53 5fafdf24 ths
    if (len < buf_size)
54 18607dcb bellard
        pstrcpy(buf + len, buf_size - len, s);
55 18607dcb bellard
    return buf;
56 18607dcb bellard
}
57 18607dcb bellard
58 18607dcb bellard
int strstart(const char *str, const char *val, const char **ptr)
59 18607dcb bellard
{
60 18607dcb bellard
    const char *p, *q;
61 18607dcb bellard
    p = str;
62 18607dcb bellard
    q = val;
63 18607dcb bellard
    while (*q != '\0') {
64 18607dcb bellard
        if (*p != *q)
65 18607dcb bellard
            return 0;
66 18607dcb bellard
        p++;
67 18607dcb bellard
        q++;
68 18607dcb bellard
    }
69 18607dcb bellard
    if (ptr)
70 18607dcb bellard
        *ptr = p;
71 18607dcb bellard
    return 1;
72 18607dcb bellard
}
73 18607dcb bellard
74 18607dcb bellard
int stristart(const char *str, const char *val, const char **ptr)
75 18607dcb bellard
{
76 18607dcb bellard
    const char *p, *q;
77 18607dcb bellard
    p = str;
78 18607dcb bellard
    q = val;
79 18607dcb bellard
    while (*q != '\0') {
80 cd390083 blueswir1
        if (qemu_toupper(*p) != qemu_toupper(*q))
81 18607dcb bellard
            return 0;
82 18607dcb bellard
        p++;
83 18607dcb bellard
        q++;
84 18607dcb bellard
    }
85 18607dcb bellard
    if (ptr)
86 18607dcb bellard
        *ptr = p;
87 18607dcb bellard
    return 1;
88 18607dcb bellard
}
89 3c6b2088 bellard
90 d43277c5 Blue Swirl
/* XXX: use host strnlen if available ? */
91 d43277c5 Blue Swirl
int qemu_strnlen(const char *s, int max_len)
92 d43277c5 Blue Swirl
{
93 d43277c5 Blue Swirl
    int i;
94 d43277c5 Blue Swirl
95 d43277c5 Blue Swirl
    for(i = 0; i < max_len; i++) {
96 d43277c5 Blue Swirl
        if (s[i] == '\0') {
97 d43277c5 Blue Swirl
            break;
98 d43277c5 Blue Swirl
        }
99 d43277c5 Blue Swirl
    }
100 d43277c5 Blue Swirl
    return i;
101 d43277c5 Blue Swirl
}
102 d43277c5 Blue Swirl
103 3c6b2088 bellard
time_t mktimegm(struct tm *tm)
104 3c6b2088 bellard
{
105 3c6b2088 bellard
    time_t t;
106 3c6b2088 bellard
    int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday;
107 3c6b2088 bellard
    if (m < 3) {
108 3c6b2088 bellard
        m += 12;
109 3c6b2088 bellard
        y--;
110 3c6b2088 bellard
    }
111 3c6b2088 bellard
    t = 86400 * (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + 
112 3c6b2088 bellard
                 y / 400 - 719469);
113 3c6b2088 bellard
    t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
114 3c6b2088 bellard
    return t;
115 3c6b2088 bellard
}
116 b39ade83 aliguori
117 ad46db9a blueswir1
int qemu_fls(int i)
118 b39ade83 aliguori
{
119 8d371d4b aliguori
    return 32 - clz32(i);
120 b39ade83 aliguori
}
121 44e3ee8a aliguori
122 6f1953c4 Christoph Hellwig
/*
123 6f1953c4 Christoph Hellwig
 * Make sure data goes on disk, but if possible do not bother to
124 6f1953c4 Christoph Hellwig
 * write out the inode just for timestamp updates.
125 6f1953c4 Christoph Hellwig
 *
126 6f1953c4 Christoph Hellwig
 * Unfortunately even in 2009 many operating systems do not support
127 6f1953c4 Christoph Hellwig
 * fdatasync and have to fall back to fsync.
128 6f1953c4 Christoph Hellwig
 */
129 6f1953c4 Christoph Hellwig
int qemu_fdatasync(int fd)
130 6f1953c4 Christoph Hellwig
{
131 5f6b9e8f Blue Swirl
#ifdef CONFIG_FDATASYNC
132 6f1953c4 Christoph Hellwig
    return fdatasync(fd);
133 6f1953c4 Christoph Hellwig
#else
134 6f1953c4 Christoph Hellwig
    return fsync(fd);
135 6f1953c4 Christoph Hellwig
#endif
136 6f1953c4 Christoph Hellwig
}
137 6f1953c4 Christoph Hellwig
138 44e3ee8a aliguori
/* io vectors */
139 44e3ee8a aliguori
140 44e3ee8a aliguori
void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint)
141 44e3ee8a aliguori
{
142 7267c094 Anthony Liguori
    qiov->iov = g_malloc(alloc_hint * sizeof(struct iovec));
143 44e3ee8a aliguori
    qiov->niov = 0;
144 44e3ee8a aliguori
    qiov->nalloc = alloc_hint;
145 249aa745 aliguori
    qiov->size = 0;
146 44e3ee8a aliguori
}
147 44e3ee8a aliguori
148 522584a5 aliguori
void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov)
149 522584a5 aliguori
{
150 522584a5 aliguori
    int i;
151 522584a5 aliguori
152 522584a5 aliguori
    qiov->iov = iov;
153 522584a5 aliguori
    qiov->niov = niov;
154 522584a5 aliguori
    qiov->nalloc = -1;
155 522584a5 aliguori
    qiov->size = 0;
156 522584a5 aliguori
    for (i = 0; i < niov; i++)
157 522584a5 aliguori
        qiov->size += iov[i].iov_len;
158 522584a5 aliguori
}
159 522584a5 aliguori
160 44e3ee8a aliguori
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len)
161 44e3ee8a aliguori
{
162 522584a5 aliguori
    assert(qiov->nalloc != -1);
163 522584a5 aliguori
164 44e3ee8a aliguori
    if (qiov->niov == qiov->nalloc) {
165 44e3ee8a aliguori
        qiov->nalloc = 2 * qiov->nalloc + 1;
166 7267c094 Anthony Liguori
        qiov->iov = g_realloc(qiov->iov, qiov->nalloc * sizeof(struct iovec));
167 44e3ee8a aliguori
    }
168 44e3ee8a aliguori
    qiov->iov[qiov->niov].iov_base = base;
169 44e3ee8a aliguori
    qiov->iov[qiov->niov].iov_len = len;
170 249aa745 aliguori
    qiov->size += len;
171 44e3ee8a aliguori
    ++qiov->niov;
172 44e3ee8a aliguori
}
173 44e3ee8a aliguori
174 40b4f539 Kevin Wolf
/*
175 1b093c48 Michael Tokarev
 * Concatenates (partial) iovecs from src to the end of dst.
176 1b093c48 Michael Tokarev
 * It starts copying after skipping `soffset' bytes at the
177 1b093c48 Michael Tokarev
 * beginning of src and adds individual vectors from src to
178 1b093c48 Michael Tokarev
 * dst copies up to `sbytes' bytes total, or up to the end
179 1b093c48 Michael Tokarev
 * of src if it comes first.  This way, it is okay to specify
180 1b093c48 Michael Tokarev
 * very large value for `sbytes' to indicate "up to the end
181 1b093c48 Michael Tokarev
 * of src".
182 1b093c48 Michael Tokarev
 * Only vector pointers are processed, not the actual data buffers.
183 40b4f539 Kevin Wolf
 */
184 1b093c48 Michael Tokarev
void qemu_iovec_concat(QEMUIOVector *dst,
185 1b093c48 Michael Tokarev
                       QEMUIOVector *src, size_t soffset, size_t sbytes)
186 40b4f539 Kevin Wolf
{
187 40b4f539 Kevin Wolf
    int i;
188 40b4f539 Kevin Wolf
    size_t done;
189 1b093c48 Michael Tokarev
    struct iovec *siov = src->iov;
190 40b4f539 Kevin Wolf
    assert(dst->nalloc != -1);
191 1b093c48 Michael Tokarev
    assert(src->size >= soffset);
192 1b093c48 Michael Tokarev
    for (i = 0, done = 0; done < sbytes && i < src->niov; i++) {
193 1b093c48 Michael Tokarev
        if (soffset < siov[i].iov_len) {
194 1b093c48 Michael Tokarev
            size_t len = MIN(siov[i].iov_len - soffset, sbytes - done);
195 1b093c48 Michael Tokarev
            qemu_iovec_add(dst, siov[i].iov_base + soffset, len);
196 1b093c48 Michael Tokarev
            done += len;
197 1b093c48 Michael Tokarev
            soffset = 0;
198 b8a83a4f Kevin Wolf
        } else {
199 1b093c48 Michael Tokarev
            soffset -= siov[i].iov_len;
200 b8a83a4f Kevin Wolf
        }
201 40b4f539 Kevin Wolf
    }
202 1b093c48 Michael Tokarev
    /* return done; */
203 b8a83a4f Kevin Wolf
}
204 b8a83a4f Kevin Wolf
205 44e3ee8a aliguori
void qemu_iovec_destroy(QEMUIOVector *qiov)
206 44e3ee8a aliguori
{
207 522584a5 aliguori
    assert(qiov->nalloc != -1);
208 522584a5 aliguori
209 bd83b362 Paolo Bonzini
    qemu_iovec_reset(qiov);
210 7267c094 Anthony Liguori
    g_free(qiov->iov);
211 bd83b362 Paolo Bonzini
    qiov->nalloc = 0;
212 bd83b362 Paolo Bonzini
    qiov->iov = NULL;
213 44e3ee8a aliguori
}
214 44e3ee8a aliguori
215 be959463 aliguori
void qemu_iovec_reset(QEMUIOVector *qiov)
216 be959463 aliguori
{
217 522584a5 aliguori
    assert(qiov->nalloc != -1);
218 522584a5 aliguori
219 be959463 aliguori
    qiov->niov = 0;
220 be959463 aliguori
    qiov->size = 0;
221 be959463 aliguori
}
222 be959463 aliguori
223 d5e6b161 Michael Tokarev
size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset,
224 d5e6b161 Michael Tokarev
                         void *buf, size_t bytes)
225 44e3ee8a aliguori
{
226 d5e6b161 Michael Tokarev
    return iov_to_buf(qiov->iov, qiov->niov, offset, buf, bytes);
227 44e3ee8a aliguori
}
228 44e3ee8a aliguori
229 03396148 Michael Tokarev
size_t qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset,
230 03396148 Michael Tokarev
                           const void *buf, size_t bytes)
231 44e3ee8a aliguori
{
232 03396148 Michael Tokarev
    return iov_from_buf(qiov->iov, qiov->niov, offset, buf, bytes);
233 44e3ee8a aliguori
}
234 db1a4972 Paolo Bonzini
235 3d9b4925 Michael Tokarev
size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset,
236 3d9b4925 Michael Tokarev
                         int fillc, size_t bytes)
237 b8a83a4f Kevin Wolf
{
238 3d9b4925 Michael Tokarev
    return iov_memset(qiov->iov, qiov->niov, offset, fillc, bytes);
239 e0d9c6f9 Chunqiang Tang
}
240 e0d9c6f9 Chunqiang Tang
241 1a6d39fd Stefan Hajnoczi
/*
242 1a6d39fd Stefan Hajnoczi
 * Checks if a buffer is all zeroes
243 1a6d39fd Stefan Hajnoczi
 *
244 1a6d39fd Stefan Hajnoczi
 * Attention! The len must be a multiple of 4 * sizeof(long) due to
245 1a6d39fd Stefan Hajnoczi
 * restriction of optimizations in this function.
246 1a6d39fd Stefan Hajnoczi
 */
247 1a6d39fd Stefan Hajnoczi
bool buffer_is_zero(const void *buf, size_t len)
248 1a6d39fd Stefan Hajnoczi
{
249 1a6d39fd Stefan Hajnoczi
    /*
250 1a6d39fd Stefan Hajnoczi
     * Use long as the biggest available internal data type that fits into the
251 1a6d39fd Stefan Hajnoczi
     * CPU register and unroll the loop to smooth out the effect of memory
252 1a6d39fd Stefan Hajnoczi
     * latency.
253 1a6d39fd Stefan Hajnoczi
     */
254 1a6d39fd Stefan Hajnoczi
255 1a6d39fd Stefan Hajnoczi
    size_t i;
256 1a6d39fd Stefan Hajnoczi
    long d0, d1, d2, d3;
257 1a6d39fd Stefan Hajnoczi
    const long * const data = buf;
258 1a6d39fd Stefan Hajnoczi
259 1a6d39fd Stefan Hajnoczi
    assert(len % (4 * sizeof(long)) == 0);
260 1a6d39fd Stefan Hajnoczi
    len /= sizeof(long);
261 1a6d39fd Stefan Hajnoczi
262 1a6d39fd Stefan Hajnoczi
    for (i = 0; i < len; i += 4) {
263 1a6d39fd Stefan Hajnoczi
        d0 = data[i + 0];
264 1a6d39fd Stefan Hajnoczi
        d1 = data[i + 1];
265 1a6d39fd Stefan Hajnoczi
        d2 = data[i + 2];
266 1a6d39fd Stefan Hajnoczi
        d3 = data[i + 3];
267 1a6d39fd Stefan Hajnoczi
268 1a6d39fd Stefan Hajnoczi
        if (d0 || d1 || d2 || d3) {
269 1a6d39fd Stefan Hajnoczi
            return false;
270 1a6d39fd Stefan Hajnoczi
        }
271 1a6d39fd Stefan Hajnoczi
    }
272 1a6d39fd Stefan Hajnoczi
273 1a6d39fd Stefan Hajnoczi
    return true;
274 1a6d39fd Stefan Hajnoczi
}
275 1a6d39fd Stefan Hajnoczi
276 db1a4972 Paolo Bonzini
#ifndef _WIN32
277 db1a4972 Paolo Bonzini
/* Sets a specific flag */
278 db1a4972 Paolo Bonzini
int fcntl_setfl(int fd, int flag)
279 db1a4972 Paolo Bonzini
{
280 db1a4972 Paolo Bonzini
    int flags;
281 db1a4972 Paolo Bonzini
282 db1a4972 Paolo Bonzini
    flags = fcntl(fd, F_GETFL);
283 db1a4972 Paolo Bonzini
    if (flags == -1)
284 db1a4972 Paolo Bonzini
        return -errno;
285 db1a4972 Paolo Bonzini
286 db1a4972 Paolo Bonzini
    if (fcntl(fd, F_SETFL, flags | flag) == -1)
287 db1a4972 Paolo Bonzini
        return -errno;
288 db1a4972 Paolo Bonzini
289 db1a4972 Paolo Bonzini
    return 0;
290 db1a4972 Paolo Bonzini
}
291 db1a4972 Paolo Bonzini
#endif
292 db1a4972 Paolo Bonzini
293 eba90e4e Markus Armbruster
static int64_t suffix_mul(char suffix, int64_t unit)
294 eba90e4e Markus Armbruster
{
295 eba90e4e Markus Armbruster
    switch (qemu_toupper(suffix)) {
296 eba90e4e Markus Armbruster
    case STRTOSZ_DEFSUFFIX_B:
297 eba90e4e Markus Armbruster
        return 1;
298 eba90e4e Markus Armbruster
    case STRTOSZ_DEFSUFFIX_KB:
299 eba90e4e Markus Armbruster
        return unit;
300 eba90e4e Markus Armbruster
    case STRTOSZ_DEFSUFFIX_MB:
301 eba90e4e Markus Armbruster
        return unit * unit;
302 eba90e4e Markus Armbruster
    case STRTOSZ_DEFSUFFIX_GB:
303 eba90e4e Markus Armbruster
        return unit * unit * unit;
304 eba90e4e Markus Armbruster
    case STRTOSZ_DEFSUFFIX_TB:
305 eba90e4e Markus Armbruster
        return unit * unit * unit * unit;
306 eba90e4e Markus Armbruster
    }
307 eba90e4e Markus Armbruster
    return -1;
308 eba90e4e Markus Armbruster
}
309 eba90e4e Markus Armbruster
310 9f9b17a4 Jes Sorensen
/*
311 9f9b17a4 Jes Sorensen
 * Convert string to bytes, allowing either B/b for bytes, K/k for KB,
312 8dddfb55 Markus Armbruster
 * M/m for MB, G/g for GB or T/t for TB. End pointer will be returned
313 eba90e4e Markus Armbruster
 * in *end, if not NULL. Return -1 on error.
314 9f9b17a4 Jes Sorensen
 */
315 a732e1ba Joerg Roedel
int64_t strtosz_suffix_unit(const char *nptr, char **end,
316 a732e1ba Joerg Roedel
                            const char default_suffix, int64_t unit)
317 9f9b17a4 Jes Sorensen
{
318 70b4f4bb Jes Sorensen
    int64_t retval = -1;
319 f3bd362a Jes Sorensen
    char *endptr;
320 eba90e4e Markus Armbruster
    unsigned char c;
321 9f9b17a4 Jes Sorensen
    int mul_required = 0;
322 9f9b17a4 Jes Sorensen
    double val, mul, integral, fraction;
323 9f9b17a4 Jes Sorensen
324 9f9b17a4 Jes Sorensen
    errno = 0;
325 9f9b17a4 Jes Sorensen
    val = strtod(nptr, &endptr);
326 9f9b17a4 Jes Sorensen
    if (isnan(val) || endptr == nptr || errno != 0) {
327 9f9b17a4 Jes Sorensen
        goto fail;
328 9f9b17a4 Jes Sorensen
    }
329 7eb05349 Jes Sorensen
    fraction = modf(val, &integral);
330 7eb05349 Jes Sorensen
    if (fraction != 0) {
331 9f9b17a4 Jes Sorensen
        mul_required = 1;
332 9f9b17a4 Jes Sorensen
    }
333 9f9b17a4 Jes Sorensen
    c = *endptr;
334 eba90e4e Markus Armbruster
    mul = suffix_mul(c, unit);
335 eba90e4e Markus Armbruster
    if (mul >= 0) {
336 eba90e4e Markus Armbruster
        endptr++;
337 eba90e4e Markus Armbruster
    } else {
338 eba90e4e Markus Armbruster
        mul = suffix_mul(default_suffix, unit);
339 eba90e4e Markus Armbruster
        assert(mul >= 0);
340 9f9b17a4 Jes Sorensen
    }
341 eba90e4e Markus Armbruster
    if (mul == 1 && mul_required) {
342 9f9b17a4 Jes Sorensen
        goto fail;
343 9f9b17a4 Jes Sorensen
    }
344 70b4f4bb Jes Sorensen
    if ((val * mul >= INT64_MAX) || val < 0) {
345 9f9b17a4 Jes Sorensen
        goto fail;
346 9f9b17a4 Jes Sorensen
    }
347 9f9b17a4 Jes Sorensen
    retval = val * mul;
348 9f9b17a4 Jes Sorensen
349 9f9b17a4 Jes Sorensen
fail:
350 9f9b17a4 Jes Sorensen
    if (end) {
351 9f9b17a4 Jes Sorensen
        *end = endptr;
352 9f9b17a4 Jes Sorensen
    }
353 9f9b17a4 Jes Sorensen
354 9f9b17a4 Jes Sorensen
    return retval;
355 9f9b17a4 Jes Sorensen
}
356 d8427002 Jes Sorensen
357 a732e1ba Joerg Roedel
int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
358 a732e1ba Joerg Roedel
{
359 fdc9c41a Jan Kiszka
    return strtosz_suffix_unit(nptr, end, default_suffix, 1024);
360 a732e1ba Joerg Roedel
}
361 a732e1ba Joerg Roedel
362 70b4f4bb Jes Sorensen
int64_t strtosz(const char *nptr, char **end)
363 d8427002 Jes Sorensen
{
364 d8427002 Jes Sorensen
    return strtosz_suffix(nptr, end, STRTOSZ_DEFSUFFIX_MB);
365 d8427002 Jes Sorensen
}
366 443916d1 Stefan Berger
367 443916d1 Stefan Berger
int qemu_parse_fd(const char *param)
368 443916d1 Stefan Berger
{
369 443916d1 Stefan Berger
    int fd;
370 443916d1 Stefan Berger
    char *endptr = NULL;
371 443916d1 Stefan Berger
372 443916d1 Stefan Berger
    fd = strtol(param, &endptr, 10);
373 443916d1 Stefan Berger
    if (*endptr || (fd == 0 && param == endptr)) {
374 443916d1 Stefan Berger
        return -1;
375 443916d1 Stefan Berger
    }
376 443916d1 Stefan Berger
    return fd;
377 443916d1 Stefan Berger
}
378 8c5135f9 Paolo Bonzini
379 e3e87df4 Michael Tokarev
ssize_t iov_send_recv(int sockfd, struct iovec *iov,
380 e3e87df4 Michael Tokarev
                      size_t offset, size_t bytes,
381 e3e87df4 Michael Tokarev
                      bool do_sendv)
382 8c5135f9 Paolo Bonzini
{
383 3e80bf93 Michael Tokarev
    int iovlen;
384 3e80bf93 Michael Tokarev
    ssize_t ret;
385 3e80bf93 Michael Tokarev
    size_t diff;
386 8c5135f9 Paolo Bonzini
    struct iovec *last_iov;
387 8c5135f9 Paolo Bonzini
388 8c5135f9 Paolo Bonzini
    /* last_iov is inclusive, so count from one.  */
389 8c5135f9 Paolo Bonzini
    iovlen = 1;
390 8c5135f9 Paolo Bonzini
    last_iov = iov;
391 3e80bf93 Michael Tokarev
    bytes += offset;
392 8c5135f9 Paolo Bonzini
393 3e80bf93 Michael Tokarev
    while (last_iov->iov_len < bytes) {
394 3e80bf93 Michael Tokarev
        bytes -= last_iov->iov_len;
395 8c5135f9 Paolo Bonzini
396 8c5135f9 Paolo Bonzini
        last_iov++;
397 8c5135f9 Paolo Bonzini
        iovlen++;
398 8c5135f9 Paolo Bonzini
    }
399 8c5135f9 Paolo Bonzini
400 3e80bf93 Michael Tokarev
    diff = last_iov->iov_len - bytes;
401 8c5135f9 Paolo Bonzini
    last_iov->iov_len -= diff;
402 8c5135f9 Paolo Bonzini
403 8c5135f9 Paolo Bonzini
    while (iov->iov_len <= offset) {
404 8c5135f9 Paolo Bonzini
        offset -= iov->iov_len;
405 8c5135f9 Paolo Bonzini
406 8c5135f9 Paolo Bonzini
        iov++;
407 8c5135f9 Paolo Bonzini
        iovlen--;
408 8c5135f9 Paolo Bonzini
    }
409 8c5135f9 Paolo Bonzini
410 8c5135f9 Paolo Bonzini
    iov->iov_base = (char *) iov->iov_base + offset;
411 8c5135f9 Paolo Bonzini
    iov->iov_len -= offset;
412 8c5135f9 Paolo Bonzini
413 8c5135f9 Paolo Bonzini
    {
414 8c5135f9 Paolo Bonzini
#if defined CONFIG_IOVEC && defined CONFIG_POSIX
415 8c5135f9 Paolo Bonzini
        struct msghdr msg;
416 8c5135f9 Paolo Bonzini
        memset(&msg, 0, sizeof(msg));
417 8c5135f9 Paolo Bonzini
        msg.msg_iov = iov;
418 8c5135f9 Paolo Bonzini
        msg.msg_iovlen = iovlen;
419 8c5135f9 Paolo Bonzini
420 8c5135f9 Paolo Bonzini
        do {
421 8c5135f9 Paolo Bonzini
            if (do_sendv) {
422 8c5135f9 Paolo Bonzini
                ret = sendmsg(sockfd, &msg, 0);
423 8c5135f9 Paolo Bonzini
            } else {
424 8c5135f9 Paolo Bonzini
                ret = recvmsg(sockfd, &msg, 0);
425 8c5135f9 Paolo Bonzini
            }
426 8c5135f9 Paolo Bonzini
        } while (ret == -1 && errno == EINTR);
427 8c5135f9 Paolo Bonzini
#else
428 8c5135f9 Paolo Bonzini
        struct iovec *p = iov;
429 8c5135f9 Paolo Bonzini
        ret = 0;
430 8c5135f9 Paolo Bonzini
        while (iovlen > 0) {
431 8c5135f9 Paolo Bonzini
            int rc;
432 8c5135f9 Paolo Bonzini
            if (do_sendv) {
433 8c5135f9 Paolo Bonzini
                rc = send(sockfd, p->iov_base, p->iov_len, 0);
434 8c5135f9 Paolo Bonzini
            } else {
435 8c5135f9 Paolo Bonzini
                rc = qemu_recv(sockfd, p->iov_base, p->iov_len, 0);
436 8c5135f9 Paolo Bonzini
            }
437 8c5135f9 Paolo Bonzini
            if (rc == -1) {
438 8c5135f9 Paolo Bonzini
                if (errno == EINTR) {
439 8c5135f9 Paolo Bonzini
                    continue;
440 8c5135f9 Paolo Bonzini
                }
441 8c5135f9 Paolo Bonzini
                if (ret == 0) {
442 8c5135f9 Paolo Bonzini
                    ret = -1;
443 8c5135f9 Paolo Bonzini
                }
444 8c5135f9 Paolo Bonzini
                break;
445 8c5135f9 Paolo Bonzini
            }
446 8c5135f9 Paolo Bonzini
            if (rc == 0) {
447 8c5135f9 Paolo Bonzini
                break;
448 8c5135f9 Paolo Bonzini
            }
449 8c5135f9 Paolo Bonzini
            ret += rc;
450 8c5135f9 Paolo Bonzini
            iovlen--, p++;
451 8c5135f9 Paolo Bonzini
        }
452 8c5135f9 Paolo Bonzini
#endif
453 8c5135f9 Paolo Bonzini
    }
454 8c5135f9 Paolo Bonzini
455 8c5135f9 Paolo Bonzini
    /* Undo the changes above */
456 8c5135f9 Paolo Bonzini
    iov->iov_base = (char *) iov->iov_base - offset;
457 8c5135f9 Paolo Bonzini
    iov->iov_len += offset;
458 8c5135f9 Paolo Bonzini
    last_iov->iov_len += diff;
459 8c5135f9 Paolo Bonzini
    return ret;
460 8c5135f9 Paolo Bonzini
}