Home | History | Annotate | Download | only in qemu
      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 void pstrcpy(char *buf, int buf_size, const char *str)
     29 {
     30     int c;
     31     char *q = buf;
     32 
     33     if (buf_size <= 0)
     34         return;
     35 
     36     for(;;) {
     37         c = *str++;
     38         if (c == 0 || q >= buf + buf_size - 1)
     39             break;
     40         *q++ = c;
     41     }
     42     *q = '\0';
     43 }
     44 
     45 /* strcat and truncate. */
     46 char *pstrcat(char *buf, int buf_size, const char *s)
     47 {
     48     int len;
     49     len = strlen(buf);
     50     if (len < buf_size)
     51         pstrcpy(buf + len, buf_size - len, s);
     52     return buf;
     53 }
     54 
     55 int strstart(const char *str, const char *val, const char **ptr)
     56 {
     57     const char *p, *q;
     58     p = str;
     59     q = val;
     60     while (*q != '\0') {
     61         if (*p != *q)
     62             return 0;
     63         p++;
     64         q++;
     65     }
     66     if (ptr)
     67         *ptr = p;
     68     return 1;
     69 }
     70 
     71 int stristart(const char *str, const char *val, const char **ptr)
     72 {
     73     const char *p, *q;
     74     p = str;
     75     q = val;
     76     while (*q != '\0') {
     77         if (qemu_toupper(*p) != qemu_toupper(*q))
     78             return 0;
     79         p++;
     80         q++;
     81     }
     82     if (ptr)
     83         *ptr = p;
     84     return 1;
     85 }
     86 
     87 /* XXX: use host strnlen if available ? */
     88 int qemu_strnlen(const char *s, int max_len)
     89 {
     90     int i;
     91 
     92     for(i = 0; i < max_len; i++) {
     93         if (s[i] == '\0') {
     94             break;
     95         }
     96     }
     97     return i;
     98 }
     99 
    100 time_t mktimegm(struct tm *tm)
    101 {
    102     time_t t;
    103     int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday;
    104     if (m < 3) {
    105         m += 12;
    106         y--;
    107     }
    108     t = 86400 * (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 +
    109                  y / 400 - 719469);
    110     t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
    111     return t;
    112 }
    113 
    114 int qemu_fls(int i)
    115 {
    116     return 32 - clz32(i);
    117 }
    118 
    119 /*
    120  * Make sure data goes on disk, but if possible do not bother to
    121  * write out the inode just for timestamp updates.
    122  *
    123  * Unfortunately even in 2009 many operating systems do not support
    124  * fdatasync and have to fall back to fsync.
    125  */
    126 int qemu_fdatasync(int fd)
    127 {
    128 #ifdef CONFIG_FDATASYNC
    129     return fdatasync(fd);
    130 #else
    131     return fsync(fd);
    132 #endif
    133 }
    134 
    135 /* io vectors */
    136 
    137 void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint)
    138 {
    139     qiov->iov = qemu_malloc(alloc_hint * sizeof(struct iovec));
    140     qiov->niov = 0;
    141     qiov->nalloc = alloc_hint;
    142     qiov->size = 0;
    143 }
    144 
    145 void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov)
    146 {
    147     int i;
    148 
    149     qiov->iov = iov;
    150     qiov->niov = niov;
    151     qiov->nalloc = -1;
    152     qiov->size = 0;
    153     for (i = 0; i < niov; i++)
    154         qiov->size += iov[i].iov_len;
    155 }
    156 
    157 void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len)
    158 {
    159     assert(qiov->nalloc != -1);
    160 
    161     if (qiov->niov == qiov->nalloc) {
    162         qiov->nalloc = 2 * qiov->nalloc + 1;
    163         qiov->iov = qemu_realloc(qiov->iov, qiov->nalloc * sizeof(struct iovec));
    164     }
    165     qiov->iov[qiov->niov].iov_base = base;
    166     qiov->iov[qiov->niov].iov_len = len;
    167     qiov->size += len;
    168     ++qiov->niov;
    169 }
    170 
    171 /*
    172  * Copies iovecs from src to the end of dst. It starts copying after skipping
    173  * the given number of bytes in src and copies until src is completely copied
    174  * or the total size of the copied iovec reaches size.The size of the last
    175  * copied iovec is changed in order to fit the specified total size if it isn't
    176  * a perfect fit already.
    177  */
    178 void qemu_iovec_copy(QEMUIOVector *dst, QEMUIOVector *src, uint64_t skip,
    179     size_t size)
    180 {
    181     int i;
    182     size_t done;
    183     void *iov_base;
    184     uint64_t iov_len;
    185 
    186     assert(dst->nalloc != -1);
    187 
    188     done = 0;
    189     for (i = 0; (i < src->niov) && (done != size); i++) {
    190         if (skip >= src->iov[i].iov_len) {
    191             /* Skip the whole iov */
    192             skip -= src->iov[i].iov_len;
    193             continue;
    194         } else {
    195             /* Skip only part (or nothing) of the iov */
    196             iov_base = (uint8_t*) src->iov[i].iov_base + skip;
    197             iov_len = src->iov[i].iov_len - skip;
    198             skip = 0;
    199         }
    200 
    201         if (done + iov_len > size) {
    202             qemu_iovec_add(dst, iov_base, size - done);
    203             break;
    204         } else {
    205             qemu_iovec_add(dst, iov_base, iov_len);
    206         }
    207         done += iov_len;
    208     }
    209 }
    210 
    211 void qemu_iovec_concat(QEMUIOVector *dst, QEMUIOVector *src, size_t size)
    212 {
    213     qemu_iovec_copy(dst, src, 0, size);
    214 }
    215 
    216 void qemu_iovec_destroy(QEMUIOVector *qiov)
    217 {
    218     assert(qiov->nalloc != -1);
    219 
    220     qemu_free(qiov->iov);
    221 }
    222 
    223 void qemu_iovec_reset(QEMUIOVector *qiov)
    224 {
    225     assert(qiov->nalloc != -1);
    226 
    227     qiov->niov = 0;
    228     qiov->size = 0;
    229 }
    230 
    231 void qemu_iovec_to_buffer(QEMUIOVector *qiov, void *buf)
    232 {
    233     uint8_t *p = (uint8_t *)buf;
    234     int i;
    235 
    236     for (i = 0; i < qiov->niov; ++i) {
    237         memcpy(p, qiov->iov[i].iov_base, qiov->iov[i].iov_len);
    238         p += qiov->iov[i].iov_len;
    239     }
    240 }
    241 
    242 void qemu_iovec_from_buffer(QEMUIOVector *qiov, const void *buf, size_t count)
    243 {
    244     const uint8_t *p = (const uint8_t *)buf;
    245     size_t copy;
    246     int i;
    247 
    248     for (i = 0; i < qiov->niov && count; ++i) {
    249         copy = count;
    250         if (copy > qiov->iov[i].iov_len)
    251             copy = qiov->iov[i].iov_len;
    252         memcpy(qiov->iov[i].iov_base, p, copy);
    253         p     += copy;
    254         count -= copy;
    255     }
    256 }
    257 
    258 void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count)
    259 {
    260     size_t n;
    261     int i;
    262 
    263     for (i = 0; i < qiov->niov && count; ++i) {
    264         n = MIN(count, qiov->iov[i].iov_len);
    265         memset(qiov->iov[i].iov_base, c, n);
    266         count -= n;
    267     }
    268 }
    269 
    270 void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count,
    271                             size_t skip)
    272 {
    273     int i;
    274     size_t done;
    275     void *iov_base;
    276     uint64_t iov_len;
    277 
    278     done = 0;
    279     for (i = 0; (i < qiov->niov) && (done != count); i++) {
    280         if (skip >= qiov->iov[i].iov_len) {
    281             /* Skip the whole iov */
    282             skip -= qiov->iov[i].iov_len;
    283             continue;
    284         } else {
    285             /* Skip only part (or nothing) of the iov */
    286             iov_base = (uint8_t*) qiov->iov[i].iov_base + skip;
    287             iov_len = qiov->iov[i].iov_len - skip;
    288             skip = 0;
    289         }
    290 
    291         if (done + iov_len > count) {
    292             memset(iov_base, c, count - done);
    293             break;
    294         } else {
    295             memset(iov_base, c, iov_len);
    296         }
    297         done += iov_len;
    298     }
    299 }
    300 
    301 #ifndef _WIN32
    302 /* Sets a specific flag */
    303 int fcntl_setfl(int fd, int flag)
    304 {
    305     int flags;
    306 
    307     flags = fcntl(fd, F_GETFL);
    308     if (flags == -1)
    309         return -errno;
    310 
    311     if (fcntl(fd, F_SETFL, flags | flag) == -1)
    312         return -errno;
    313 
    314     return 0;
    315 }
    316 #endif
    317 
    318 /*
    319  * Convert string to bytes, allowing either B/b for bytes, K/k for KB,
    320  * M/m for MB, G/g for GB or T/t for TB. Default without any postfix
    321  * is MB. End pointer will be returned in *end, if not NULL. A valid
    322  * value must be terminated by whitespace, ',' or '\0'. Return -1 on
    323  * error.
    324  */
    325 int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
    326 {
    327     int64_t retval = -1;
    328     char *endptr;
    329     unsigned char c, d;
    330     int mul_required = 0;
    331     double val, mul, integral, fraction;
    332 
    333     errno = 0;
    334     val = strtod(nptr, &endptr);
    335     if (isnan(val) || endptr == nptr || errno != 0) {
    336         goto fail;
    337     }
    338     fraction = modf(val, &integral);
    339     if (fraction != 0) {
    340         mul_required = 1;
    341     }
    342     /*
    343      * Any whitespace character is fine for terminating the number,
    344      * in addition we accept ',' to handle strings where the size is
    345      * part of a multi token argument.
    346      */
    347     c = *endptr;
    348     d = c;
    349     if (qemu_isspace(c) || c == '\0' || c == ',') {
    350         c = 0;
    351         if (default_suffix) {
    352             d = default_suffix;
    353         } else {
    354             d = c;
    355         }
    356     }
    357     switch (qemu_toupper(d)) {
    358     case STRTOSZ_DEFSUFFIX_B:
    359         mul = 1;
    360         if (mul_required) {
    361             goto fail;
    362         }
    363         break;
    364     case STRTOSZ_DEFSUFFIX_KB:
    365         mul = 1 << 10;
    366         break;
    367     case 0:
    368         if (mul_required) {
    369             goto fail;
    370         }
    371     case STRTOSZ_DEFSUFFIX_MB:
    372         mul = 1ULL << 20;
    373         break;
    374     case STRTOSZ_DEFSUFFIX_GB:
    375         mul = 1ULL << 30;
    376         break;
    377     case STRTOSZ_DEFSUFFIX_TB:
    378         mul = 1ULL << 40;
    379         break;
    380     default:
    381         goto fail;
    382     }
    383     /*
    384      * If not terminated by whitespace, ',', or \0, increment endptr
    385      * to point to next character, then check that we are terminated
    386      * by an appropriate separating character, ie. whitespace, ',', or
    387      * \0. If not, we are seeing trailing garbage, thus fail.
    388      */
    389     if (c != 0) {
    390         endptr++;
    391         if (!qemu_isspace(*endptr) && *endptr != ',' && *endptr != 0) {
    392             goto fail;
    393         }
    394     }
    395     if ((val * mul >= INT64_MAX) || val < 0) {
    396         goto fail;
    397     }
    398     retval = val * mul;
    399 
    400 fail:
    401     if (end) {
    402         *end = endptr;
    403     }
    404 
    405     return retval;
    406 }
    407 
    408 int64_t strtosz(const char *nptr, char **end)
    409 {
    410     return strtosz_suffix(nptr, end, STRTOSZ_DEFSUFFIX_MB);
    411 }
    412