savevm.c revision dcda949f769a11b197f4784fe299a448d87e6e14
15d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
25d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * QEMU System Emulator
35d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
45d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Copyright (c) 2003-2008 Fabrice Bellard
55d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
65d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Permission is hereby granted, free of charge, to any person obtaining a copy
75d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * of this software and associated documentation files (the "Software"), to deal
85d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * in the Software without restriction, including without limitation the rights
95d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * copies of the Software, and to permit persons to whom the Software is
115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * furnished to do so, subject to the following conditions:
125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * The above copyright notice and this permission notice shall be included in
145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * all copies or substantial portions of the Software.
155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * THE SOFTWARE.
235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <unistd.h>
255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <fcntl.h>
265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <signal.h>
275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <time.h>
285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <errno.h>
295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/time.h>
305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <zlib.h>
315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
322c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner/* Needed early for CONFIG_BSD etc. */
335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "config-host.h"
345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef _WIN32
365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/times.h>
375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/wait.h>
385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <termios.h>
395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/mman.h>
405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/ioctl.h>
415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/resource.h>
425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/socket.h>
435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/in.h>
445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <net/if.h>
455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <arpa/inet.h>
465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <dirent.h>
475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netdb.h>
485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/select.h>
492c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#ifdef CONFIG_BSD
505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/stat.h>
51cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <libutil.h>
535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <util.h>
555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __linux__
575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <pty.h>
585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <malloc.h>
595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <linux/rtc.h>
605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32
655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <windows.h>
665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <malloc.h>
675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/timeb.h>
685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <mmsystem.h>
695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define getopt_long_only getopt_long
705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define memalign(align, size) malloc(size)
715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h"
745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "hw/hw.h"
75cc330d4169441727fecf1da08aee806fc021c4e2David 'Digit' Turner#include "net/net.h"
766af6765e2f3bc930d0dce21d752bea570a1b1362David 'Digit' Turner#include "monitor/monitor.h"
7734c48ff1e3ad5cd2084ca40188754d45f423750bDavid 'Digit' Turner#include "sysemu/sysemu.h"
78c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner#include "qemu/iov.h"
797a78db75ad42aea283f5073f51891464104a9fc3David 'Digit' Turner#include "qemu/timer.h"
80e7216d82dbaa19892ad62b07402d512234559a6eDavid 'Digit' Turner#include "sysemu/char.h"
8134c48ff1e3ad5cd2084ca40188754d45f423750bDavid 'Digit' Turner#include "sysemu/blockdev.h"
82e1e03df288d5a44bfbffbd86588395c7cbbc27dfDavid 'Digit' Turner#include "block/block.h"
835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "audio/audio.h"
8428a09b6fe8d8f3e92ffee9263609a6da881b8818David 'Digit' Turner#include "migration/migration.h"
85d0edecb426b34ddb9b10b81dea19aee04a61a385David 'Digit' Turner#include "qemu/sockets.h"
86031d655004e505a15e92580a16a181d1d247c4d5David 'Digit' Turner#include "qemu/queue.h"
8728a09b6fe8d8f3e92ffee9263609a6da881b8818David 'Digit' Turner#include "migration/qemu-file.h"
88622b8f4c760b8c4479d28430f978bad8bb9ea32cTim Baverstock#include "android/snapshot.h"
895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define SELF_ANNOUNCE_ROUNDS 5
92986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
93986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner#ifndef ETH_P_RARP
94986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner#define ETH_P_RARP 0x8035
95986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner#endif
96986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner#define ARP_HTYPE_ETH 0x0001
97986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner#define ARP_PTYPE_IP 0x0800
98986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner#define ARP_OP_REQUEST_REV 0x3
995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1005973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turnerstatic int announce_self_create(uint8_t *buf,
1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				uint8_t *mac_addr)
1025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
103986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    /* Ethernet header. */
104986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    memset(buf, 0xff, 6);         /* destination MAC addr */
105986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    memcpy(buf + 6, mac_addr, 6); /* source MAC addr */
106986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    *(uint16_t *)(buf + 12) = htons(ETH_P_RARP); /* ethertype */
107986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
108986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    /* RARP header. */
109986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    *(uint16_t *)(buf + 14) = htons(ARP_HTYPE_ETH); /* hardware addr space */
110986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    *(uint16_t *)(buf + 16) = htons(ARP_PTYPE_IP); /* protocol addr space */
111986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    *(buf + 18) = 6; /* hardware addr length (ethernet) */
112986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    *(buf + 19) = 4; /* protocol addr length (IPv4) */
113986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    *(uint16_t *)(buf + 20) = htons(ARP_OP_REQUEST_REV); /* opcode */
114986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    memcpy(buf + 22, mac_addr, 6); /* source hw addr */
115986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    memset(buf + 28, 0x00, 4);     /* source protocol addr */
116986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    memcpy(buf + 32, mac_addr, 6); /* target hw addr */
117986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    memset(buf + 38, 0x00, 4);     /* target protocol addr */
118986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
119986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    /* Padding to get up to 60 bytes (ethernet min packet size, minus FCS). */
120986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    memset(buf + 42, 0x00, 18);
121986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
122986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    return 60; /* len (FCS will be added by hardware) */
1235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void qemu_announce_self_once(void *opaque)
1265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int i, len;
1285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    VLANState *vlan;
1295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    VLANClientState *vc;
1305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t buf[256];
1315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    static int count = SELF_ANNOUNCE_ROUNDS;
1325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUTimer *timer = *(QEMUTimer **)opaque;
1335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (i = 0; i < MAX_NICS; i++) {
1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!nd_table[i].used)
1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            continue;
1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        len = announce_self_create(buf, nd_table[i].macaddr);
1385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        vlan = nd_table[i].vlan;
1395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            vc->receive(vc, buf, len);
1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
143986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    if (--count) {
144986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner        /* delay 50ms, 150ms, 250ms, ... */
145dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timer_mod(timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) +
146986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner                       50 + (SELF_ANNOUNCE_ROUNDS - count - 1) * 100);
1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
148dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner	    timer_del(timer);
149dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner	    timer_free(timer);
1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_announce_self(void)
1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	static QEMUTimer *timer;
156dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner	timer = timer_new_ms(QEMU_CLOCK_REALTIME, qemu_announce_self_once, &timer);
1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	qemu_announce_self_once(&timer);
1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/***********************************************************/
1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* savevm/loadvm support */
1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define IO_BUF_SIZE 32768
164c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner#define MAX_IOV_SIZE MIN(IOV_MAX, 64)
1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct QEMUFile {
167c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    const QEMUFileOps *ops;
1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    void *opaque;
1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
170c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    int64_t bytes_xfer;
171c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    int64_t xfer_limit;
172c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
173c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    int64_t pos; /* start of buffer when writing, end of buffer
174c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner                    when reading */
1755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int buf_index;
1765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int buf_size; /* 0 when writing */
1775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t buf[IO_BUF_SIZE];
1785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
179c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    struct iovec iov[MAX_IOV_SIZE];
180c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    unsigned int iovcnt;
181c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
182c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    int last_error;
1835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner};
1845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
185986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnertypedef struct QEMUFileStdio
1865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
187986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    FILE *stdio_file;
1885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFile *file;
189986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner} QEMUFileStdio;
1905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct QEMUFileSocket
1925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd;
1945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFile *file;
1955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} QEMUFileSocket;
1965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
197c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerstatic ssize_t socket_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
198c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner                                    int64_t pos)
199c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner{
200c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    QEMUFileSocket *s = opaque;
201c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    ssize_t len;
202c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    ssize_t size = iov_size(iov, iovcnt);
203c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
204c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    len = iov_send(s->fd, iov, iovcnt, 0, size);
205c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (len < size) {
206c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        len = -socket_error();
207c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
208c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return len;
209c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner}
210c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
2110e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turnerstatic int socket_get_fd(void *opaque)
2120e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner{
2130e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    QEMUFileSocket *s = opaque;
2140e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner
2150e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    return s->fd;
2160e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner}
2170e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner
218986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnerstatic int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
2195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFileSocket *s = opaque;
2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ssize_t len;
2225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
223c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    for (;;) {
224c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        len = qemu_recv(s->fd, buf, size, 0);
225c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (len != -1) {
226c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            break;
227c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
228c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner#ifndef CONFIG_ANDROID
229c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (socket_error() == EAGAIN) {
230c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            yield_until_fd_readable(s->fd);
231c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        } else if (socket_error() != EINTR) {
232c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            break;
233c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
234c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner#else
235c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner       if (socket_error() != EINTR)
236c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner           break;
237c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner#endif
238c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
2395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
240c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (len == -1) {
2415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        len = -socket_error();
242c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
2435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return len;
2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int file_socket_close(void *opaque)
2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFileSocket *s = opaque;
2490e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    if (s->fd >= 0)
2500e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        socket_close(s->fd);
251aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(s);
2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
255c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerstatic int stdio_get_fd(void *opaque)
2560e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner{
2570e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    QEMUFileStdio *s = opaque;
258c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
2590e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    return fileno(s->stdio_file);
2600e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner}
2610e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner
262986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnerstatic int stdio_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size)
2635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
264986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    QEMUFileStdio *s = opaque;
265986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    return fwrite(buf, 1, size, s->stdio_file);
2665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
268986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnerstatic int stdio_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
2695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
270986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    QEMUFileStdio *s = opaque;
271986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    FILE *fp = s->stdio_file;
2725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int bytes;
2735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
274c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    for (;;) {
2755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        clearerr(fp);
2765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bytes = fread(buf, 1, size, fp);
277c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (bytes != 0 || !ferror(fp)) {
278c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            break;
279c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
280c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner#ifndef CONFIG_ANDROID
281c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (errno == EAGAIN) {
282c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            yield_until_fd_readable(fileno(fp));
283c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        } else if (errno != EINTR) {
284c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            break;
285c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
286c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner#else
287c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (errno != EINTR)
288c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            break;
289c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner#endif
290c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
2915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return bytes;
2925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
294986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnerstatic int stdio_pclose(void *opaque)
2955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
296986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    QEMUFileStdio *s = opaque;
297986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    int ret;
298986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    ret = pclose(s->stdio_file);
299c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (ret == -1) {
300c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        ret = -errno;
301c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    } else if (!WIFEXITED(ret) || WEXITSTATUS(ret) != 0) {
302c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        /* close succeeded, but non-zero exit code: */
303c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        ret = -EIO; /* fake errno value */
304c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
305aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(s);
306986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    return ret;
307986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner}
308986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
309986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnerstatic int stdio_fclose(void *opaque)
310986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner{
311986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    QEMUFileStdio *s = opaque;
312c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    int ret = 0;
313c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
314c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (s->file->ops->put_buffer || s->file->ops->writev_buffer) {
315c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        int fd = fileno(s->stdio_file);
316c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        struct stat st;
317c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
318c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        ret = fstat(fd, &st);
319c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (ret == 0 && S_ISREG(st.st_mode)) {
320c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            /*
321c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner             * If the file handle is a regular file make sure the
322c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner             * data is flushed to disk before signaling success.
323c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner             */
324c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            ret = fsync(fd);
325c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            if (ret != 0) {
326c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner                ret = -errno;
327c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner                return ret;
328c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            }
329c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
330c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
331c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (fclose(s->stdio_file) == EOF) {
332c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        ret = -errno;
333c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
334aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(s);
335c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return ret;
3365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3380e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turnerstatic const QEMUFileOps stdio_pipe_read_ops = {
3390e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    .get_fd =     stdio_get_fd,
3400e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    .get_buffer = stdio_get_buffer,
3410e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    .close =      stdio_pclose
3420e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner};
3430e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner
3440e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turnerstatic const QEMUFileOps stdio_pipe_write_ops = {
3450e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    .get_fd =     stdio_get_fd,
3460e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    .put_buffer = stdio_put_buffer,
3470e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    .close =      stdio_pclose
3480e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner};
3490e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner
350c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' TurnerQEMUFile *qemu_popen_cmd(const char *command, const char *mode)
3515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
352c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    FILE *stdio_file;
353986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    QEMUFileStdio *s;
3545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
355c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) {
3565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "qemu_popen: Argument validity check failed\n");
3575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
3585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
3595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
360c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    stdio_file = popen(command, mode);
361c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (stdio_file == NULL) {
362c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        return NULL;
363c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
364c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
365aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    s = g_malloc0(sizeof(QEMUFileStdio));
3665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
367986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    s->stdio_file = stdio_file;
3685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if(mode[0] == 'r') {
3700e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        s->file = qemu_fopen_ops(s, &stdio_pipe_read_ops);
3715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
3720e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        s->file = qemu_fopen_ops(s, &stdio_pipe_write_ops);
3735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
3745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return s->file;
3755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
377c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerstatic const QEMUFileOps stdio_file_read_ops = {
378c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    .get_fd =     stdio_get_fd,
379c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    .get_buffer = stdio_get_buffer,
380c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    .close =      stdio_fclose
381c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner};
382c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
383c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerstatic const QEMUFileOps stdio_file_write_ops = {
384c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    .get_fd =     stdio_get_fd,
385c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    .put_buffer = stdio_put_buffer,
386c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    .close =      stdio_fclose
387c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner};
388c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
389c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerstatic ssize_t unix_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
390c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner                                  int64_t pos)
3915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
392c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    QEMUFileSocket *s = opaque;
393c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    ssize_t len, offset;
394c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    ssize_t size = iov_size(iov, iovcnt);
395c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    ssize_t total = 0;
3965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
397c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    assert(iovcnt > 0);
398c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    offset = 0;
399c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    while (size > 0) {
400c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        /* Find the next start position; skip all full-sized vector elements  */
401c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        while (offset >= iov[0].iov_len) {
402c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            offset -= iov[0].iov_len;
403c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            iov++, iovcnt--;
404c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
405c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
406c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        /* skip `offset' bytes from the (now) first element, undo it on exit */
407c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        assert(iovcnt > 0);
408c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        iov[0].iov_base += offset;
409c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        iov[0].iov_len -= offset;
410c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
411c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        do {
412c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            len = writev(s->fd, iov, iovcnt);
413c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        } while (len == -1 && errno == EINTR);
414c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (len == -1) {
415c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            return -errno;
416c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
417c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
418c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        /* Undo the changes above */
419c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        iov[0].iov_base -= offset;
420c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        iov[0].iov_len += offset;
421c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
422c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        /* Prepare for the next iteration */
423c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        offset += len;
424c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        total += len;
425c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        size -= len;
4265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
4275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
428c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return total;
4295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
431c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerstatic int unix_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
4325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
433c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    QEMUFileSocket *s = opaque;
434c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    ssize_t len;
4355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
436c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    for (;;) {
437c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        len = read(s->fd, buf, size);
438c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (len != -1) {
439c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            break;
440c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
441c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (errno == EAGAIN) {
442c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            yield_until_fd_readable(s->fd);
443c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        } else if (errno != EINTR) {
444c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            break;
445c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
446c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
447c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
448c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (len == -1) {
449c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        len = -errno;
450c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
451c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return len;
4525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
454c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerstatic int unix_close(void *opaque)
455c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner{
456c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    QEMUFileSocket *s = opaque;
457c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    close(s->fd);
458c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    g_free(s);
459c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return 0;
460c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner}
461c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
462c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerstatic const QEMUFileOps unix_read_ops = {
463c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    .get_fd =     socket_get_fd,
464c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    .get_buffer = unix_get_buffer,
465c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    .close =      unix_close
4660e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner};
4670e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner
468c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerstatic const QEMUFileOps unix_write_ops = {
469c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    .get_fd =     socket_get_fd,
470c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    .writev_buffer = unix_writev_buffer,
471c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    .close =      unix_close
4720e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner};
4730e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner
474986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' TurnerQEMUFile *qemu_fdopen(int fd, const char *mode)
475986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner{
476c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    QEMUFileSocket *s;
477986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
478986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    if (mode == NULL ||
479c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner	(mode[0] != 'r' && mode[0] != 'w') ||
480c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner	mode[1] != 'b' || mode[2] != 0) {
481986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner        fprintf(stderr, "qemu_fdopen: Argument validity check failed\n");
482986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner        return NULL;
483986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    }
484986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
485c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    s = g_malloc0(sizeof(QEMUFileSocket));
486c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    s->fd = fd;
487986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
488986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    if(mode[0] == 'r') {
489c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        s->file = qemu_fopen_ops(s, &unix_read_ops);
490986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    } else {
491c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        s->file = qemu_fopen_ops(s, &unix_write_ops);
492986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    }
493986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    return s->file;
494986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner}
495986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
4960e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turnerstatic const QEMUFileOps socket_read_ops = {
4970e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    .get_fd =     socket_get_fd,
4980e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    .get_buffer = socket_get_buffer,
4990e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    .close = file_socket_close
5000e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner};
5010e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner
5020e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turnerstatic const QEMUFileOps socket_write_ops = {
5030e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    .get_fd =     socket_get_fd,
504c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    .writev_buffer = socket_writev_buffer,
5050e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    .close = file_socket_close
5060e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner};
5070e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner
5080e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turnerbool qemu_file_mode_is_not_valid(const char *mode)
5095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5100e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    if (mode == NULL ||
5110e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        (mode[0] != 'r' && mode[0] != 'w') ||
5120e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        mode[1] != 'b' || mode[2] != 0) {
5130e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        fprintf(stderr, "qemu_fopen: Argument validity check failed\n");
5140e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        return true;
5150e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    }
5165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5170e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    return false;
5185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
520c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' TurnerQEMUFile *qemu_fopen_socket(int fd, const char *mode)
521c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner{
522c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    QEMUFileSocket *s;
523c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
524c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (qemu_file_mode_is_not_valid(mode)) {
525c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        return NULL;
526c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
527c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
528c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    s = g_malloc0(sizeof(QEMUFileSocket));
529c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    s->fd = fd;
530c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (mode[0] == 'w') {
531c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        qemu_set_block(s->fd);
532c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        s->file = qemu_fopen_ops(s, &socket_write_ops);
533c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    } else {
534c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        s->file = qemu_fopen_ops(s, &socket_read_ops);
535c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
536c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return s->file;
537c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner}
538c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
5395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerQEMUFile *qemu_fopen(const char *filename, const char *mode)
5405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFileStdio *s;
5425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5430e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    if (qemu_file_mode_is_not_valid(mode)) {
544986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner        return NULL;
545986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    }
546986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
547aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    s = g_malloc0(sizeof(QEMUFileStdio));
5485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
549986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    s->stdio_file = fopen(filename, mode);
550986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    if (!s->stdio_file)
5515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto fail;
552c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
553986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    if(mode[0] == 'w') {
5540e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        s->file = qemu_fopen_ops(s, &stdio_file_write_ops);
555986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    } else {
5560e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner        s->file = qemu_fopen_ops(s, &stdio_file_read_ops);
557986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    }
558986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    return s->file;
5595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerfail:
560aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(s);
5615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return NULL;
5625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
564c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner#ifndef CONFIG_ANDROID
565c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner// TODO(digit): Once bdrv_writev_vmstate() is implemented.
566c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerstatic ssize_t block_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
567c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner                                   int64_t pos)
568c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner{
569c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    int ret;
570c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    QEMUIOVector qiov;
571c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
572c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    qemu_iovec_init_external(&qiov, iov, iovcnt);
573c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    ret = bdrv_writev_vmstate(opaque, &qiov, pos);
574c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (ret < 0) {
575c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        return ret;
576c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
577c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
578c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return qiov.size;
579c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner}
580c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner#endif
581c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
5825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int block_put_buffer(void *opaque, const uint8_t *buf,
5835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                           int64_t pos, int size)
5845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
585986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    bdrv_save_vmstate(opaque, buf, pos, size);
5865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return size;
5875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int block_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
5905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
591986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    return bdrv_load_vmstate(opaque, buf, pos, size);
5925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bdrv_fclose(void *opaque)
5955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
596c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    // TODO(digit): bdrv_flush() should return error code.
597c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    bdrv_flush(opaque);
5985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
5995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
601c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerstatic const QEMUFileOps bdrv_read_ops = {
6020e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner    .get_buffer = block_get_buffer,
603c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    .close =      bdrv_fclose
6040e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner};
6050e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner
606c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerstatic const QEMUFileOps bdrv_write_ops = {
607c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    .put_buffer     = block_put_buffer,
608c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    //.writev_buffer  = block_writev_buffer,
609c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    .close          = bdrv_fclose
6100e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner};
6110e0515410009c5bdd4d2d77a4a9131081573f040David 'Digit' Turner
612986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnerstatic QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable)
6135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (is_writable)
615c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        return qemu_fopen_ops(bs, &bdrv_write_ops);
616c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return qemu_fopen_ops(bs, &bdrv_read_ops);
6175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
619c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' TurnerQEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops)
6205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFile *f;
6225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
623aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    f = g_malloc0(sizeof(QEMUFile));
6245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    f->opaque = opaque;
626c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    f->ops = ops;
6275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return f;
6285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
630c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner/*
631c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner * Get last error for stream f
632c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner *
633c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner * Return negative error value if there has been an error on previous
634c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner * operations, return 0 if no error happened.
635c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner *
636c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner */
637c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerint qemu_file_get_error(QEMUFile *f)
638c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner{
639c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return f->last_error;
640c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner}
641c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
642c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnervoid qemu_file_set_error(QEMUFile *f, int ret)
6435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
644c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (f->last_error == 0) {
645c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        f->last_error = ret;
646c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
6475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
649c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerstatic inline bool qemu_file_is_writable(QEMUFile *f)
6505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
651c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return f->ops->writev_buffer || f->ops->put_buffer;
6525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
654c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner/**
655c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner * Flushes QEMUFile buffer
656c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner *
657c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner * If there is writev_buffer QEMUFileOps it uses it otherwise uses
658c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner * put_buffer ops.
659c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner */
6605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_fflush(QEMUFile *f)
6615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
662c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    ssize_t ret = 0;
663c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
664c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (!qemu_file_is_writable(f)) {
6655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
666c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
6675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
668c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (f->ops->writev_buffer) {
669c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (f->iovcnt > 0) {
670c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            ret = f->ops->writev_buffer(f->opaque, f->iov, f->iovcnt, f->pos);
671c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
672c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    } else {
673c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (f->buf_index > 0) {
674c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            ret = f->ops->put_buffer(f->opaque, f->buf, f->pos, f->buf_index);
675c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
676c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
677c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (ret >= 0) {
678c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        f->pos += ret;
679c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
680c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    f->buf_index = 0;
681c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    f->iovcnt = 0;
682c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (ret < 0) {
683c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        qemu_file_set_error(f, ret);
684c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
685c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner}
686c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
687c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner#ifndef CONFIG_ANDROID
688c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner// TODO(digit).
689c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnervoid ram_control_before_iterate(QEMUFile *f, uint64_t flags)
690c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner{
691c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    int ret = 0;
692c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
693c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (f->ops->before_ram_iterate) {
694c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        ret = f->ops->before_ram_iterate(f, f->opaque, flags);
695c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (ret < 0) {
696c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            qemu_file_set_error(f, ret);
697c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
698c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
699c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner}
700c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
701c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnervoid ram_control_after_iterate(QEMUFile *f, uint64_t flags)
702c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner{
703c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    int ret = 0;
704c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
705c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (f->ops->after_ram_iterate) {
706c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        ret = f->ops->after_ram_iterate(f, f->opaque, flags);
707c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (ret < 0) {
708c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            qemu_file_set_error(f, ret);
709c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
710c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
711c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner}
712c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
713c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnervoid ram_control_load_hook(QEMUFile *f, uint64_t flags)
714c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner{
715c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    int ret = -EINVAL;
716c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
717c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (f->ops->hook_ram_load) {
718c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        ret = f->ops->hook_ram_load(f, f->opaque, flags);
719c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (ret < 0) {
720c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            qemu_file_set_error(f, ret);
721c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
722c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    } else {
723c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        qemu_file_set_error(f, ret);
724c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
725c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner}
726c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
727c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnersize_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
728c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner                         ram_addr_t offset, size_t size, int *bytes_sent)
729c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner{
730c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (f->ops->save_page) {
731c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        int ret = f->ops->save_page(f, f->opaque, block_offset,
732c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner                                    offset, size, bytes_sent);
733c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
734c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (ret != RAM_SAVE_CONTROL_DELAYED) {
735c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            if (bytes_sent && *bytes_sent > 0) {
736c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner                qemu_update_position(f, *bytes_sent);
737c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            } else if (ret < 0) {
738c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner                qemu_file_set_error(f, ret);
739c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            }
740c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
7415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
742c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        return ret;
7435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
744c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
745c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return RAM_SAVE_CONTROL_NOT_SUPP;
7465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
747c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner#endif  // !CONFIG_ANDROID
7485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void qemu_fill_buffer(QEMUFile *f)
7505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int len;
752c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    int pending;
7535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
754c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    assert(!qemu_file_is_writable(f));
7555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
756c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    pending = f->buf_size - f->buf_index;
757c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (pending > 0) {
758c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        memmove(f->buf, f->buf + f->buf_index, pending);
759c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
760c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    f->buf_index = 0;
761c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    f->buf_size = pending;
7625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
763c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    len = f->ops->get_buffer(f->opaque, f->buf + pending, f->pos,
764c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner                        IO_BUF_SIZE - pending);
7655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (len > 0) {
766c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        f->buf_size += len;
767c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        f->pos += len;
768c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    } else if (len == 0) {
769c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        qemu_file_set_error(f, -EIO);
7705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (len != -EAGAIN)
771c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        qemu_file_set_error(f, len);
7725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
7735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
774c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerint qemu_get_fd(QEMUFile *f)
775c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner{
776c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (f->ops->get_fd) {
777c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        return f->ops->get_fd(f->opaque);
778c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
779c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return -1;
780c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner}
781c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
782c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnervoid qemu_update_position(QEMUFile *f, size_t size)
783c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner{
784c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    f->pos += size;
785c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner}
786c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
787c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner/** Closes the file
788c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner *
789c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner * Returns negative error value if any error happened on previous operations or
790c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner * while closing the file. Returns 0 or positive number on success.
791c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner *
792c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner * The meaning of return value on success depends on the specific backend
793c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner * being used.
794c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner */
7955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_fclose(QEMUFile *f)
7965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
797c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    int ret;
7985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_fflush(f);
799c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    ret = qemu_file_get_error(f);
800c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
801c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (f->ops->close) {
802c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        int ret2 = f->ops->close(f->opaque);
803c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (ret >= 0) {
804c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            ret = ret2;
805c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
806c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
807c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    /* If any error was spotted before closing, we should report it
808c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner     * instead of the close() return value.
809c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner     */
810c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (f->last_error) {
811c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        ret = f->last_error;
812c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
813aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(f);
8145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
8155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
817c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerstatic void add_to_iovec(QEMUFile *f, const uint8_t *buf, int size)
8185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
819c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    /* check for adjacent buffer and coalesce them */
820c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (f->iovcnt > 0 && buf == f->iov[f->iovcnt - 1].iov_base +
821c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        f->iov[f->iovcnt - 1].iov_len) {
822c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        f->iov[f->iovcnt - 1].iov_len += size;
823c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    } else {
824c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        f->iov[f->iovcnt].iov_base = (uint8_t *)buf;
825c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        f->iov[f->iovcnt++].iov_len = size;
826c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
827c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
828c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (f->iovcnt >= MAX_IOV_SIZE) {
829c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        qemu_fflush(f);
830c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
831c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner}
832c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
833c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnervoid qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, int size)
834c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner{
835c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (!f->ops->writev_buffer) {
836c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        qemu_put_buffer(f, buf, size);
837c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        return;
838c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
839c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
840c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (f->last_error) {
841c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        return;
842c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
843c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
844c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    f->bytes_xfer += size;
845c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    add_to_iovec(f, buf, size);
8465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
8495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int l;
8515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
852c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (f->last_error) {
853c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        return;
8545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
856c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    while (size > 0) {
8575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        l = IO_BUF_SIZE - f->buf_index;
8585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (l > size)
8595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            l = size;
8605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        memcpy(f->buf + f->buf_index, buf, l);
861c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        f->bytes_xfer += l;
862c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (f->ops->writev_buffer) {
863c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            add_to_iovec(f, f->buf + f->buf_index, l);
864c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
8655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        f->buf_index += l;
866c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (f->buf_index == IO_BUF_SIZE) {
867c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            qemu_fflush(f);
868c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
869c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (qemu_file_get_error(f)) {
870c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            break;
871c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
8725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        buf += l;
8735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        size -= l;
8745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_put_byte(QEMUFile *f, int v)
8785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
879c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (f->last_error) {
880c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        return;
8815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
883c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    f->buf[f->buf_index] = v;
884c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    f->bytes_xfer++;
885c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (f->ops->writev_buffer) {
886c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        add_to_iovec(f, f->buf + f->buf_index, 1);
887c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
888c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    f->buf_index++;
889c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (f->buf_index == IO_BUF_SIZE) {
8905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_fflush(f);
891c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
8925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
894c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerstatic void qemu_file_skip(QEMUFile *f, int size)
8955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
896c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (f->buf_index + size <= f->buf_size) {
897c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        f->buf_index += size;
898c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
899c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner}
9005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
901c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerstatic int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset)
902c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner{
903c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    int pending;
904c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    int index;
9055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
906c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    assert(!qemu_file_is_writable(f));
907c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
908c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    index = f->buf_index + offset;
909c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    pending = f->buf_size - index;
910c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (pending < size) {
911c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        qemu_fill_buffer(f);
912c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        index = f->buf_index + offset;
913c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        pending = f->buf_size - index;
914c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
915c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
916c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (pending <= 0) {
917c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        return 0;
918c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
919c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (size > pending) {
920c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        size = pending;
921c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    }
922c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
923c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    memcpy(buf, f->buf + index, size);
924c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return size;
925c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner}
926c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
927c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerint qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
928c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner{
929c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    int pending = size;
930c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    int done = 0;
931c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
932c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    while (pending > 0) {
933c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        int res;
934c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
935c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        res = qemu_peek_buffer(f, buf, pending, 0);
936c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (res == 0) {
937c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner            return done;
9385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
939c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        qemu_file_skip(f, res);
940c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        buf += res;
941c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        pending -= res;
942c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        done += res;
9435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
944c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return done;
9455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
9465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
947c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerstatic int qemu_peek_byte(QEMUFile *f, int offset)
9485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
949c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    int index = f->buf_index + offset;
950c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
951c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    assert(!qemu_file_is_writable(f));
9525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
953c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (index >= f->buf_size) {
9545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_fill_buffer(f);
955c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        index = f->buf_index + offset;
956c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        if (index >= f->buf_size) {
9575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return 0;
958c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        }
9595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
960c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return f->buf[index];
961c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner}
962c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
963c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerint qemu_get_byte(QEMUFile *f)
964c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner{
965c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    int result;
966c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner
967c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    result = qemu_peek_byte(f, 0);
968c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    qemu_file_skip(f, 1);
969c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return result;
9705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
9715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9723e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner#ifdef CONFIG_ANDROID
9733e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turnervoid qemu_put_string(QEMUFile *f, const char* str)
9743e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner{
9753e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    /* We will encode NULL and the empty string in the same way */
9763e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    int  slen;
9773e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    if (str == NULL) {
9783e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner        str = "";
9793e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    }
9803e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    slen = strlen(str);
9813e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    qemu_put_be32(f, slen);
9823e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    qemu_put_buffer(f, (const uint8_t*)str, slen);
9833e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner}
9843e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner
9853e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turnerchar* qemu_get_string(QEMUFile *f)
9863e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner{
9873e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    int slen = qemu_get_be32(f);
9883e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    char* str;
9893e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    if (slen == 0)
9903e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner        return NULL;
9913e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner
992aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    str = g_malloc(slen+1);
9933e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    if (qemu_get_buffer(f, (uint8_t*)str, slen) != slen) {
994aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner        g_free(str);
9953e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner        return NULL;
9963e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    }
9973e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    str[slen] = '\0';
9983e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    return str;
9993e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner}
10003e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner#endif
10013e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner
10023e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner
10035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint64_t qemu_ftell(QEMUFile *f)
10045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1005c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    qemu_fflush(f);
1006c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return f->pos;
10075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1009c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnerint qemu_file_rate_limit(QEMUFile *f)
10105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1011c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (qemu_file_get_error(f)) {
1012c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        return 1;
10135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
1014c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (f->xfer_limit > 0 && f->bytes_xfer > f->xfer_limit) {
1015c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        return 1;
10165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
10175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
10185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1020986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnerint64_t qemu_file_get_rate_limit(QEMUFile *f)
1021986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner{
1022c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return f->xfer_limit;
1023986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner}
1024986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
1025c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnervoid qemu_file_set_rate_limit(QEMUFile *f, int64_t limit)
10265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1027c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    f->xfer_limit = limit;
1028c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner}
10295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1030c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turnervoid qemu_file_reset_rate_limit(QEMUFile *f)
1031c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner{
1032c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    f->bytes_xfer = 0;
10335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_put_be16(QEMUFile *f, unsigned int v)
10365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_byte(f, v >> 8);
10385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_byte(f, v);
10395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_put_be32(QEMUFile *f, unsigned int v)
10425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_byte(f, v >> 24);
10445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_byte(f, v >> 16);
10455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_byte(f, v >> 8);
10465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_byte(f, v);
10475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_put_be64(QEMUFile *f, uint64_t v)
10505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_be32(f, v >> 32);
10525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_be32(f, v);
10535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerunsigned int qemu_get_be16(QEMUFile *f)
10565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    unsigned int v;
10585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v = qemu_get_byte(f) << 8;
10595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v |= qemu_get_byte(f);
10605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return v;
10615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerunsigned int qemu_get_be32(QEMUFile *f)
10645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    unsigned int v;
10665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v = qemu_get_byte(f) << 24;
10675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v |= qemu_get_byte(f) << 16;
10685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v |= qemu_get_byte(f) << 8;
10695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v |= qemu_get_byte(f);
10705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return v;
10715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneruint64_t qemu_get_be64(QEMUFile *f)
10745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint64_t v;
10765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v = (uint64_t)qemu_get_be32(f) << 32;
10775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v |= qemu_get_be32(f);
10785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return v;
10795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1081dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
1082dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner/* timer */
1083dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
1084dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid timer_put(QEMUFile *f, QEMUTimer *ts)
1085dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
1086dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    uint64_t expire_time;
1087dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
1088dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    expire_time = timer_expire_time_ns(ts);
1089dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    qemu_put_be64(f, expire_time);
1090dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
1091dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
1092dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turnervoid timer_get(QEMUFile *f, QEMUTimer *ts)
1093dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner{
1094dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    uint64_t expire_time;
1095dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
1096dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    expire_time = qemu_get_be64(f);
1097dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    if (expire_time != -1) {
1098dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timer_mod_ns(ts, expire_time);
1099dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    } else {
1100dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner        timer_del(ts);
1101dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    }
1102dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner}
1103dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner
11045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid  qemu_put_struct(QEMUFile*  f, const QField*  fields, const void*  s)
11055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    const QField*  qf = fields;
11075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11087fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije    /* Iterate over struct fields */
11097fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije    while (qf->type != Q_FIELD_END) {
11105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t*  p = (uint8_t*)s + qf->offset;
11115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        switch (qf->type) {
11135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_BYTE:
11145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                qemu_put_byte(f, p[0]);
11155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
11165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_INT16:
11175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                qemu_put_be16(f, ((uint16_t*)p)[0]);
11185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
11195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_INT32:
11205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                qemu_put_be32(f, ((uint32_t*)p)[0]);
11215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
11225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_INT64:
11235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                qemu_put_be64(f, ((uint64_t*)p)[0]);
11245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
11255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_BUFFER:
11267fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije                if (qf[1].type != Q_FIELD_BUFFER_SIZE ||
11277fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije                    qf[2].type != Q_FIELD_BUFFER_SIZE)
11285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                {
11295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    fprintf(stderr, "%s: invalid QFIELD_BUFFER item passed as argument. aborting\n",
11305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            __FUNCTION__ );
11315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    exit(1);
11325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
11335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                else
11345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                {
11357fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije                    uint32_t  size = ((uint32_t)qf[1].offset << 16) | (uint32_t)qf[2].offset;
11365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    qemu_put_buffer(f, p, size);
11385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    qf += 2;
11395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
11405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
11415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            default:
11425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                fprintf(stderr, "%s: invalid fields list passed as argument. aborting\n", __FUNCTION__);
11435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                exit(1);
11445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
11455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qf++;
11465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
11475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint   qemu_get_struct(QEMUFile*  f, const QField*  fields, void*  s)
11505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    const QField*  qf = fields;
11525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11537fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije    /* Iterate over struct fields */
11547fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije    while (qf->type != Q_FIELD_END) {
11555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t*  p = (uint8_t*)s + qf->offset;
11565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        switch (qf->type) {
11585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_BYTE:
11595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                p[0] = qemu_get_byte(f);
11605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
11615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_INT16:
11625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ((uint16_t*)p)[0] = qemu_get_be16(f);
11635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
11645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_INT32:
11655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ((uint32_t*)p)[0] = qemu_get_be32(f);
11665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
11675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_INT64:
11685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ((uint64_t*)p)[0] = qemu_get_be64(f);
11695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
11705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_BUFFER:
11717fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije                if (qf[1].type != Q_FIELD_BUFFER_SIZE ||
11727fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije                        qf[2].type != Q_FIELD_BUFFER_SIZE)
11735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                {
11745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    fprintf(stderr, "%s: invalid QFIELD_BUFFER item passed as argument.\n",
11755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            __FUNCTION__ );
11765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    return -1;
11775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
11785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                else
11795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                {
11807fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije                    uint32_t  size = ((uint32_t)qf[1].offset << 16) | (uint32_t)qf[2].offset;
11815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    int       ret  = qemu_get_buffer(f, p, size);
11825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    if (ret != size) {
11845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        fprintf(stderr, "%s: not enough bytes to load structure\n", __FUNCTION__);
11855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        return -1;
11865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    }
11875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    qf += 2;
11885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
11895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
11905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            default:
11915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                fprintf(stderr, "%s: invalid fields list passed as argument. aborting\n", __FUNCTION__);
11925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                exit(1);
11935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
11945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qf++;
11955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
11965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
11975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1199871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije/* write a float to file */
1200871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thijevoid qemu_put_float(QEMUFile *f, float v)
1201871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije{
1202871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije    uint8_t *bytes = (uint8_t*) &v;
1203871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije    qemu_put_buffer(f, bytes, sizeof(float));
1204871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije}
1205871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije
1206871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije/* read a float from file */
1207871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thijefloat qemu_get_float(QEMUFile *f)
1208871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije{
1209871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije    uint8_t bytes[sizeof(float)];
1210871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije    qemu_get_buffer(f, bytes, sizeof(float));
1211871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije
1212871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije    return *((float*) bytes);
1213871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije}
1214871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije
12155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct SaveStateEntry {
12165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char idstr[256];
12175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int instance_id;
12185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int version_id;
12195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int section_id;
12205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveLiveStateHandler *save_live_state;
12215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveStateHandler *save_state;
12225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    LoadStateHandler *load_state;
12235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    void *opaque;
12245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct SaveStateEntry *next;
12255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} SaveStateEntry;
12265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic SaveStateEntry *first_se;
12285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* TODO: Individual devices generally have very little idea about the rest
12305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   of the system, so instance_id should be removed/replaced.
12315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   Meanwhile pass -1 as instance_id if you do not already have a clearly
12325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   distinguishing id for all instances of your device class. */
12335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint register_savevm_live(const char *idstr,
12345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         int instance_id,
12355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         int version_id,
12365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         SaveLiveStateHandler *save_live_state,
12375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         SaveStateHandler *save_state,
12385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         LoadStateHandler *load_state,
12395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         void *opaque)
12405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
12415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveStateEntry *se, **pse;
12425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    static int global_section_id;
12435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1244aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    se = g_malloc(sizeof(SaveStateEntry));
12455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    pstrcpy(se->idstr, sizeof(se->idstr), idstr);
12465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    se->instance_id = (instance_id == -1) ? 0 : instance_id;
12475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    se->version_id = version_id;
12485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    se->section_id = global_section_id++;
12495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    se->save_live_state = save_live_state;
12505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    se->save_state = save_state;
12515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    se->load_state = load_state;
12525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    se->opaque = opaque;
12535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    se->next = NULL;
12545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* add at the end of list */
12565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    pse = &first_se;
12575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (*pse != NULL) {
12585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (instance_id == -1
12595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                && strcmp(se->idstr, (*pse)->idstr) == 0
12605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                && se->instance_id <= (*pse)->instance_id)
12615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            se->instance_id = (*pse)->instance_id + 1;
12625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        pse = &(*pse)->next;
12635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
12645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    *pse = se;
12655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
12665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
12675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint register_savevm(const char *idstr,
12695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    int instance_id,
12705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    int version_id,
12715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    SaveStateHandler *save_state,
12725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    LoadStateHandler *load_state,
12735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    void *opaque)
12745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
12755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return register_savevm_live(idstr, instance_id, version_id,
12765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                NULL, save_state, load_state, opaque);
12775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
12785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid unregister_savevm(const char *idstr, void *opaque)
12805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
12815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveStateEntry **pse;
12825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    pse = &first_se;
12845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (*pse != NULL) {
12855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (strcmp((*pse)->idstr, idstr) == 0 && (*pse)->opaque == opaque) {
12865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            SaveStateEntry *next = (*pse)->next;
1287aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner            g_free(*pse);
12885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *pse = next;
12895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            continue;
12905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
12915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        pse = &(*pse)->next;
12925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
12935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
12945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define QEMU_VM_FILE_MAGIC           0x5145564d
12965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define QEMU_VM_FILE_VERSION_COMPAT  0x00000002
12973e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner#define QEMU_VM_FILE_VERSION         0x00000004
12985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define QEMU_VM_EOF                  0x00
13005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define QEMU_VM_SECTION_START        0x01
13015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define QEMU_VM_SECTION_PART         0x02
13025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define QEMU_VM_SECTION_END          0x03
13035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define QEMU_VM_SECTION_FULL         0x04
13045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_savevm_state_begin(QEMUFile *f)
13065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveStateEntry *se;
13085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
13105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_be32(f, QEMU_VM_FILE_VERSION);
13115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (se = first_se; se != NULL; se = se->next) {
13135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int len;
13145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (se->save_live_state == NULL)
13165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            continue;
13175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Section type */
13195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_byte(f, QEMU_VM_SECTION_START);
13205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_be32(f, se->section_id);
13215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* ID string */
13235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        len = strlen(se->idstr);
13245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_byte(f, len);
13255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_buffer(f, (uint8_t *)se->idstr, len);
13265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_be32(f, se->instance_id);
13285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_be32(f, se->version_id);
13295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        se->save_live_state(f, QEMU_VM_SECTION_START, se->opaque);
13315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
13325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1333c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return qemu_file_get_error(f);
13345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_savevm_state_iterate(QEMUFile *f)
13375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveStateEntry *se;
13395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret = 1;
13405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (se = first_se; se != NULL; se = se->next) {
13425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (se->save_live_state == NULL)
13435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            continue;
13445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Section type */
13465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_byte(f, QEMU_VM_SECTION_PART);
13475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_be32(f, se->section_id);
13485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret &= !!se->save_live_state(f, QEMU_VM_SECTION_PART, se->opaque);
13505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
13515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ret)
13535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 1;
13545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1355c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return qemu_file_get_error(f);
13565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_savevm_state_complete(QEMUFile *f)
13595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveStateEntry *se;
13615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (se = first_se; se != NULL; se = se->next) {
13635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (se->save_live_state == NULL)
13645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            continue;
13655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Section type */
13675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_byte(f, QEMU_VM_SECTION_END);
13685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_be32(f, se->section_id);
13695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        se->save_live_state(f, QEMU_VM_SECTION_END, se->opaque);
13715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
13725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for(se = first_se; se != NULL; se = se->next) {
13745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int len;
13755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13768f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thije        if (se->save_state == NULL)
13778f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thije            continue;
13785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Section type */
13805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_byte(f, QEMU_VM_SECTION_FULL);
13815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_be32(f, se->section_id);
13825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* ID string */
13845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        len = strlen(se->idstr);
13855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_byte(f, len);
13865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_buffer(f, (uint8_t *)se->idstr, len);
13875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_be32(f, se->instance_id);
13895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_be32(f, se->version_id);
13905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        se->save_state(f, se->opaque);
13925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
13935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_byte(f, QEMU_VM_EOF);
13955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1396c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return qemu_file_get_error(f);
13975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_savevm_state(QEMUFile *f)
14005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
14015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int saved_vm_running;
14025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret;
14035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    saved_vm_running = vm_running;
14055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    vm_stop(0);
14065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bdrv_flush_all();
14085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = qemu_savevm_state_begin(f);
14105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ret < 0)
14115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto out;
14125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    do {
14145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = qemu_savevm_state_iterate(f);
14155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret < 0)
14165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto out;
14175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } while (ret == 0);
14185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = qemu_savevm_state_complete(f);
14205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerout:
1422c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    ret = qemu_file_get_error(f);
14235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!ret && saved_vm_running)
14255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        vm_start();
14265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
14285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic SaveStateEntry *find_se(const char *idstr, int instance_id)
14315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
14325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveStateEntry *se;
14335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for(se = first_se; se != NULL; se = se->next) {
14355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!strcmp(se->idstr, idstr) &&
14365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            instance_id == se->instance_id)
14375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return se;
14385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
14395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return NULL;
14405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct LoadStateEntry {
14435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveStateEntry *se;
14445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int section_id;
14455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int version_id;
14465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct LoadStateEntry *next;
14475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} LoadStateEntry;
14485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int qemu_loadvm_state_v2(QEMUFile *f)
14505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
14515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveStateEntry *se;
14525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int len, ret, instance_id, record_len, version_id;
14535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int64_t total_len, end_pos, cur_pos;
14545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char idstr[256];
14555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    total_len = qemu_get_be64(f);
14575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    end_pos = total_len + qemu_ftell(f);
14585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for(;;) {
14595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (qemu_ftell(f) >= end_pos)
14605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
14615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        len = qemu_get_byte(f);
14625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_get_buffer(f, (uint8_t *)idstr, len);
14635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        idstr[len] = '\0';
14645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        instance_id = qemu_get_be32(f);
14655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        version_id = qemu_get_be32(f);
14665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        record_len = qemu_get_be32(f);
14675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        cur_pos = qemu_ftell(f);
14685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        se = find_se(idstr, instance_id);
14695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!se) {
14705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            fprintf(stderr, "qemu: warning: instance 0x%x of device '%s' not present in current VM\n",
14715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    instance_id, idstr);
14725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
14735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret = se->load_state(f, se->opaque, version_id);
14745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (ret < 0) {
14755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n",
14765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        instance_id, idstr);
14775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return ret;
14785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
14795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
14805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* always seek to exact end of record */
1481c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner        qemu_file_skip(f, cur_pos + record_len - qemu_ftell(f));
14825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
14835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1484c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    return qemu_file_get_error(f);
14855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_loadvm_state(QEMUFile *f)
14885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
14895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    LoadStateEntry *first_le = NULL;
14905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t section_type;
14915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    unsigned int v;
14925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret;
14935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v = qemu_get_be32(f);
14955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (v != QEMU_VM_FILE_MAGIC)
14965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EINVAL;
14975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v = qemu_get_be32(f);
14995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (v == QEMU_VM_FILE_VERSION_COMPAT)
15005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return qemu_loadvm_state_v2(f);
15013e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    if (v < QEMU_VM_FILE_VERSION) {
15023e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner        fprintf(stderr, "Snapshot format %d is too old for this version of the emulator, please create a new one.\n", v);
15033e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner        return -ENOTSUP;
15043e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    } else if (v > QEMU_VM_FILE_VERSION) {
15053e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner        fprintf(stderr, "Snapshot format %d is more recent than the emulator, please update your Android SDK Tools.\n", v);
15065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOTSUP;
15073e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    }
15085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) {
15105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint32_t instance_id, version_id, section_id;
15115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LoadStateEntry *le;
15125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        SaveStateEntry *se;
15135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        char idstr[257];
15145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int len;
15155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        switch (section_type) {
15175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case QEMU_VM_SECTION_START:
15185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case QEMU_VM_SECTION_FULL:
15195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* Read section start */
15205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            section_id = qemu_get_be32(f);
15215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            len = qemu_get_byte(f);
15225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            qemu_get_buffer(f, (uint8_t *)idstr, len);
15235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            idstr[len] = 0;
15245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            instance_id = qemu_get_be32(f);
15255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            version_id = qemu_get_be32(f);
15265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* Find savevm section */
15285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            se = find_se(idstr, instance_id);
15295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (se == NULL) {
15305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                fprintf(stderr, "Unknown savevm section or instance '%s' %d\n", idstr, instance_id);
15315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ret = -EINVAL;
15325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                goto out;
15335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
15345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* Validate version */
15365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (version_id > se->version_id) {
15375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                fprintf(stderr, "savevm: unsupported version %d for '%s' v%d\n",
15385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        version_id, idstr, se->version_id);
15395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ret = -EINVAL;
15405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                goto out;
15415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
15425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* Add entry */
1544aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner            le = g_malloc0(sizeof(*le));
15455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            le->se = se;
15475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            le->section_id = section_id;
15485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            le->version_id = version_id;
15495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            le->next = first_le;
15505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            first_le = le;
15515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1552d0e2872813e1d37e8233befdfd13a4d6cb0d7431Vladimir Chtchetkine            if (le->se->load_state(f, le->se->opaque, le->version_id)) {
1553d0e2872813e1d37e8233befdfd13a4d6cb0d7431Vladimir Chtchetkine                fprintf(stderr, "savevm: unable to load section %s\n", idstr);
1554d0e2872813e1d37e8233befdfd13a4d6cb0d7431Vladimir Chtchetkine                ret = -EINVAL;
1555d0e2872813e1d37e8233befdfd13a4d6cb0d7431Vladimir Chtchetkine                goto out;
1556d0e2872813e1d37e8233befdfd13a4d6cb0d7431Vladimir Chtchetkine            }
15575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
15585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case QEMU_VM_SECTION_PART:
15595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case QEMU_VM_SECTION_END:
15605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            section_id = qemu_get_be32(f);
15615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            for (le = first_le; le && le->section_id != section_id; le = le->next);
15635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (le == NULL) {
15645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                fprintf(stderr, "Unknown savevm section %d\n", section_id);
15655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ret = -EINVAL;
15665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                goto out;
15675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
15685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            le->se->load_state(f, le->se->opaque, le->version_id);
15705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
15715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        default:
15725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            fprintf(stderr, "Unknown savevm section type %d\n", section_type);
15735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret = -EINVAL;
15745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto out;
15755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
15765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
15775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = 0;
15795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerout:
15815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (first_le) {
15825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LoadStateEntry *le = first_le;
15835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        first_le = first_le->next;
1584aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner        g_free(le);
15855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
15865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1587c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner    if (qemu_file_get_error(f))
1588c79de3c66b3506a1c6b00daedaea9b616b3e140cDavid 'Digit' Turner      ret = qemu_file_get_error(f);
15895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
15915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1592cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#if 0
15935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverState *get_bs_snapshots(void)
15945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
15955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverState *bs;
15965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int i;
15975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bs_snapshots)
15995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return bs_snapshots;
16005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for(i = 0; i <= nb_drives; i++) {
16015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bs = drives_table[i].bdrv;
16025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bdrv_can_snapshot(bs))
16035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto ok;
16045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
16055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return NULL;
16065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ok:
16075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bs_snapshots = bs;
16085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return bs;
16095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1610cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#endif
16115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
16125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                              const char *name)
16135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
16145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUSnapshotInfo *sn_tab, *sn;
16155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int nb_sns, i, ret;
16165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = -ENOENT;
16185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
16195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (nb_sns < 0)
16205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return ret;
16215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for(i = 0; i < nb_sns; i++) {
16225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        sn = &sn_tab[i];
16235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
16245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *sn_info = *sn;
16255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret = 0;
16265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
16275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
16285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
1629aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(sn_tab);
16305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
16315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
16325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
163395a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turnervoid do_savevm(Monitor *err, const char *name)
16342ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
16355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverState *bs, *bs1;
16365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
1637cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int must_delete, ret;
16385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverInfo bdi1, *bdi = &bdi1;
16395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFile *f;
16405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int saved_vm_running;
16415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint32_t vm_state_size;
16425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32
16435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct _timeb tb;
16445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
16455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct timeval tv;
16465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
16475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1648cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs = bdrv_snapshots();
16495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bs) {
165095a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "No block device can accept snapshots\n");
16515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
16525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
16535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* ??? Should this occur after vm_stop?  */
16555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_aio_flush();
16565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    saved_vm_running = vm_running;
16585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    vm_stop(0);
16595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    must_delete = 0;
16615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (name) {
16625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = bdrv_snapshot_find(bs, old_sn, name);
16635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret >= 0) {
16645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            must_delete = 1;
16655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
16665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
16675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    memset(sn, 0, sizeof(*sn));
16685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (must_delete) {
16695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        pstrcpy(sn->name, sizeof(sn->name), old_sn->name);
16705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);
16715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
16725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (name)
16735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            pstrcpy(sn->name, sizeof(sn->name), name);
16745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
16755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* fill auxiliary fields */
16775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32
16785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    _ftime(&tb);
16795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    sn->date_sec = tb.time;
16805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    sn->date_nsec = tb.millitm * 1000000;
16815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
16825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    gettimeofday(&tv, NULL);
16835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    sn->date_sec = tv.tv_sec;
16845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    sn->date_nsec = tv.tv_usec * 1000;
16855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
1686dcda949f769a11b197f4784fe299a448d87e6e14David 'Digit' Turner    sn->vm_clock_nsec = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
16875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
168995a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "Device %s does not support VM state snapshots\n",
16902ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije                              bdrv_get_device_name(bs));
16915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto the_end;
16925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
16935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* save the VM state */
1695986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    f = qemu_fopen_bdrv(bs, 1);
16965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!f) {
169795a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "Could not open VM state file\n");
16985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto the_end;
16995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
17005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = qemu_savevm_state(f);
17015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    vm_state_size = qemu_ftell(f);
17025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_fclose(f);
17035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ret < 0) {
170495a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "Error %d while writing VM\n", ret);
17055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto the_end;
17065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
17075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* create the snapshots */
17095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1710cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs1 = NULL;
1711cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    while ((bs1 = bdrv_next(bs1))) {
17128f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thije        if (bdrv_can_snapshot(bs1)) {
17135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (must_delete) {
17145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ret = bdrv_snapshot_delete(bs1, old_sn->id_str);
17155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (ret < 0) {
171695a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner                    monitor_printf(err,
17172ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije                                          "Error while deleting snapshot on '%s'\n",
17182ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije                                          bdrv_get_device_name(bs1));
17195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
17205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
17215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* Write VM state size only to the image that contains the state */
17225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            sn->vm_state_size = (bs == bs1 ? vm_state_size : 0);
17235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret = bdrv_snapshot_create(bs1, sn);
17245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (ret < 0) {
172595a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner                monitor_printf(err, "Error while creating snapshot on '%s'\n",
17262ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije                                      bdrv_get_device_name(bs1));
17275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
17285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
17295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
17305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner the_end:
17325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (saved_vm_running)
17335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        vm_start();
17345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
17355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
173695a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turnervoid do_loadvm(Monitor *err, const char *name)
17372ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
17385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverState *bs, *bs1;
17395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverInfo bdi1, *bdi = &bdi1;
17405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUSnapshotInfo sn;
17415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFile *f;
1742cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
17435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int saved_vm_running;
17445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1745cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs = bdrv_snapshots();
17465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bs) {
174795a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "No block device supports snapshots\n");
17485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
17495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
17505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Flush all IO requests so they don't interfere with the new state.  */
17525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_aio_flush();
17535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    saved_vm_running = vm_running;
17555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    vm_stop(0);
17565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
175705e074899c900b99adca7b37eee19a4ddc090e38Vladimir Chtchetkine    bs1 = bs;
175805e074899c900b99adca7b37eee19a4ddc090e38Vladimir Chtchetkine    do {
17598f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thije        if (bdrv_can_snapshot(bs1)) {
17605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret = bdrv_snapshot_goto(bs1, name);
17615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (ret < 0) {
17625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (bs != bs1)
176395a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner                    monitor_printf(err, "Warning: ");
17645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                switch(ret) {
17655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                case -ENOTSUP:
176695a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner                    monitor_printf(err,
17675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                   "Snapshots not supported on device '%s'\n",
17685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                   bdrv_get_device_name(bs1));
17695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    break;
17705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                case -ENOENT:
177195a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner                    monitor_printf(err, "Could not find snapshot '%s' on "
17725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                   "device '%s'\n",
17735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                   name, bdrv_get_device_name(bs1));
17745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    break;
17755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                default:
177695a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner                    monitor_printf(err, "Error %d while activating snapshot on"
17775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                   " '%s'\n", ret, bdrv_get_device_name(bs1));
17785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    break;
17795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
17805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* fatal on snapshot block device */
17815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (bs == bs1)
17825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    goto the_end;
17835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
17845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
178505e074899c900b99adca7b37eee19a4ddc090e38Vladimir Chtchetkine    } while ((bs1 = bdrv_next(bs)));
17865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
178895a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "Device %s does not support VM state snapshots\n",
17895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                       bdrv_get_device_name(bs));
17905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
17915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
17925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Don't even try to load empty VM states */
17945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = bdrv_snapshot_find(bs, &sn, name);
17955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if ((ret >= 0) && (sn.vm_state_size == 0))
17965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto the_end;
17975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* restore the VM state */
1799986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    f = qemu_fopen_bdrv(bs, 0);
18005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!f) {
180195a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "Could not open VM state file\n");
18025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto the_end;
18035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
18045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = qemu_loadvm_state(f);
18055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_fclose(f);
18065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ret < 0) {
180795a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "Error %d while loading VM state\n", ret);
18085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
18095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner the_end:
18105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (saved_vm_running)
18115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        vm_start();
18125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
18135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
181495a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turnervoid do_delvm(Monitor *err, const char *name)
18152ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
18165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverState *bs, *bs1;
1817cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
18185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1819cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs = bdrv_snapshots();
18205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bs) {
182195a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "No block device supports snapshots\n");
18225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
18235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
18245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1825cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs1 = NULL;
1826cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    while ((bs1 = bdrv_next(bs1))) {
18278f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thije        if (bdrv_can_snapshot(bs1)) {
18285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret = bdrv_snapshot_delete(bs1, name);
18295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (ret < 0) {
18305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (ret == -ENOTSUP)
183195a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner                    monitor_printf(err,
18322ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije                                          "Snapshots not supported on device '%s'\n",
18332ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije                                          bdrv_get_device_name(bs1));
18345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                else
183595a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner                    monitor_printf(err, "Error %d while deleting snapshot on "
18362ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije                                          "'%s'\n", ret, bdrv_get_device_name(bs1));
18375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
18385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
18395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
18405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
18415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
184295a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turnervoid do_info_snapshots(Monitor* out, Monitor* err)
18432ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
18445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverState *bs, *bs1;
18455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUSnapshotInfo *sn_tab, *sn;
18465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int nb_sns, i;
18475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char buf[256];
18485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1849cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs = bdrv_snapshots();
18505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bs) {
185195a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "No available block device supports snapshots\n");
18525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
18535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
185495a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    monitor_printf(out, "Snapshot devices:");
1855cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs1 = NULL;
1856cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    while ((bs1 = bdrv_next(bs1))) {
18578f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thije        if (bdrv_can_snapshot(bs1)) {
18585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (bs == bs1)
185995a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner                monitor_printf(out, " %s", bdrv_get_device_name(bs1));
18605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
18615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
186295a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    monitor_printf(out, "\n");
18635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
18655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (nb_sns < 0) {
186695a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "bdrv_snapshot_list: error %d\n", nb_sns);
18675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
18685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
186995a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    monitor_printf(out, "Snapshot list (from %s):\n",
18705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   bdrv_get_device_name(bs));
187195a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    monitor_printf(out, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
18725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for(i = 0; i < nb_sns; i++) {
18735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        sn = &sn_tab[i];
187495a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(out, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
18755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
1876aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(sn_tab);
18775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1878