Statistics
| Branch: | Revision:

root / cutils.c @ e3e87df4

History | View | Annotate | Download (10.8 kB)

1
/*
2
 * Simple C functions to supplement the C library
3
 *
4
 * Copyright (c) 2006 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "qemu-common.h"
25
#include "host-utils.h"
26
#include <math.h>
27

    
28
#include "qemu_socket.h"
29
#include "iov.h"
30

    
31
void pstrcpy(char *buf, int buf_size, const char *str)
32
{
33
    int c;
34
    char *q = buf;
35

    
36
    if (buf_size <= 0)
37
        return;
38

    
39
    for(;;) {
40
        c = *str++;
41
        if (c == 0 || q >= buf + buf_size - 1)
42
            break;
43
        *q++ = c;
44
    }
45
    *q = '\0';
46
}
47

    
48
/* strcat and truncate. */
49
char *pstrcat(char *buf, int buf_size, const char *s)
50
{
51
    int len;
52
    len = strlen(buf);
53
    if (len < buf_size)
54
        pstrcpy(buf + len, buf_size - len, s);
55
    return buf;
56
}
57

    
58
int strstart(const char *str, const char *val, const char **ptr)
59
{
60
    const char *p, *q;
61
    p = str;
62
    q = val;
63
    while (*q != '\0') {
64
        if (*p != *q)
65
            return 0;
66
        p++;
67
        q++;
68
    }
69
    if (ptr)
70
        *ptr = p;
71
    return 1;
72
}
73

    
74
int stristart(const char *str, const char *val, const char **ptr)
75
{
76
    const char *p, *q;
77
    p = str;
78
    q = val;
79
    while (*q != '\0') {
80
        if (qemu_toupper(*p) != qemu_toupper(*q))
81
            return 0;
82
        p++;
83
        q++;
84
    }
85
    if (ptr)
86
        *ptr = p;
87
    return 1;
88
}
89

    
90
/* XXX: use host strnlen if available ? */
91
int qemu_strnlen(const char *s, int max_len)
92
{
93
    int i;
94

    
95
    for(i = 0; i < max_len; i++) {
96
        if (s[i] == '\0') {
97
            break;
98
        }
99
    }
100
    return i;
101
}
102

    
103
time_t mktimegm(struct tm *tm)
104
{
105
    time_t t;
106
    int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday;
107
    if (m < 3) {
108
        m += 12;
109
        y--;
110
    }
111
    t = 86400 * (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + 
112
                 y / 400 - 719469);
113
    t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
114
    return t;
115
}
116

    
117
int qemu_fls(int i)
118
{
119
    return 32 - clz32(i);
120
}
121

    
122
/*
123
 * Make sure data goes on disk, but if possible do not bother to
124
 * write out the inode just for timestamp updates.
125
 *
126
 * Unfortunately even in 2009 many operating systems do not support
127
 * fdatasync and have to fall back to fsync.
128
 */
129
int qemu_fdatasync(int fd)
130
{
131
#ifdef CONFIG_FDATASYNC
132
    return fdatasync(fd);
133
#else
134
    return fsync(fd);
135
#endif
136
}
137

    
138
/* io vectors */
139

    
140
void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint)
141
{
142
    qiov->iov = g_malloc(alloc_hint * sizeof(struct iovec));
143
    qiov->niov = 0;
144
    qiov->nalloc = alloc_hint;
145
    qiov->size = 0;
146
}
147

    
148
void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov)
149
{
150
    int i;
151

    
152
    qiov->iov = iov;
153
    qiov->niov = niov;
154
    qiov->nalloc = -1;
155
    qiov->size = 0;
156
    for (i = 0; i < niov; i++)
157
        qiov->size += iov[i].iov_len;
158
}
159

    
160
void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len)
161
{
162
    assert(qiov->nalloc != -1);
163

    
164
    if (qiov->niov == qiov->nalloc) {
165
        qiov->nalloc = 2 * qiov->nalloc + 1;
166
        qiov->iov = g_realloc(qiov->iov, qiov->nalloc * sizeof(struct iovec));
167
    }
168
    qiov->iov[qiov->niov].iov_base = base;
169
    qiov->iov[qiov->niov].iov_len = len;
170
    qiov->size += len;
171
    ++qiov->niov;
172
}
173

    
174
/*
175
 * Concatenates (partial) iovecs from src to the end of dst.
176
 * It starts copying after skipping `soffset' bytes at the
177
 * beginning of src and adds individual vectors from src to
178
 * dst copies up to `sbytes' bytes total, or up to the end
179
 * of src if it comes first.  This way, it is okay to specify
180
 * very large value for `sbytes' to indicate "up to the end
181
 * of src".
182
 * Only vector pointers are processed, not the actual data buffers.
183
 */
184
void qemu_iovec_concat(QEMUIOVector *dst,
185
                       QEMUIOVector *src, size_t soffset, size_t sbytes)
186
{
187
    int i;
188
    size_t done;
189
    struct iovec *siov = src->iov;
190
    assert(dst->nalloc != -1);
191
    assert(src->size >= soffset);
192
    for (i = 0, done = 0; done < sbytes && i < src->niov; i++) {
193
        if (soffset < siov[i].iov_len) {
194
            size_t len = MIN(siov[i].iov_len - soffset, sbytes - done);
195
            qemu_iovec_add(dst, siov[i].iov_base + soffset, len);
196
            done += len;
197
            soffset = 0;
198
        } else {
199
            soffset -= siov[i].iov_len;
200
        }
201
    }
202
    /* return done; */
203
}
204

    
205
void qemu_iovec_destroy(QEMUIOVector *qiov)
206
{
207
    assert(qiov->nalloc != -1);
208

    
209
    qemu_iovec_reset(qiov);
210
    g_free(qiov->iov);
211
    qiov->nalloc = 0;
212
    qiov->iov = NULL;
213
}
214

    
215
void qemu_iovec_reset(QEMUIOVector *qiov)
216
{
217
    assert(qiov->nalloc != -1);
218

    
219
    qiov->niov = 0;
220
    qiov->size = 0;
221
}
222

    
223
size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset,
224
                         void *buf, size_t bytes)
225
{
226
    return iov_to_buf(qiov->iov, qiov->niov, offset, buf, bytes);
227
}
228

    
229
size_t qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset,
230
                           const void *buf, size_t bytes)
231
{
232
    return iov_from_buf(qiov->iov, qiov->niov, offset, buf, bytes);
233
}
234

    
235
size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset,
236
                         int fillc, size_t bytes)
237
{
238
    return iov_memset(qiov->iov, qiov->niov, offset, fillc, bytes);
239
}
240

    
241
/*
242
 * Checks if a buffer is all zeroes
243
 *
244
 * Attention! The len must be a multiple of 4 * sizeof(long) due to
245
 * restriction of optimizations in this function.
246
 */
247
bool buffer_is_zero(const void *buf, size_t len)
248
{
249
    /*
250
     * Use long as the biggest available internal data type that fits into the
251
     * CPU register and unroll the loop to smooth out the effect of memory
252
     * latency.
253
     */
254

    
255
    size_t i;
256
    long d0, d1, d2, d3;
257
    const long * const data = buf;
258

    
259
    assert(len % (4 * sizeof(long)) == 0);
260
    len /= sizeof(long);
261

    
262
    for (i = 0; i < len; i += 4) {
263
        d0 = data[i + 0];
264
        d1 = data[i + 1];
265
        d2 = data[i + 2];
266
        d3 = data[i + 3];
267

    
268
        if (d0 || d1 || d2 || d3) {
269
            return false;
270
        }
271
    }
272

    
273
    return true;
274
}
275

    
276
#ifndef _WIN32
277
/* Sets a specific flag */
278
int fcntl_setfl(int fd, int flag)
279
{
280
    int flags;
281

    
282
    flags = fcntl(fd, F_GETFL);
283
    if (flags == -1)
284
        return -errno;
285

    
286
    if (fcntl(fd, F_SETFL, flags | flag) == -1)
287
        return -errno;
288

    
289
    return 0;
290
}
291
#endif
292

    
293
static int64_t suffix_mul(char suffix, int64_t unit)
294
{
295
    switch (qemu_toupper(suffix)) {
296
    case STRTOSZ_DEFSUFFIX_B:
297
        return 1;
298
    case STRTOSZ_DEFSUFFIX_KB:
299
        return unit;
300
    case STRTOSZ_DEFSUFFIX_MB:
301
        return unit * unit;
302
    case STRTOSZ_DEFSUFFIX_GB:
303
        return unit * unit * unit;
304
    case STRTOSZ_DEFSUFFIX_TB:
305
        return unit * unit * unit * unit;
306
    }
307
    return -1;
308
}
309

    
310
/*
311
 * Convert string to bytes, allowing either B/b for bytes, K/k for KB,
312
 * M/m for MB, G/g for GB or T/t for TB. End pointer will be returned
313
 * in *end, if not NULL. Return -1 on error.
314
 */
315
int64_t strtosz_suffix_unit(const char *nptr, char **end,
316
                            const char default_suffix, int64_t unit)
317
{
318
    int64_t retval = -1;
319
    char *endptr;
320
    unsigned char c;
321
    int mul_required = 0;
322
    double val, mul, integral, fraction;
323

    
324
    errno = 0;
325
    val = strtod(nptr, &endptr);
326
    if (isnan(val) || endptr == nptr || errno != 0) {
327
        goto fail;
328
    }
329
    fraction = modf(val, &integral);
330
    if (fraction != 0) {
331
        mul_required = 1;
332
    }
333
    c = *endptr;
334
    mul = suffix_mul(c, unit);
335
    if (mul >= 0) {
336
        endptr++;
337
    } else {
338
        mul = suffix_mul(default_suffix, unit);
339
        assert(mul >= 0);
340
    }
341
    if (mul == 1 && mul_required) {
342
        goto fail;
343
    }
344
    if ((val * mul >= INT64_MAX) || val < 0) {
345
        goto fail;
346
    }
347
    retval = val * mul;
348

    
349
fail:
350
    if (end) {
351
        *end = endptr;
352
    }
353

    
354
    return retval;
355
}
356

    
357
int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
358
{
359
    return strtosz_suffix_unit(nptr, end, default_suffix, 1024);
360
}
361

    
362
int64_t strtosz(const char *nptr, char **end)
363
{
364
    return strtosz_suffix(nptr, end, STRTOSZ_DEFSUFFIX_MB);
365
}
366

    
367
int qemu_parse_fd(const char *param)
368
{
369
    int fd;
370
    char *endptr = NULL;
371

    
372
    fd = strtol(param, &endptr, 10);
373
    if (*endptr || (fd == 0 && param == endptr)) {
374
        return -1;
375
    }
376
    return fd;
377
}
378

    
379
ssize_t iov_send_recv(int sockfd, struct iovec *iov,
380
                      size_t offset, size_t bytes,
381
                      bool do_sendv)
382
{
383
    int iovlen;
384
    ssize_t ret;
385
    size_t diff;
386
    struct iovec *last_iov;
387

    
388
    /* last_iov is inclusive, so count from one.  */
389
    iovlen = 1;
390
    last_iov = iov;
391
    bytes += offset;
392

    
393
    while (last_iov->iov_len < bytes) {
394
        bytes -= last_iov->iov_len;
395

    
396
        last_iov++;
397
        iovlen++;
398
    }
399

    
400
    diff = last_iov->iov_len - bytes;
401
    last_iov->iov_len -= diff;
402

    
403
    while (iov->iov_len <= offset) {
404
        offset -= iov->iov_len;
405

    
406
        iov++;
407
        iovlen--;
408
    }
409

    
410
    iov->iov_base = (char *) iov->iov_base + offset;
411
    iov->iov_len -= offset;
412

    
413
    {
414
#if defined CONFIG_IOVEC && defined CONFIG_POSIX
415
        struct msghdr msg;
416
        memset(&msg, 0, sizeof(msg));
417
        msg.msg_iov = iov;
418
        msg.msg_iovlen = iovlen;
419

    
420
        do {
421
            if (do_sendv) {
422
                ret = sendmsg(sockfd, &msg, 0);
423
            } else {
424
                ret = recvmsg(sockfd, &msg, 0);
425
            }
426
        } while (ret == -1 && errno == EINTR);
427
#else
428
        struct iovec *p = iov;
429
        ret = 0;
430
        while (iovlen > 0) {
431
            int rc;
432
            if (do_sendv) {
433
                rc = send(sockfd, p->iov_base, p->iov_len, 0);
434
            } else {
435
                rc = qemu_recv(sockfd, p->iov_base, p->iov_len, 0);
436
            }
437
            if (rc == -1) {
438
                if (errno == EINTR) {
439
                    continue;
440
                }
441
                if (ret == 0) {
442
                    ret = -1;
443
                }
444
                break;
445
            }
446
            if (rc == 0) {
447
                break;
448
            }
449
            ret += rc;
450
            iovlen--, p++;
451
        }
452
#endif
453
    }
454

    
455
    /* Undo the changes above */
456
    iov->iov_base = (char *) iov->iov_base - offset;
457
    iov->iov_len += offset;
458
    last_iov->iov_len += diff;
459
    return ret;
460
}