diff options
Diffstat (limited to 'cutils.c')
-rw-r--r-- | cutils.c | 234 |
1 files changed, 30 insertions, 204 deletions
@@ -26,6 +26,7 @@ #include <math.h> #include "qemu_socket.h" +#include "iov.h" void pstrcpy(char *buf, int buf_size, const char *str) { @@ -171,48 +172,34 @@ void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len) } /* - * Copies iovecs from src to the end of dst. It starts copying after skipping - * the given number of bytes in src and copies until src is completely copied - * or the total size of the copied iovec reaches size.The size of the last - * copied iovec is changed in order to fit the specified total size if it isn't - * a perfect fit already. + * Concatenates (partial) iovecs from src to the end of dst. + * It starts copying after skipping `soffset' bytes at the + * beginning of src and adds individual vectors from src to + * dst copies up to `sbytes' bytes total, or up to the end + * of src if it comes first. This way, it is okay to specify + * very large value for `sbytes' to indicate "up to the end + * of src". + * Only vector pointers are processed, not the actual data buffers. */ -void qemu_iovec_copy(QEMUIOVector *dst, QEMUIOVector *src, uint64_t skip, - size_t size) +void qemu_iovec_concat(QEMUIOVector *dst, + QEMUIOVector *src, size_t soffset, size_t sbytes) { int i; size_t done; - void *iov_base; - uint64_t iov_len; - + struct iovec *siov = src->iov; assert(dst->nalloc != -1); - - done = 0; - for (i = 0; (i < src->niov) && (done != size); i++) { - if (skip >= src->iov[i].iov_len) { - /* Skip the whole iov */ - skip -= src->iov[i].iov_len; - continue; - } else { - /* Skip only part (or nothing) of the iov */ - iov_base = (uint8_t*) src->iov[i].iov_base + skip; - iov_len = src->iov[i].iov_len - skip; - skip = 0; - } - - if (done + iov_len > size) { - qemu_iovec_add(dst, iov_base, size - done); - break; + assert(src->size >= soffset); + for (i = 0, done = 0; done < sbytes && i < src->niov; i++) { + if (soffset < siov[i].iov_len) { + size_t len = MIN(siov[i].iov_len - soffset, sbytes - done); + qemu_iovec_add(dst, siov[i].iov_base + soffset, len); + done += len; + soffset = 0; } else { - qemu_iovec_add(dst, iov_base, iov_len); + soffset -= siov[i].iov_len; } - done += iov_len; } -} - -void qemu_iovec_concat(QEMUIOVector *dst, QEMUIOVector *src, size_t size) -{ - qemu_iovec_copy(dst, src, 0, size); + /* return done; */ } void qemu_iovec_destroy(QEMUIOVector *qiov) @@ -233,74 +220,22 @@ void qemu_iovec_reset(QEMUIOVector *qiov) qiov->size = 0; } -void qemu_iovec_to_buffer(QEMUIOVector *qiov, void *buf) +size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset, + void *buf, size_t bytes) { - uint8_t *p = (uint8_t *)buf; - int i; - - for (i = 0; i < qiov->niov; ++i) { - memcpy(p, qiov->iov[i].iov_base, qiov->iov[i].iov_len); - p += qiov->iov[i].iov_len; - } + return iov_to_buf(qiov->iov, qiov->niov, offset, buf, bytes); } -void qemu_iovec_from_buffer(QEMUIOVector *qiov, const void *buf, size_t count) +size_t qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset, + const void *buf, size_t bytes) { - const uint8_t *p = (const uint8_t *)buf; - size_t copy; - int i; - - for (i = 0; i < qiov->niov && count; ++i) { - copy = count; - if (copy > qiov->iov[i].iov_len) - copy = qiov->iov[i].iov_len; - memcpy(qiov->iov[i].iov_base, p, copy); - p += copy; - count -= copy; - } + return iov_from_buf(qiov->iov, qiov->niov, offset, buf, bytes); } -void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count) +size_t qemu_iovec_memset(QEMUIOVector *qiov, size_t offset, + int fillc, size_t bytes) { - size_t n; - int i; - - for (i = 0; i < qiov->niov && count; ++i) { - n = MIN(count, qiov->iov[i].iov_len); - memset(qiov->iov[i].iov_base, c, n); - count -= n; - } -} - -void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count, - size_t skip) -{ - int i; - size_t done; - void *iov_base; - uint64_t iov_len; - - done = 0; - for (i = 0; (i < qiov->niov) && (done != count); i++) { - if (skip >= qiov->iov[i].iov_len) { - /* Skip the whole iov */ - skip -= qiov->iov[i].iov_len; - continue; - } else { - /* Skip only part (or nothing) of the iov */ - iov_base = (uint8_t*) qiov->iov[i].iov_base + skip; - iov_len = qiov->iov[i].iov_len - skip; - skip = 0; - } - - if (done + iov_len > count) { - memset(iov_base, c, count - done); - break; - } else { - memset(iov_base, c, iov_len); - } - done += iov_len; - } + return iov_memset(qiov->iov, qiov->niov, offset, fillc, bytes); } /* @@ -440,112 +375,3 @@ int qemu_parse_fd(const char *param) } return fd; } - -/* - * Send/recv data with iovec buffers - * - * This function send/recv data from/to the iovec buffer directly. - * The first `offset' bytes in the iovec buffer are skipped and next - * `len' bytes are used. - * - * For example, - * - * do_sendv_recvv(sockfd, iov, len, offset, 1); - * - * is equal to - * - * char *buf = malloc(size); - * iov_to_buf(iov, iovcnt, buf, offset, size); - * send(sockfd, buf, size, 0); - * free(buf); - */ -static int do_sendv_recvv(int sockfd, struct iovec *iov, int len, int offset, - int do_sendv) -{ - int ret, diff, iovlen; - struct iovec *last_iov; - - /* last_iov is inclusive, so count from one. */ - iovlen = 1; - last_iov = iov; - len += offset; - - while (last_iov->iov_len < len) { - len -= last_iov->iov_len; - - last_iov++; - iovlen++; - } - - diff = last_iov->iov_len - len; - last_iov->iov_len -= diff; - - while (iov->iov_len <= offset) { - offset -= iov->iov_len; - - iov++; - iovlen--; - } - - iov->iov_base = (char *) iov->iov_base + offset; - iov->iov_len -= offset; - - { -#if defined CONFIG_IOVEC && defined CONFIG_POSIX - struct msghdr msg; - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = iov; - msg.msg_iovlen = iovlen; - - do { - if (do_sendv) { - ret = sendmsg(sockfd, &msg, 0); - } else { - ret = recvmsg(sockfd, &msg, 0); - } - } while (ret == -1 && errno == EINTR); -#else - struct iovec *p = iov; - ret = 0; - while (iovlen > 0) { - int rc; - if (do_sendv) { - rc = send(sockfd, p->iov_base, p->iov_len, 0); - } else { - rc = qemu_recv(sockfd, p->iov_base, p->iov_len, 0); - } - if (rc == -1) { - if (errno == EINTR) { - continue; - } - if (ret == 0) { - ret = -1; - } - break; - } - if (rc == 0) { - break; - } - ret += rc; - iovlen--, p++; - } -#endif - } - - /* Undo the changes above */ - iov->iov_base = (char *) iov->iov_base - offset; - iov->iov_len += offset; - last_iov->iov_len += diff; - return ret; -} - -int qemu_recvv(int sockfd, struct iovec *iov, int len, int iov_offset) -{ - return do_sendv_recvv(sockfd, iov, len, iov_offset, 0); -} - -int qemu_sendv(int sockfd, struct iovec *iov, int len, int iov_offset) -{ - return do_sendv_recvv(sockfd, iov, len, iov_offset, 1); -} - |