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 27 void pstrcpy(char *buf, int buf_size, const char *str) 28 { 29 int c; 30 char *q = buf; 31 32 if (buf_size <= 0) 33 return; 34 35 for(;;) { 36 c = *str++; 37 if (c == 0 || q >= buf + buf_size - 1) 38 break; 39 *q++ = c; 40 } 41 *q = '\0'; 42 } 43 44 /* strcat and truncate. */ 45 char *pstrcat(char *buf, int buf_size, const char *s) 46 { 47 int len; 48 len = strlen(buf); 49 if (len < buf_size) 50 pstrcpy(buf + len, buf_size - len, s); 51 return buf; 52 } 53 54 int strstart(const char *str, const char *val, const char **ptr) 55 { 56 const char *p, *q; 57 p = str; 58 q = val; 59 while (*q != '\0') { 60 if (*p != *q) 61 return 0; 62 p++; 63 q++; 64 } 65 if (ptr) 66 *ptr = p; 67 return 1; 68 } 69 70 int stristart(const char *str, const char *val, const char **ptr) 71 { 72 const char *p, *q; 73 p = str; 74 q = val; 75 while (*q != '\0') { 76 if (qemu_toupper(*p) != qemu_toupper(*q)) 77 return 0; 78 p++; 79 q++; 80 } 81 if (ptr) 82 *ptr = p; 83 return 1; 84 } 85 86 /* XXX: use host strnlen if available ? */ 87 int qemu_strnlen(const char *s, int max_len) 88 { 89 int i; 90 91 for(i = 0; i < max_len; i++) { 92 if (s[i] == '\0') { 93 break; 94 } 95 } 96 return i; 97 } 98 99 time_t mktimegm(struct tm *tm) 100 { 101 time_t t; 102 int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday; 103 if (m < 3) { 104 m += 12; 105 y--; 106 } 107 t = 86400 * (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + 108 y / 400 - 719469); 109 t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec; 110 return t; 111 } 112 113 int qemu_fls(int i) 114 { 115 return 32 - clz32(i); 116 } 117 118 /* 119 * Make sure data goes on disk, but if possible do not bother to 120 * write out the inode just for timestamp updates. 121 * 122 * Unfortunately even in 2009 many operating systems do not support 123 * fdatasync and have to fall back to fsync. 124 */ 125 int qemu_fdatasync(int fd) 126 { 127 #ifdef CONFIG_FDATASYNC 128 return fdatasync(fd); 129 #else 130 return fsync(fd); 131 #endif 132 } 133 134 /* io vectors */ 135 136 void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint) 137 { 138 qiov->iov = qemu_malloc(alloc_hint * sizeof(struct iovec)); 139 qiov->niov = 0; 140 qiov->nalloc = alloc_hint; 141 qiov->size = 0; 142 } 143 144 void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov) 145 { 146 int i; 147 148 qiov->iov = iov; 149 qiov->niov = niov; 150 qiov->nalloc = -1; 151 qiov->size = 0; 152 for (i = 0; i < niov; i++) 153 qiov->size += iov[i].iov_len; 154 } 155 156 void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len) 157 { 158 assert(qiov->nalloc != -1); 159 160 if (qiov->niov == qiov->nalloc) { 161 qiov->nalloc = 2 * qiov->nalloc + 1; 162 qiov->iov = qemu_realloc(qiov->iov, qiov->nalloc * sizeof(struct iovec)); 163 } 164 qiov->iov[qiov->niov].iov_base = base; 165 qiov->iov[qiov->niov].iov_len = len; 166 qiov->size += len; 167 ++qiov->niov; 168 } 169 170 /* 171 * Copies iovecs from src to the end dst until src is completely copied or the 172 * total size of the copied iovec reaches size. The size of the last copied 173 * iovec is changed in order to fit the specified total size if it isn't a 174 * perfect fit already. 175 */ 176 void qemu_iovec_concat(QEMUIOVector *dst, QEMUIOVector *src, size_t size) 177 { 178 int i; 179 size_t done; 180 181 assert(dst->nalloc != -1); 182 183 done = 0; 184 for (i = 0; (i < src->niov) && (done != size); i++) { 185 if (done + src->iov[i].iov_len > size) { 186 qemu_iovec_add(dst, src->iov[i].iov_base, size - done); 187 break; 188 } else { 189 qemu_iovec_add(dst, src->iov[i].iov_base, src->iov[i].iov_len); 190 } 191 done += src->iov[i].iov_len; 192 } 193 } 194 195 void qemu_iovec_destroy(QEMUIOVector *qiov) 196 { 197 assert(qiov->nalloc != -1); 198 199 qemu_free(qiov->iov); 200 } 201 202 void qemu_iovec_reset(QEMUIOVector *qiov) 203 { 204 assert(qiov->nalloc != -1); 205 206 qiov->niov = 0; 207 qiov->size = 0; 208 } 209 210 void qemu_iovec_to_buffer(QEMUIOVector *qiov, void *buf) 211 { 212 uint8_t *p = (uint8_t *)buf; 213 int i; 214 215 for (i = 0; i < qiov->niov; ++i) { 216 memcpy(p, qiov->iov[i].iov_base, qiov->iov[i].iov_len); 217 p += qiov->iov[i].iov_len; 218 } 219 } 220 221 void qemu_iovec_from_buffer(QEMUIOVector *qiov, const void *buf, size_t count) 222 { 223 const uint8_t *p = (const uint8_t *)buf; 224 size_t copy; 225 int i; 226 227 for (i = 0; i < qiov->niov && count; ++i) { 228 copy = count; 229 if (copy > qiov->iov[i].iov_len) 230 copy = qiov->iov[i].iov_len; 231 memcpy(qiov->iov[i].iov_base, p, copy); 232 p += copy; 233 count -= copy; 234 } 235 } 236