From patchwork Fri Oct 14 18:19:56 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 119902 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 00518B6F9A for ; Sat, 15 Oct 2011 05:36:40 +1100 (EST) Received: from localhost ([::1]:57189 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1REmNP-0003SA-4g for incoming@patchwork.ozlabs.org; Fri, 14 Oct 2011 14:20:59 -0400 Received: from eggs.gnu.org ([140.186.70.92]:53465) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1REmMz-00037Z-DV for qemu-devel@nongnu.org; Fri, 14 Oct 2011 14:20:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1REmMw-0005cN-Hc for qemu-devel@nongnu.org; Fri, 14 Oct 2011 14:20:33 -0400 Received: from mout.perfora.net ([74.208.4.195]:52583) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1REmMw-0005cE-6R for qemu-devel@nongnu.org; Fri, 14 Oct 2011 14:20:30 -0400 Received: from illuin.austin.ibm.com ([32.97.110.59]) by mrelay.perfora.net (node=mrus1) with ESMTP (Nemesis) id 0MPW1p-1RAdVQ1oLx-004e8d; Fri, 14 Oct 2011 14:20:29 -0400 From: Michael Roth To: qemu-devel@nongnu.org Date: Fri, 14 Oct 2011 13:19:56 -0500 Message-Id: <1318616402-18474-5-git-send-email-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1318616402-18474-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1318616402-18474-1-git-send-email-mdroth@linux.vnet.ibm.com> X-Provags-ID: V02:K0:mWpj18p/g3Ify/x6+Fgp499R4iR6Bs4w7/isJxYZXuS zgJNzpRq0JGSdrN4Ct6fIhXyaV6R1NvWPdwLj7hUFK4WXBaQq1 /l3V0vZezJUMa7w2jSUk5HoIq9rlZgDfT4g7lmPdGA20xPSyo8 dudWIet+BXrpGwUZpFicYpYMr73silccIme/S1SmK45g1X/VV1 FXghYBFvnrlJXXDeTrd+rECs9cNoxgaXDvszxea3GeyFl1Yu9L YfVa6MWapX+waiY0gkcxrVoZG4MfHvGpILVmTL+hhV6nAm7CxP TOH5FLNrXU1UKBbuktTeJQVpVuZRTBMrVC25108E9yi2Xhu3ka sToPZYC9D6VIe2qRYfLYB+/88GBrTupbVi24ZBhobzJbvyDukc aM56S64Q9yrAKikFgIQa7Z+qhPFANTuXXA= X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 74.208.4.195 Cc: aliguori@us.ibm.com, mdroth@linux.vnet.ibm.com Subject: [Qemu-devel] [PATCH 04/10] savevm: move QEMUFile interfaces into qemu-file.c X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Michael Roth --- Makefile.objs | 2 +- hw/hw.h | 1 + qemu-file.c | 541 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ savevm.c | 494 ---------------------------------------------------- 4 files changed, 543 insertions(+), 495 deletions(-) create mode 100644 qemu-file.c diff --git a/Makefile.objs b/Makefile.objs index b39750b..75c5770 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -119,7 +119,7 @@ common-obj-$(CONFIG_SD) += sd.o common-obj-y += bt.o bt-host.o bt-vhci.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o usb-bt.o common-obj-y += bt-hci-csr.o common-obj-y += buffered_file.o migration.o migration-tcp.o -common-obj-y += qemu-char.o savevm.o #aio.o +common-obj-y += qemu-char.o savevm.o qemu-file.o #aio.o common-obj-y += msmouse.o ps2.o common-obj-y += qdev.o qdev-properties.o common-obj-y += block-migration.o iohandler.o diff --git a/hw/hw.h b/hw/hw.h index a124da9..244bfb9 100644 --- a/hw/hw.h +++ b/hw/hw.h @@ -58,6 +58,7 @@ void qemu_fflush(QEMUFile *f); int qemu_fclose(QEMUFile *f); void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size); void qemu_put_byte(QEMUFile *f, int v); +int qemu_peek_byte(QEMUFile *f); static inline void qemu_put_ubyte(QEMUFile *f, unsigned int v) { diff --git a/qemu-file.c b/qemu-file.c new file mode 100644 index 0000000..fed555d --- /dev/null +++ b/qemu-file.c @@ -0,0 +1,541 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu-common.h" +#include "qemu_socket.h" +#include "hw/hw.h" + +#define IO_BUF_SIZE 32768 + +struct QEMUFile { + QEMUFilePutBufferFunc *put_buffer; + QEMUFileGetBufferFunc *get_buffer; + QEMUFileCloseFunc *close; + QEMUFileRateLimit *rate_limit; + QEMUFileSetRateLimit *set_rate_limit; + QEMUFileGetRateLimit *get_rate_limit; + void *opaque; + int is_write; + + int64_t buf_offset; /* start of buffer when writing, end of buffer + when reading */ + int buf_index; + int buf_size; /* 0 when writing */ + uint8_t buf[IO_BUF_SIZE]; + + int has_error; +}; + +QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer, + QEMUFileGetBufferFunc *get_buffer, + QEMUFileCloseFunc *close, + QEMUFileRateLimit *rate_limit, + QEMUFileSetRateLimit *set_rate_limit, + QEMUFileGetRateLimit *get_rate_limit) +{ + QEMUFile *f; + + f = g_malloc0(sizeof(QEMUFile)); + + f->opaque = opaque; + f->put_buffer = put_buffer; + f->get_buffer = get_buffer; + f->close = close; + f->rate_limit = rate_limit; + f->set_rate_limit = set_rate_limit; + f->get_rate_limit = get_rate_limit; + f->is_write = 0; + + return f; +} + +int qemu_file_has_error(QEMUFile *f) +{ + return f->has_error; +} + +void qemu_file_set_error(QEMUFile *f) +{ + f->has_error = 1; +} + +void qemu_fflush(QEMUFile *f) +{ + if (!f->put_buffer) { + return; + } + + if (f->is_write && f->buf_index > 0) { + int len; + + len = f->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index); + if (len > 0) { + f->buf_offset += f->buf_index; + } + else { + f->has_error = 1; + } + f->buf_index = 0; + } +} + +static void qemu_fill_buffer(QEMUFile *f) +{ + int len; + + if (!f->get_buffer) { + return; + } + + if (f->is_write) { + abort(); + } + + len = f->get_buffer(f->opaque, f->buf, f->buf_offset, IO_BUF_SIZE); + if (len > 0) { + f->buf_index = 0; + f->buf_size = len; + f->buf_offset += len; + } else if (len != -EAGAIN) { + f->has_error = 1; + } +} + +int qemu_fclose(QEMUFile *f) +{ + int ret = 0; + qemu_fflush(f); + if (f->close) { + ret = f->close(f->opaque); + } + g_free(f); + return ret; +} + +void qemu_file_put_notify(QEMUFile *f) +{ + f->put_buffer(f->opaque, NULL, 0, 0); +} + +void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size) +{ + int l; + + if (!f->has_error && f->is_write == 0 && f->buf_index > 0) { + fprintf(stderr, + "Attempted to write to buffer while read buffer is not empty\n"); + abort(); + } + + while (!f->has_error && size > 0) { + l = IO_BUF_SIZE - f->buf_index; + if (l > size) { + l = size; + } + memcpy(f->buf + f->buf_index, buf, l); + f->is_write = 1; + f->buf_index += l; + buf += l; + size -= l; + if (f->buf_index >= IO_BUF_SIZE) { + qemu_fflush(f); + } + } +} + +void qemu_put_byte(QEMUFile *f, int v) +{ + if (!f->has_error && f->is_write == 0 && f->buf_index > 0) { + fprintf(stderr, + "Attempted to write to buffer while read buffer is not empty\n"); + abort(); + } + + f->buf[f->buf_index++] = v; + f->is_write = 1; + if (f->buf_index >= IO_BUF_SIZE) { + qemu_fflush(f); + } +} + +int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1) +{ + int size, l; + + if (f->is_write) { + abort(); + } + + size = size1; + while (size > 0) { + l = f->buf_size - f->buf_index; + if (l == 0) { + qemu_fill_buffer(f); + l = f->buf_size - f->buf_index; + if (l == 0) + break; + } + if (l > size) { + l = size; + } + memcpy(buf, f->buf + f->buf_index, l); + f->buf_index += l; + buf += l; + size -= l; + } + return size1 - size; +} + +int qemu_get_byte(QEMUFile *f) +{ + if (f->is_write) { + abort(); + } + + if (f->buf_index >= f->buf_size) { + qemu_fill_buffer(f); + if (f->buf_index >= f->buf_size) { + return 0; + } + } + return f->buf[f->buf_index++]; +} + +int64_t qemu_ftell(QEMUFile *f) +{ + return f->buf_offset - f->buf_size + f->buf_index; +} + +int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence) +{ + if (whence == SEEK_SET) { + /* nothing to do */ + } else if (whence == SEEK_CUR) { + pos += qemu_ftell(f); + } else { + /* SEEK_END not supported */ + return -1; + } + if (f->put_buffer) { + qemu_fflush(f); + f->buf_offset = pos; + } else { + f->buf_offset = pos; + f->buf_index = 0; + f->buf_size = 0; + } + return pos; +} + +int qemu_peek_byte(QEMUFile *f) +{ + if (f->is_write) { + abort(); + } + + if (f->buf_index >= f->buf_size) { + qemu_fill_buffer(f); + if (f->buf_index >= f->buf_size) { + return 0; + } + } + return f->buf[f->buf_index]; +} + +int qemu_file_rate_limit(QEMUFile *f) +{ + if (f->rate_limit) { + return f->rate_limit(f->opaque); + } + + return 0; +} + +int64_t qemu_file_get_rate_limit(QEMUFile *f) +{ + if (f->get_rate_limit) { + return f->get_rate_limit(f->opaque); + } + + return 0; +} + +int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate) +{ + /* any failed or completed migration keeps its state to allow probing of + * migration data, but has no associated file anymore */ + if (f && f->set_rate_limit) { + return f->set_rate_limit(f->opaque, new_rate); + } + + return 0; +} + +void qemu_put_be16(QEMUFile *f, unsigned int v) +{ + qemu_put_byte(f, v >> 8); + qemu_put_byte(f, v); +} + +void qemu_put_be32(QEMUFile *f, unsigned int v) +{ + qemu_put_byte(f, v >> 24); + qemu_put_byte(f, v >> 16); + qemu_put_byte(f, v >> 8); + qemu_put_byte(f, v); +} + +void qemu_put_be64(QEMUFile *f, uint64_t v) +{ + qemu_put_be32(f, v >> 32); + qemu_put_be32(f, v); +} + +unsigned int qemu_get_be16(QEMUFile *f) +{ + unsigned int v; + v = qemu_get_byte(f) << 8; + v |= qemu_get_byte(f); + return v; +} + +unsigned int qemu_get_be32(QEMUFile *f) +{ + unsigned int v; + v = qemu_get_byte(f) << 24; + v |= qemu_get_byte(f) << 16; + v |= qemu_get_byte(f) << 8; + v |= qemu_get_byte(f); + return v; +} + +uint64_t qemu_get_be64(QEMUFile *f) +{ + uint64_t v; + v = (uint64_t)qemu_get_be32(f) << 32; + v |= qemu_get_be32(f); + return v; +} + +typedef struct QEMUFileStdio +{ + FILE *stdio_file; + QEMUFile *file; +} QEMUFileStdio; + +typedef struct QEMUFileSocket +{ + int fd; + QEMUFile *file; +} QEMUFileSocket; + +static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) +{ + QEMUFileSocket *s = opaque; + ssize_t len; + + do { + len = qemu_recv(s->fd, buf, size, 0); + } while (len == -1 && socket_error() == EINTR); + + if (len == -1) + len = -socket_error(); + + return len; +} + +static int socket_close(void *opaque) +{ + QEMUFileSocket *s = opaque; + g_free(s); + return 0; +} + +int qemu_stdio_fd(QEMUFile *f) +{ + QEMUFileStdio *p; + int fd; + + p = (QEMUFileStdio *)f->opaque; + fd = fileno(p->stdio_file); + + return fd; +} + +static int stdio_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, + int size) +{ + QEMUFileStdio *s = opaque; + return fwrite(buf, 1, size, s->stdio_file); +} + +static int stdio_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) +{ + QEMUFileStdio *s = opaque; + FILE *fp = s->stdio_file; + int bytes; + + do { + clearerr(fp); + bytes = fread(buf, 1, size, fp); + } while ((bytes == 0) && ferror(fp) && (errno == EINTR)); + return bytes; +} + +static int stdio_pclose(void *opaque) +{ + QEMUFileStdio *s = opaque; + int ret; + ret = pclose(s->stdio_file); + g_free(s); + return ret; +} + +static int stdio_fclose(void *opaque) +{ + QEMUFileStdio *s = opaque; + fclose(s->stdio_file); + g_free(s); + return 0; +} + +QEMUFile *qemu_popen(FILE *stdio_file, const char *mode) +{ + QEMUFileStdio *s; + + if (stdio_file == NULL || mode == NULL || + (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) { + fprintf(stderr, "qemu_popen: Argument validity check failed\n"); + return NULL; + } + + s = g_malloc0(sizeof(QEMUFileStdio)); + + s->stdio_file = stdio_file; + + if(mode[0] == 'r') { + s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_pclose, + NULL, NULL, NULL); + } else { + s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_pclose, + NULL, NULL, NULL); + } + return s->file; +} + +QEMUFile *qemu_popen_cmd(const char *command, const char *mode) +{ + FILE *popen_file; + + popen_file = popen(command, mode); + if(popen_file == NULL) { + return NULL; + } + + return qemu_popen(popen_file, mode); +} + +QEMUFile *qemu_fdopen(int fd, const char *mode) +{ + QEMUFileStdio *s; + + if (mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || + mode[1] != 'b' || mode[2] != 0) { + fprintf(stderr, "qemu_fdopen: Argument validity check failed\n"); + return NULL; + } + + s = g_malloc0(sizeof(QEMUFileStdio)); + s->stdio_file = fdopen(fd, mode); + if (!s->stdio_file) + goto fail; + + if(mode[0] == 'r') { + s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_fclose, + NULL, NULL, NULL); + } else { + s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_fclose, + NULL, NULL, NULL); + } + return s->file; + +fail: + g_free(s); + return NULL; +} + +QEMUFile *qemu_fopen_socket(int fd) +{ + QEMUFileSocket *s = g_malloc0(sizeof(QEMUFileSocket)); + + s->fd = fd; + s->file = qemu_fopen_ops(s, NULL, socket_get_buffer, socket_close, + NULL, NULL, NULL); + return s->file; +} + +static int file_put_buffer(void *opaque, const uint8_t *buf, + int64_t pos, int size) +{ + QEMUFileStdio *s = opaque; + fseek(s->stdio_file, pos, SEEK_SET); + return fwrite(buf, 1, size, s->stdio_file); +} + +static int file_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) +{ + QEMUFileStdio *s = opaque; + fseek(s->stdio_file, pos, SEEK_SET); + return fread(buf, 1, size, s->stdio_file); +} + +QEMUFile *qemu_fopen(const char *filename, const char *mode) +{ + QEMUFileStdio *s; + + if (mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || + mode[1] != 'b' || mode[2] != 0) { + fprintf(stderr, "qemu_fopen: Argument validity check failed\n"); + return NULL; + } + + s = g_malloc0(sizeof(QEMUFileStdio)); + + s->stdio_file = fopen(filename, mode); + if (!s->stdio_file) { + goto fail; + } + + if(mode[0] == 'w') { + s->file = qemu_fopen_ops(s, file_put_buffer, NULL, stdio_fclose, + NULL, NULL, NULL); + } else { + s->file = qemu_fopen_ops(s, NULL, file_get_buffer, stdio_fclose, + NULL, NULL, NULL); + } + return s->file; +fail: + g_free(s); + return NULL; +} diff --git a/savevm.c b/savevm.c index bf4d0e7..95135e1 100644 --- a/savevm.c +++ b/savevm.c @@ -155,228 +155,6 @@ void qemu_announce_self(void) /***********************************************************/ /* savevm/loadvm support */ -#define IO_BUF_SIZE 32768 - -struct QEMUFile { - QEMUFilePutBufferFunc *put_buffer; - QEMUFileGetBufferFunc *get_buffer; - QEMUFileCloseFunc *close; - QEMUFileRateLimit *rate_limit; - QEMUFileSetRateLimit *set_rate_limit; - QEMUFileGetRateLimit *get_rate_limit; - void *opaque; - int is_write; - - int64_t buf_offset; /* start of buffer when writing, end of buffer - when reading */ - int buf_index; - int buf_size; /* 0 when writing */ - uint8_t buf[IO_BUF_SIZE]; - - int has_error; -}; - -typedef struct QEMUFileStdio -{ - FILE *stdio_file; - QEMUFile *file; -} QEMUFileStdio; - -typedef struct QEMUFileSocket -{ - int fd; - QEMUFile *file; -} QEMUFileSocket; - -static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) -{ - QEMUFileSocket *s = opaque; - ssize_t len; - - do { - len = qemu_recv(s->fd, buf, size, 0); - } while (len == -1 && socket_error() == EINTR); - - if (len == -1) - len = -socket_error(); - - return len; -} - -static int socket_close(void *opaque) -{ - QEMUFileSocket *s = opaque; - g_free(s); - return 0; -} - -static int stdio_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size) -{ - QEMUFileStdio *s = opaque; - return fwrite(buf, 1, size, s->stdio_file); -} - -static int stdio_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) -{ - QEMUFileStdio *s = opaque; - FILE *fp = s->stdio_file; - int bytes; - - do { - clearerr(fp); - bytes = fread(buf, 1, size, fp); - } while ((bytes == 0) && ferror(fp) && (errno == EINTR)); - return bytes; -} - -static int stdio_pclose(void *opaque) -{ - QEMUFileStdio *s = opaque; - int ret; - ret = pclose(s->stdio_file); - g_free(s); - return ret; -} - -static int stdio_fclose(void *opaque) -{ - QEMUFileStdio *s = opaque; - fclose(s->stdio_file); - g_free(s); - return 0; -} - -QEMUFile *qemu_popen(FILE *stdio_file, const char *mode) -{ - QEMUFileStdio *s; - - if (stdio_file == NULL || mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) { - fprintf(stderr, "qemu_popen: Argument validity check failed\n"); - return NULL; - } - - s = g_malloc0(sizeof(QEMUFileStdio)); - - s->stdio_file = stdio_file; - - if(mode[0] == 'r') { - s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_pclose, - NULL, NULL, NULL); - } else { - s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_pclose, - NULL, NULL, NULL); - } - return s->file; -} - -QEMUFile *qemu_popen_cmd(const char *command, const char *mode) -{ - FILE *popen_file; - - popen_file = popen(command, mode); - if(popen_file == NULL) { - return NULL; - } - - return qemu_popen(popen_file, mode); -} - -int qemu_stdio_fd(QEMUFile *f) -{ - QEMUFileStdio *p; - int fd; - - p = (QEMUFileStdio *)f->opaque; - fd = fileno(p->stdio_file); - - return fd; -} - -QEMUFile *qemu_fdopen(int fd, const char *mode) -{ - QEMUFileStdio *s; - - if (mode == NULL || - (mode[0] != 'r' && mode[0] != 'w') || - mode[1] != 'b' || mode[2] != 0) { - fprintf(stderr, "qemu_fdopen: Argument validity check failed\n"); - return NULL; - } - - s = g_malloc0(sizeof(QEMUFileStdio)); - s->stdio_file = fdopen(fd, mode); - if (!s->stdio_file) - goto fail; - - if(mode[0] == 'r') { - s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_fclose, - NULL, NULL, NULL); - } else { - s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_fclose, - NULL, NULL, NULL); - } - return s->file; - -fail: - g_free(s); - return NULL; -} - -QEMUFile *qemu_fopen_socket(int fd) -{ - QEMUFileSocket *s = g_malloc0(sizeof(QEMUFileSocket)); - - s->fd = fd; - s->file = qemu_fopen_ops(s, NULL, socket_get_buffer, socket_close, - NULL, NULL, NULL); - return s->file; -} - -static int file_put_buffer(void *opaque, const uint8_t *buf, - int64_t pos, int size) -{ - QEMUFileStdio *s = opaque; - fseek(s->stdio_file, pos, SEEK_SET); - return fwrite(buf, 1, size, s->stdio_file); -} - -static int file_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) -{ - QEMUFileStdio *s = opaque; - fseek(s->stdio_file, pos, SEEK_SET); - return fread(buf, 1, size, s->stdio_file); -} - -QEMUFile *qemu_fopen(const char *filename, const char *mode) -{ - QEMUFileStdio *s; - - if (mode == NULL || - (mode[0] != 'r' && mode[0] != 'w') || - mode[1] != 'b' || mode[2] != 0) { - fprintf(stderr, "qemu_fopen: Argument validity check failed\n"); - return NULL; - } - - s = g_malloc0(sizeof(QEMUFileStdio)); - - s->stdio_file = fopen(filename, mode); - if (!s->stdio_file) - goto fail; - - if(mode[0] == 'w') { - s->file = qemu_fopen_ops(s, file_put_buffer, NULL, stdio_fclose, - NULL, NULL, NULL); - } else { - s->file = qemu_fopen_ops(s, NULL, file_get_buffer, stdio_fclose, - NULL, NULL, NULL); - } - return s->file; -fail: - g_free(s); - return NULL; -} - static int block_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size) { @@ -402,278 +180,6 @@ static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable) return qemu_fopen_ops(bs, NULL, block_get_buffer, bdrv_fclose, NULL, NULL, NULL); } -QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer, - QEMUFileGetBufferFunc *get_buffer, - QEMUFileCloseFunc *close, - QEMUFileRateLimit *rate_limit, - QEMUFileSetRateLimit *set_rate_limit, - QEMUFileGetRateLimit *get_rate_limit) -{ - QEMUFile *f; - - f = g_malloc0(sizeof(QEMUFile)); - - f->opaque = opaque; - f->put_buffer = put_buffer; - f->get_buffer = get_buffer; - f->close = close; - f->rate_limit = rate_limit; - f->set_rate_limit = set_rate_limit; - f->get_rate_limit = get_rate_limit; - f->is_write = 0; - - return f; -} - -int qemu_file_has_error(QEMUFile *f) -{ - return f->has_error; -} - -void qemu_file_set_error(QEMUFile *f) -{ - f->has_error = 1; -} - -void qemu_fflush(QEMUFile *f) -{ - if (!f->put_buffer) - return; - - if (f->is_write && f->buf_index > 0) { - int len; - - len = f->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index); - if (len > 0) - f->buf_offset += f->buf_index; - else - f->has_error = 1; - f->buf_index = 0; - } -} - -static void qemu_fill_buffer(QEMUFile *f) -{ - int len; - - if (!f->get_buffer) - return; - - if (f->is_write) - abort(); - - len = f->get_buffer(f->opaque, f->buf, f->buf_offset, IO_BUF_SIZE); - if (len > 0) { - f->buf_index = 0; - f->buf_size = len; - f->buf_offset += len; - } else if (len != -EAGAIN) - f->has_error = 1; -} - -int qemu_fclose(QEMUFile *f) -{ - int ret = 0; - qemu_fflush(f); - if (f->close) - ret = f->close(f->opaque); - g_free(f); - return ret; -} - -void qemu_file_put_notify(QEMUFile *f) -{ - f->put_buffer(f->opaque, NULL, 0, 0); -} - -void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size) -{ - int l; - - if (!f->has_error && f->is_write == 0 && f->buf_index > 0) { - fprintf(stderr, - "Attempted to write to buffer while read buffer is not empty\n"); - abort(); - } - - while (!f->has_error && size > 0) { - l = IO_BUF_SIZE - f->buf_index; - if (l > size) - l = size; - memcpy(f->buf + f->buf_index, buf, l); - f->is_write = 1; - f->buf_index += l; - buf += l; - size -= l; - if (f->buf_index >= IO_BUF_SIZE) - qemu_fflush(f); - } -} - -void qemu_put_byte(QEMUFile *f, int v) -{ - if (!f->has_error && f->is_write == 0 && f->buf_index > 0) { - fprintf(stderr, - "Attempted to write to buffer while read buffer is not empty\n"); - abort(); - } - - f->buf[f->buf_index++] = v; - f->is_write = 1; - if (f->buf_index >= IO_BUF_SIZE) - qemu_fflush(f); -} - -int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1) -{ - int size, l; - - if (f->is_write) - abort(); - - size = size1; - while (size > 0) { - l = f->buf_size - f->buf_index; - if (l == 0) { - qemu_fill_buffer(f); - l = f->buf_size - f->buf_index; - if (l == 0) - break; - } - if (l > size) - l = size; - memcpy(buf, f->buf + f->buf_index, l); - f->buf_index += l; - buf += l; - size -= l; - } - return size1 - size; -} - -static int qemu_peek_byte(QEMUFile *f) -{ - if (f->is_write) - abort(); - - if (f->buf_index >= f->buf_size) { - qemu_fill_buffer(f); - if (f->buf_index >= f->buf_size) - return 0; - } - return f->buf[f->buf_index]; -} - -int qemu_get_byte(QEMUFile *f) -{ - if (f->is_write) - abort(); - - if (f->buf_index >= f->buf_size) { - qemu_fill_buffer(f); - if (f->buf_index >= f->buf_size) - return 0; - } - return f->buf[f->buf_index++]; -} - -int64_t qemu_ftell(QEMUFile *f) -{ - return f->buf_offset - f->buf_size + f->buf_index; -} - -int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence) -{ - if (whence == SEEK_SET) { - /* nothing to do */ - } else if (whence == SEEK_CUR) { - pos += qemu_ftell(f); - } else { - /* SEEK_END not supported */ - return -1; - } - if (f->put_buffer) { - qemu_fflush(f); - f->buf_offset = pos; - } else { - f->buf_offset = pos; - f->buf_index = 0; - f->buf_size = 0; - } - return pos; -} - -int qemu_file_rate_limit(QEMUFile *f) -{ - if (f->rate_limit) - return f->rate_limit(f->opaque); - - return 0; -} - -int64_t qemu_file_get_rate_limit(QEMUFile *f) -{ - if (f->get_rate_limit) - return f->get_rate_limit(f->opaque); - - return 0; -} - -int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate) -{ - /* any failed or completed migration keeps its state to allow probing of - * migration data, but has no associated file anymore */ - if (f && f->set_rate_limit) - return f->set_rate_limit(f->opaque, new_rate); - - return 0; -} - -void qemu_put_be16(QEMUFile *f, unsigned int v) -{ - qemu_put_byte(f, v >> 8); - qemu_put_byte(f, v); -} - -void qemu_put_be32(QEMUFile *f, unsigned int v) -{ - qemu_put_byte(f, v >> 24); - qemu_put_byte(f, v >> 16); - qemu_put_byte(f, v >> 8); - qemu_put_byte(f, v); -} - -void qemu_put_be64(QEMUFile *f, uint64_t v) -{ - qemu_put_be32(f, v >> 32); - qemu_put_be32(f, v); -} - -unsigned int qemu_get_be16(QEMUFile *f) -{ - unsigned int v; - v = qemu_get_byte(f) << 8; - v |= qemu_get_byte(f); - return v; -} - -unsigned int qemu_get_be32(QEMUFile *f) -{ - unsigned int v; - v = qemu_get_byte(f) << 24; - v |= qemu_get_byte(f) << 16; - v |= qemu_get_byte(f) << 8; - v |= qemu_get_byte(f); - return v; -} - -uint64_t qemu_get_be64(QEMUFile *f) -{ - uint64_t v; - v = (uint64_t)qemu_get_be32(f) << 32; - v |= qemu_get_be32(f); - return v; -} - /* bool */ static int get_bool(QEMUFile *f, void *pv, size_t size)