migration/qemu-file.h: Move QEMUFile declarations here.

Move the QEMUFile-related declarations to migration/qemu-file.h,
from hw/hw.h to get closer to upstream. Note that this also
updates the implementation slightly. The end result is still
different from upstream in certain ways, that will be handled
in future patches.

Change-Id: I11719c4449040df13d9e6f62c55d642a0dd6434d
diff --git a/savevm.c b/savevm.c
index a81b166..e344fe8 100644
--- a/savevm.c
+++ b/savevm.c
@@ -162,12 +162,7 @@
 #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;
+    const QEMUFileOps* ops;
     void *opaque;
     int is_write;
 
@@ -192,6 +187,13 @@
     QEMUFile *file;
 } QEMUFileSocket;
 
+static int socket_get_fd(void *opaque)
+{
+    QEMUFileSocket *s = opaque;
+
+    return s->fd;
+}
+
 static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
 {
     QEMUFileSocket *s = opaque;
@@ -210,13 +212,22 @@
 static int file_socket_close(void *opaque)
 {
     QEMUFileSocket *s = opaque;
+    if (s->fd >= 0)
+        socket_close(s->fd);
     g_free(s);
     return 0;
 }
 
+static int stdio_get_fd(void* opaque)
+{
+    QEMUFileStdio *s = opaque;
+    return fileno(s->stdio_file);
+}
+
 static int stdio_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);
 }
 
@@ -226,6 +237,7 @@
     FILE *fp = s->stdio_file;
     int bytes;
 
+    fseek(s->stdio_file, pos, SEEK_SET);
     do {
         clearerr(fp);
         bytes = fread(buf, 1, size, fp);
@@ -250,6 +262,18 @@
     return 0;
 }
 
+static const QEMUFileOps stdio_pipe_read_ops = {
+    .get_fd =     stdio_get_fd,
+    .get_buffer = stdio_get_buffer,
+    .close =      stdio_pclose
+};
+
+static const QEMUFileOps stdio_pipe_write_ops = {
+    .get_fd =     stdio_get_fd,
+    .put_buffer = stdio_put_buffer,
+    .close =      stdio_pclose
+};
+
 QEMUFile *qemu_popen(FILE *stdio_file, const char *mode)
 {
     QEMUFileStdio *s;
@@ -264,11 +288,9 @@
     s->stdio_file = stdio_file;
 
     if(mode[0] == 'r') {
-        s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_pclose,
-				 NULL, NULL, NULL);
+        s->file = qemu_fopen_ops(s, &stdio_pipe_read_ops);
     } else {
-        s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_pclose,
-				 NULL, NULL, NULL);
+        s->file = qemu_fopen_ops(s, &stdio_pipe_write_ops);
     }
     return s->file;
 }
@@ -285,24 +307,33 @@
     return qemu_popen(popen_file, mode);
 }
 
-int qemu_stdio_fd(QEMUFile *f)
+int qemu_get_fd(QEMUFile *f)
 {
-    QEMUFileStdio *p;
-    int fd;
+    if (f->ops->get_fd)
+        return f->ops->get_fd(f->opaque);
 
-    p = (QEMUFileStdio *)f->opaque;
-    fd = fileno(p->stdio_file);
-
-    return fd;
+    return -1;
 }
 
+static const QEMUFileOps stdio_file_read_ops = {
+    .get_fd =     stdio_get_fd,
+    .get_buffer = stdio_get_buffer,
+    .close =      stdio_fclose
+};
+
+static const QEMUFileOps stdio_file_write_ops = {
+    .get_fd =     stdio_get_fd,
+    .put_buffer = stdio_put_buffer,
+    .close =      stdio_fclose
+};
+
 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) {
+        (mode[0] != 'r' && mode[0] != 'w') ||
+        mode[1] != 'b' || mode[2] != 0) {
         fprintf(stderr, "qemu_fdopen: Argument validity check failed\n");
         return NULL;
     }
@@ -313,11 +344,9 @@
         goto fail;
 
     if(mode[0] == 'r') {
-        s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_fclose,
-				 NULL, NULL, NULL);
+        s->file = qemu_fopen_ops(s, &stdio_file_read_ops);
     } else {
-        s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_fclose,
-				 NULL, NULL, NULL);
+        s->file = qemu_fopen_ops(s, &stdio_file_write_ops);
     }
     return s->file;
 
@@ -326,39 +355,47 @@
     return NULL;
 }
 
-QEMUFile *qemu_fopen_socket(int fd)
+static const QEMUFileOps socket_read_ops = {
+    .get_fd =     socket_get_fd,
+    .get_buffer = socket_get_buffer,
+    .close = file_socket_close
+};
+
+static const QEMUFileOps socket_write_ops = {
+    .get_fd =     socket_get_fd,
+    .close = file_socket_close
+};
+
+QEMUFile *qemu_fopen_socket(int fd, const char* mode)
 {
     QEMUFileSocket *s = g_malloc0(sizeof(QEMUFileSocket));
 
     s->fd = fd;
-    s->file = qemu_fopen_ops(s, NULL, socket_get_buffer, file_socket_close,
-			     NULL, NULL, NULL);
+    if (mode[0] == 'r')
+        s->file = qemu_fopen_ops(s, &socket_read_ops);
+    else
+        s->file = qemu_fopen_ops(s, &socket_write_ops);
+
     return s->file;
 }
 
-static int file_put_buffer(void *opaque, const uint8_t *buf,
-                            int64_t pos, int size)
+bool qemu_file_mode_is_not_valid(const char *mode)
 {
-    QEMUFileStdio *s = opaque;
-    fseek(s->stdio_file, pos, SEEK_SET);
-    return fwrite(buf, 1, size, s->stdio_file);
-}
+    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 true;
+    }
 
-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);
+    return false;
 }
 
 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");
+    if (qemu_file_mode_is_not_valid(mode)) {
         return NULL;
     }
 
@@ -369,11 +406,9 @@
         goto fail;
 
     if(mode[0] == 'w') {
-        s->file = qemu_fopen_ops(s, file_put_buffer, NULL, stdio_fclose,
-				 NULL, NULL, NULL);
+        s->file = qemu_fopen_ops(s, &stdio_file_write_ops);
     } else {
-        s->file = qemu_fopen_ops(s, NULL, file_get_buffer, stdio_fclose,
-			       NULL, NULL, NULL);
+        s->file = qemu_fopen_ops(s, &stdio_file_read_ops);
     }
     return s->file;
 fail:
@@ -398,33 +433,33 @@
     return 0;
 }
 
+static const QEMUFileOps bdrv_file_read_ops = {
+    .get_buffer = block_get_buffer,
+    .close = bdrv_fclose,
+};
+
+static const QEMUFileOps bdrv_file_write_opts = {
+    .put_buffer = block_put_buffer,
+    .close = bdrv_fclose,
+};
+
 static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable)
 {
     if (is_writable)
-        return qemu_fopen_ops(bs, block_put_buffer, NULL, bdrv_fclose,
-			      NULL, NULL, NULL);
-    return qemu_fopen_ops(bs, NULL, block_get_buffer, bdrv_fclose, NULL, NULL, NULL);
+        return qemu_fopen_ops(bs, &bdrv_file_write_opts);
+    else
+        return qemu_fopen_ops(bs, &bdrv_file_read_ops);
 }
 
-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 *qemu_fopen_ops(void *opaque, const QEMUFileOps* file_ops)
 {
     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;
+    f->ops = file_ops;
+    f->is_write = (file_ops->put_buffer != NULL);
 
     return f;
 }
@@ -441,13 +476,13 @@
 
 void qemu_fflush(QEMUFile *f)
 {
-    if (!f->put_buffer)
+    if (!f->ops->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);
+        len = f->ops->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index);
         if (len > 0)
             f->buf_offset += f->buf_index;
         else
@@ -460,13 +495,13 @@
 {
     int len;
 
-    if (!f->get_buffer)
+    if (!f->ops->get_buffer)
         return;
 
     if (f->is_write)
         abort();
 
-    len = f->get_buffer(f->opaque, f->buf, f->buf_offset, IO_BUF_SIZE);
+    len = f->ops->get_buffer(f->opaque, f->buf, f->buf_offset, IO_BUF_SIZE);
     if (len > 0) {
         f->buf_index = 0;
         f->buf_size = len;
@@ -479,15 +514,15 @@
 {
     int ret = 0;
     qemu_fflush(f);
-    if (f->close)
-        ret = f->close(f->opaque);
+    if (f->ops->close)
+        ret = f->ops->close(f->opaque);
     g_free(f);
     return ret;
 }
 
 void qemu_file_put_notify(QEMUFile *f)
 {
-    f->put_buffer(f->opaque, NULL, 0, 0);
+    f->ops->put_buffer(f->opaque, NULL, 0, 0);
 }
 
 void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
@@ -613,7 +648,7 @@
         /* SEEK_END not supported */
         return -1;
     }
-    if (f->put_buffer) {
+    if (f->ops->put_buffer) {
         qemu_fflush(f);
         f->buf_offset = pos;
     } else {
@@ -626,16 +661,16 @@
 
 int qemu_file_rate_limit(QEMUFile *f)
 {
-    if (f->rate_limit)
-        return f->rate_limit(f->opaque);
+    if (f->ops->rate_limit)
+        return f->ops->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);
+    if (f->ops->get_rate_limit)
+        return f->ops->get_rate_limit(f->opaque);
 
     return 0;
 }
@@ -644,8 +679,8 @@
 {
     /* 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);
+    if (f && f->ops->set_rate_limit)
+        return f->ops->set_rate_limit(f->opaque, new_rate);
 
     return 0;
 }