savevm.c revision 28a09b6fe8d8f3e92ffee9263609a6da881b8818
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"
775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "sysemu.h"
787a78db75ad42aea283f5073f51891464104a9fc3David 'Digit' Turner#include "qemu/timer.h"
795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-char.h"
80cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include "blockdev.h"
815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "block.h"
825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "audio/audio.h"
8328a09b6fe8d8f3e92ffee9263609a6da881b8818David 'Digit' Turner#include "migration/migration.h"
845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu_socket.h"
85cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include "qemu-queue.h"
8628a09b6fe8d8f3e92ffee9263609a6da881b8818David 'Digit' Turner#include "migration/qemu-file.h"
87622b8f4c760b8c4479d28430f978bad8bb9ea32cTim Baverstock#include "android/snapshot.h"
885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define SELF_ANNOUNCE_ROUNDS 5
91986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
92986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner#ifndef ETH_P_RARP
93986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner#define ETH_P_RARP 0x8035
94986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner#endif
95986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner#define ARP_HTYPE_ETH 0x0001
96986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner#define ARP_PTYPE_IP 0x0800
97986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner#define ARP_OP_REQUEST_REV 0x3
985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
995973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turnerstatic int announce_self_create(uint8_t *buf,
1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				uint8_t *mac_addr)
1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
102986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    /* Ethernet header. */
103986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    memset(buf, 0xff, 6);         /* destination MAC addr */
104986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    memcpy(buf + 6, mac_addr, 6); /* source MAC addr */
105986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    *(uint16_t *)(buf + 12) = htons(ETH_P_RARP); /* ethertype */
106986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
107986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    /* RARP header. */
108986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    *(uint16_t *)(buf + 14) = htons(ARP_HTYPE_ETH); /* hardware addr space */
109986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    *(uint16_t *)(buf + 16) = htons(ARP_PTYPE_IP); /* protocol addr space */
110986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    *(buf + 18) = 6; /* hardware addr length (ethernet) */
111986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    *(buf + 19) = 4; /* protocol addr length (IPv4) */
112986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    *(uint16_t *)(buf + 20) = htons(ARP_OP_REQUEST_REV); /* opcode */
113986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    memcpy(buf + 22, mac_addr, 6); /* source hw addr */
114986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    memset(buf + 28, 0x00, 4);     /* source protocol addr */
115986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    memcpy(buf + 32, mac_addr, 6); /* target hw addr */
116986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    memset(buf + 38, 0x00, 4);     /* target protocol addr */
117986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
118986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    /* Padding to get up to 60 bytes (ethernet min packet size, minus FCS). */
119986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    memset(buf + 42, 0x00, 18);
120986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
121986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    return 60; /* len (FCS will be added by hardware) */
1225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void qemu_announce_self_once(void *opaque)
1255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int i, len;
1275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    VLANState *vlan;
1285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    VLANClientState *vc;
1295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t buf[256];
1305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    static int count = SELF_ANNOUNCE_ROUNDS;
1315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUTimer *timer = *(QEMUTimer **)opaque;
1325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (i = 0; i < MAX_NICS; i++) {
1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!nd_table[i].used)
1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            continue;
1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        len = announce_self_create(buf, nd_table[i].macaddr);
1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        vlan = nd_table[i].vlan;
1385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
1395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            vc->receive(vc, buf, len);
1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
142986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    if (--count) {
143986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner        /* delay 50ms, 150ms, 250ms, ... */
144986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner        qemu_mod_timer(timer, qemu_get_clock_ms(rt_clock) +
145986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner                       50 + (SELF_ANNOUNCE_ROUNDS - count - 1) * 100);
1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    qemu_del_timer(timer);
1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    qemu_free_timer(timer);
1495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_announce_self(void)
1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	static QEMUTimer *timer;
1555973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turner	timer = qemu_new_timer_ms(rt_clock, qemu_announce_self_once, &timer);
1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	qemu_announce_self_once(&timer);
1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/***********************************************************/
1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* savevm/loadvm support */
1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define IO_BUF_SIZE 32768
1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct QEMUFile {
1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFilePutBufferFunc *put_buffer;
1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFileGetBufferFunc *get_buffer;
1675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFileCloseFunc *close;
1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFileRateLimit *rate_limit;
1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFileSetRateLimit *set_rate_limit;
170a12820ef4aff2e2f6d3db9b704abee2c54d08f40David Turner    QEMUFileGetRateLimit *get_rate_limit;
1715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    void *opaque;
1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int is_write;
1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int64_t buf_offset; /* start of buffer when writing, end of buffer
1755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                           when reading */
1765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int buf_index;
1775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int buf_size; /* 0 when writing */
1785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t buf[IO_BUF_SIZE];
1795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int has_error;
1815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner};
1825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
183986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnertypedef struct QEMUFileStdio
1845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
185986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    FILE *stdio_file;
1865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFile *file;
187986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner} QEMUFileStdio;
1885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct QEMUFileSocket
1905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd;
1925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFile *file;
1935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} QEMUFileSocket;
1945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
195986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnerstatic int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
1965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFileSocket *s = opaque;
1985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ssize_t len;
1995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    do {
2015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        len = recv(s->fd, (void *)buf, size, 0);
2025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } while (len == -1 && socket_error() == EINTR);
2035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (len == -1)
2055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        len = -socket_error();
2065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return len;
2085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int file_socket_close(void *opaque)
2115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFileSocket *s = opaque;
2135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(s);
2145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
2155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
217986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnerstatic int stdio_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size)
2185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
219986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    QEMUFileStdio *s = opaque;
220986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    return fwrite(buf, 1, size, s->stdio_file);
2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
223986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnerstatic int stdio_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
2245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
225986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    QEMUFileStdio *s = opaque;
226986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    FILE *fp = s->stdio_file;
2275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int bytes;
2285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    do {
2305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        clearerr(fp);
2315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bytes = fread(buf, 1, size, fp);
2325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } while ((bytes == 0) && ferror(fp) && (errno == EINTR));
2335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return bytes;
2345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
236986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnerstatic int stdio_pclose(void *opaque)
2375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
238986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    QEMUFileStdio *s = opaque;
239986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    int ret;
240986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    ret = pclose(s->stdio_file);
241986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    qemu_free(s);
242986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    return ret;
243986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner}
244986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
245986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnerstatic int stdio_fclose(void *opaque)
246986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner{
247986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    QEMUFileStdio *s = opaque;
248986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    fclose(s->stdio_file);
2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(s);
2505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
253986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' TurnerQEMUFile *qemu_popen(FILE *stdio_file, const char *mode)
2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
255986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    QEMUFileStdio *s;
2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
257986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    if (stdio_file == NULL || mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) {
2585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "qemu_popen: Argument validity check failed\n");
2595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
2605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
2615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
262986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    s = qemu_mallocz(sizeof(QEMUFileStdio));
2635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
264986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    s->stdio_file = stdio_file;
2655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if(mode[0] == 'r') {
26795a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_pclose,
268986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner				 NULL, NULL, NULL);
2695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
27095a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_pclose,
271986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner				 NULL, NULL, NULL);
2725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
2735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return s->file;
2745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerQEMUFile *qemu_popen_cmd(const char *command, const char *mode)
2775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    FILE *popen_file;
2795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    popen_file = popen(command, mode);
2815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if(popen_file == NULL) {
2825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
2835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
2845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return qemu_popen(popen_file, mode);
2865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
288986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnerint qemu_stdio_fd(QEMUFile *f)
2895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
290986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    QEMUFileStdio *p;
2915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int fd;
2925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
293986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    p = (QEMUFileStdio *)f->opaque;
294986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    fd = fileno(p->stdio_file);
2955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return fd;
2975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
299986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' TurnerQEMUFile *qemu_fdopen(int fd, const char *mode)
300986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner{
301986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    QEMUFileStdio *s;
302986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
303986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    if (mode == NULL ||
304986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner	(mode[0] != 'r' && mode[0] != 'w') ||
305986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner	mode[1] != 'b' || mode[2] != 0) {
306986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner        fprintf(stderr, "qemu_fdopen: Argument validity check failed\n");
307986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner        return NULL;
308986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    }
309986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
310986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    s = qemu_mallocz(sizeof(QEMUFileStdio));
311986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    s->stdio_file = fdopen(fd, mode);
312986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    if (!s->stdio_file)
313986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner        goto fail;
314986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
315986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    if(mode[0] == 'r') {
31695a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_fclose,
317986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner				 NULL, NULL, NULL);
318986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    } else {
31995a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_fclose,
320986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner				 NULL, NULL, NULL);
321986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    }
322986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    return s->file;
323986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
324986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnerfail:
325986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    qemu_free(s);
326986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    return NULL;
327986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner}
328986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerQEMUFile *qemu_fopen_socket(int fd)
3305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
3315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFileSocket *s = qemu_mallocz(sizeof(QEMUFileSocket));
3325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->fd = fd;
33495a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    s->file = qemu_fopen_ops(s, NULL, socket_get_buffer, file_socket_close,
335986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner			     NULL, NULL, NULL);
3365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return s->file;
3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int file_put_buffer(void *opaque, const uint8_t *buf,
3405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            int64_t pos, int size)
3415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
3425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFileStdio *s = opaque;
343986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    fseek(s->stdio_file, pos, SEEK_SET);
344986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    return fwrite(buf, 1, size, s->stdio_file);
3455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int file_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
3485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
3495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFileStdio *s = opaque;
350986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    fseek(s->stdio_file, pos, SEEK_SET);
351986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    return fread(buf, 1, size, s->stdio_file);
3525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerQEMUFile *qemu_fopen(const char *filename, const char *mode)
3555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
3565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFileStdio *s;
3575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
358986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    if (mode == NULL ||
359986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner	(mode[0] != 'r' && mode[0] != 'w') ||
360986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner	mode[1] != 'b' || mode[2] != 0) {
361986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner        fprintf(stderr, "qemu_fopen: Argument validity check failed\n");
362986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner        return NULL;
363986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    }
364986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
3655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s = qemu_mallocz(sizeof(QEMUFileStdio));
3665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
367986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    s->stdio_file = fopen(filename, mode);
368986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    if (!s->stdio_file)
3695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto fail;
37095a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner
371986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    if(mode[0] == 'w') {
37295a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        s->file = qemu_fopen_ops(s, file_put_buffer, NULL, stdio_fclose,
373986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner				 NULL, NULL, NULL);
374986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    } else {
37595a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        s->file = qemu_fopen_ops(s, NULL, file_get_buffer, stdio_fclose,
376986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner			       NULL, NULL, NULL);
377986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    }
378986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    return s->file;
3795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerfail:
3805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(s);
3815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return NULL;
3825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int block_put_buffer(void *opaque, const uint8_t *buf,
3855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                           int64_t pos, int size)
3865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
387986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    bdrv_save_vmstate(opaque, buf, pos, size);
3885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return size;
3895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int block_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
3925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
393986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    return bdrv_load_vmstate(opaque, buf, pos, size);
3945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bdrv_fclose(void *opaque)
3975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
3985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
3995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
401986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnerstatic QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable)
4025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (is_writable)
40495a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        return qemu_fopen_ops(bs, block_put_buffer, NULL, bdrv_fclose,
405986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner			      NULL, NULL, NULL);
406986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    return qemu_fopen_ops(bs, NULL, block_get_buffer, bdrv_fclose, NULL, NULL, NULL);
4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerQEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
4105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         QEMUFileGetBufferFunc *get_buffer,
4115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         QEMUFileCloseFunc *close,
4125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         QEMUFileRateLimit *rate_limit,
413a12820ef4aff2e2f6d3db9b704abee2c54d08f40David Turner                         QEMUFileSetRateLimit *set_rate_limit,
414a12820ef4aff2e2f6d3db9b704abee2c54d08f40David Turner                         QEMUFileGetRateLimit *get_rate_limit)
4155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFile *f;
4175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    f = qemu_mallocz(sizeof(QEMUFile));
4195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    f->opaque = opaque;
4215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    f->put_buffer = put_buffer;
4225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    f->get_buffer = get_buffer;
4235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    f->close = close;
4245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    f->rate_limit = rate_limit;
4255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    f->set_rate_limit = set_rate_limit;
426986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    f->get_rate_limit = get_rate_limit;
4275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    f->is_write = 0;
4285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return f;
4305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_file_has_error(QEMUFile *f)
4335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return f->has_error;
4355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_file_set_error(QEMUFile *f)
4385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    f->has_error = 1;
4405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_fflush(QEMUFile *f)
4435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!f->put_buffer)
4455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
4465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (f->is_write && f->buf_index > 0) {
4485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int len;
4495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        len = f->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index);
4515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (len > 0)
4525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            f->buf_offset += f->buf_index;
4535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        else
4545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            f->has_error = 1;
4555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        f->buf_index = 0;
4565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
4575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void qemu_fill_buffer(QEMUFile *f)
4605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int len;
4625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!f->get_buffer)
4645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
4655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (f->is_write)
4675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        abort();
4685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    len = f->get_buffer(f->opaque, f->buf, f->buf_offset, IO_BUF_SIZE);
4705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (len > 0) {
4715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        f->buf_index = 0;
4725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        f->buf_size = len;
4735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        f->buf_offset += len;
4745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (len != -EAGAIN)
4755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        f->has_error = 1;
4765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_fclose(QEMUFile *f)
4795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret = 0;
4815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_fflush(f);
4825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (f->close)
4835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = f->close(f->opaque);
4845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(f);
4855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
4865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_file_put_notify(QEMUFile *f)
4895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    f->put_buffer(f->opaque, NULL, 0, 0);
4915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
4945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int l;
4965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!f->has_error && f->is_write == 0 && f->buf_index > 0) {
4985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr,
4995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                "Attempted to write to buffer while read buffer is not empty\n");
5005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        abort();
5015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
5025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (!f->has_error && size > 0) {
5045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        l = IO_BUF_SIZE - f->buf_index;
5055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (l > size)
5065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            l = size;
5075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        memcpy(f->buf + f->buf_index, buf, l);
5085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        f->is_write = 1;
5095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        f->buf_index += l;
5105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        buf += l;
5115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        size -= l;
5125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (f->buf_index >= IO_BUF_SIZE)
5135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            qemu_fflush(f);
5145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
5155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_put_byte(QEMUFile *f, int v)
5185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!f->has_error && f->is_write == 0 && f->buf_index > 0) {
5205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr,
5215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                "Attempted to write to buffer while read buffer is not empty\n");
5225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        abort();
5235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
5245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    f->buf[f->buf_index++] = v;
5265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    f->is_write = 1;
5275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (f->buf_index >= IO_BUF_SIZE)
5285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_fflush(f);
5295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1)
5325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int size, l;
5345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (f->is_write)
5365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        abort();
5375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    size = size1;
5395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (size > 0) {
5405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        l = f->buf_size - f->buf_index;
5415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (l == 0) {
5425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            qemu_fill_buffer(f);
5435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            l = f->buf_size - f->buf_index;
5445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (l == 0)
5455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
5465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
5475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (l > size)
5485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            l = size;
5495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        memcpy(buf, f->buf + f->buf_index, l);
5505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        f->buf_index += l;
5515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        buf += l;
5525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        size -= l;
5535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
5545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return size1 - size;
5555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_get_byte(QEMUFile *f)
5585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (f->is_write)
5605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        abort();
5615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (f->buf_index >= f->buf_size) {
5635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_fill_buffer(f);
5645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (f->buf_index >= f->buf_size)
5655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return 0;
5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
5675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return f->buf[f->buf_index++];
5685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5703e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner#ifdef CONFIG_ANDROID
5713e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turnervoid qemu_put_string(QEMUFile *f, const char* str)
5723e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner{
5733e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    /* We will encode NULL and the empty string in the same way */
5743e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    int  slen;
5753e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    if (str == NULL) {
5763e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner        str = "";
5773e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    }
5783e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    slen = strlen(str);
5793e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    qemu_put_be32(f, slen);
5803e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    qemu_put_buffer(f, (const uint8_t*)str, slen);
5813e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner}
5823e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner
5833e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turnerchar* qemu_get_string(QEMUFile *f)
5843e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner{
5853e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    int slen = qemu_get_be32(f);
5863e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    char* str;
5873e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    if (slen == 0)
5883e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner        return NULL;
5893e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner
5903e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    str = qemu_malloc(slen+1);
5913e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    if (qemu_get_buffer(f, (uint8_t*)str, slen) != slen) {
5923e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner        qemu_free(str);
5933e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner        return NULL;
5943e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    }
5953e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    str[slen] = '\0';
5963e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    return str;
5973e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner}
5983e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner#endif
5993e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner
6003e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner
6015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint64_t qemu_ftell(QEMUFile *f)
6025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return f->buf_offset - f->buf_size + f->buf_index;
6045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence)
6075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (whence == SEEK_SET) {
6095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* nothing to do */
6105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (whence == SEEK_CUR) {
6115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        pos += qemu_ftell(f);
6125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
6135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* SEEK_END not supported */
6145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -1;
6155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
6165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (f->put_buffer) {
6175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_fflush(f);
6185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        f->buf_offset = pos;
6195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
6205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        f->buf_offset = pos;
6215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        f->buf_index = 0;
6225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        f->buf_size = 0;
6235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
6245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return pos;
6255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_file_rate_limit(QEMUFile *f)
6285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (f->rate_limit)
6305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return f->rate_limit(f->opaque);
6315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
6335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
635986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnerint64_t qemu_file_get_rate_limit(QEMUFile *f)
636986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner{
637986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    if (f->get_rate_limit)
638986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner        return f->get_rate_limit(f->opaque);
639986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
640986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    return 0;
641986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner}
642986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner
643986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turnerint64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate)
6445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
645986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    /* any failed or completed migration keeps its state to allow probing of
646986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner     * migration data, but has no associated file anymore */
647986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    if (f && f->set_rate_limit)
6485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return f->set_rate_limit(f->opaque, new_rate);
6495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
6515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_put_be16(QEMUFile *f, unsigned int v)
6545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_byte(f, v >> 8);
6565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_byte(f, v);
6575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_put_be32(QEMUFile *f, unsigned int v)
6605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_byte(f, v >> 24);
6625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_byte(f, v >> 16);
6635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_byte(f, v >> 8);
6645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_byte(f, v);
6655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_put_be64(QEMUFile *f, uint64_t v)
6685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_be32(f, v >> 32);
6705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_be32(f, v);
6715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerunsigned int qemu_get_be16(QEMUFile *f)
6745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    unsigned int v;
6765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v = qemu_get_byte(f) << 8;
6775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v |= qemu_get_byte(f);
6785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return v;
6795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerunsigned int qemu_get_be32(QEMUFile *f)
6825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    unsigned int v;
6845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v = qemu_get_byte(f) << 24;
6855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v |= qemu_get_byte(f) << 16;
6865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v |= qemu_get_byte(f) << 8;
6875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v |= qemu_get_byte(f);
6885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return v;
6895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneruint64_t qemu_get_be64(QEMUFile *f)
6925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint64_t v;
6945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v = (uint64_t)qemu_get_be32(f) << 32;
6955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v |= qemu_get_be32(f);
6965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return v;
6975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid  qemu_put_struct(QEMUFile*  f, const QField*  fields, const void*  s)
7005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    const QField*  qf = fields;
7025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7037fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije    /* Iterate over struct fields */
7047fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije    while (qf->type != Q_FIELD_END) {
7055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t*  p = (uint8_t*)s + qf->offset;
7065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        switch (qf->type) {
7085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_BYTE:
7095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                qemu_put_byte(f, p[0]);
7105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
7115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_INT16:
7125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                qemu_put_be16(f, ((uint16_t*)p)[0]);
7135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
7145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_INT32:
7155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                qemu_put_be32(f, ((uint32_t*)p)[0]);
7165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
7175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_INT64:
7185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                qemu_put_be64(f, ((uint64_t*)p)[0]);
7195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
7205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_BUFFER:
7217fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije                if (qf[1].type != Q_FIELD_BUFFER_SIZE ||
7227fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije                    qf[2].type != Q_FIELD_BUFFER_SIZE)
7235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                {
7245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    fprintf(stderr, "%s: invalid QFIELD_BUFFER item passed as argument. aborting\n",
7255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            __FUNCTION__ );
7265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    exit(1);
7275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
7285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                else
7295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                {
7307fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije                    uint32_t  size = ((uint32_t)qf[1].offset << 16) | (uint32_t)qf[2].offset;
7315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    qemu_put_buffer(f, p, size);
7335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    qf += 2;
7345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
7355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
7365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            default:
7375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                fprintf(stderr, "%s: invalid fields list passed as argument. aborting\n", __FUNCTION__);
7385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                exit(1);
7395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
7405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qf++;
7415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
7425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
7435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint   qemu_get_struct(QEMUFile*  f, const QField*  fields, void*  s)
7455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    const QField*  qf = fields;
7475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7487fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije    /* Iterate over struct fields */
7497fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije    while (qf->type != Q_FIELD_END) {
7505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint8_t*  p = (uint8_t*)s + qf->offset;
7515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        switch (qf->type) {
7535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_BYTE:
7545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                p[0] = qemu_get_byte(f);
7555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
7565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_INT16:
7575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ((uint16_t*)p)[0] = qemu_get_be16(f);
7585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
7595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_INT32:
7605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ((uint32_t*)p)[0] = qemu_get_be32(f);
7615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
7625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_INT64:
7635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ((uint64_t*)p)[0] = qemu_get_be64(f);
7645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
7655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case Q_FIELD_BUFFER:
7667fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije                if (qf[1].type != Q_FIELD_BUFFER_SIZE ||
7677fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije                        qf[2].type != Q_FIELD_BUFFER_SIZE)
7685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                {
7695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    fprintf(stderr, "%s: invalid QFIELD_BUFFER item passed as argument.\n",
7705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            __FUNCTION__ );
7715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    return -1;
7725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
7735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                else
7745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                {
7757fd67eba0b961d94a5d6baa8e3c3de37b729f738Ot ten Thije                    uint32_t  size = ((uint32_t)qf[1].offset << 16) | (uint32_t)qf[2].offset;
7765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    int       ret  = qemu_get_buffer(f, p, size);
7775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    if (ret != size) {
7795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        fprintf(stderr, "%s: not enough bytes to load structure\n", __FUNCTION__);
7805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        return -1;
7815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    }
7825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    qf += 2;
7835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
7845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                break;
7855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            default:
7865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                fprintf(stderr, "%s: invalid fields list passed as argument. aborting\n", __FUNCTION__);
7875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                exit(1);
7885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
7895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qf++;
7905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
7915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
7925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
7935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
794871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije/* write a float to file */
795871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thijevoid qemu_put_float(QEMUFile *f, float v)
796871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije{
797871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije    uint8_t *bytes = (uint8_t*) &v;
798871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije    qemu_put_buffer(f, bytes, sizeof(float));
799871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije}
800871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije
801871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije/* read a float from file */
802871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thijefloat qemu_get_float(QEMUFile *f)
803871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije{
804871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije    uint8_t bytes[sizeof(float)];
805871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije    qemu_get_buffer(f, bytes, sizeof(float));
806871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije
807871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije    return *((float*) bytes);
808871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije}
809871da2aa80687142bec00ef7c1112253c76c32bbOt ten Thije
8105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct SaveStateEntry {
8115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char idstr[256];
8125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int instance_id;
8135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int version_id;
8145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int section_id;
8155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveLiveStateHandler *save_live_state;
8165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveStateHandler *save_state;
8175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    LoadStateHandler *load_state;
8185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    void *opaque;
8195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct SaveStateEntry *next;
8205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} SaveStateEntry;
8215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic SaveStateEntry *first_se;
8235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* TODO: Individual devices generally have very little idea about the rest
8255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   of the system, so instance_id should be removed/replaced.
8265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   Meanwhile pass -1 as instance_id if you do not already have a clearly
8275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   distinguishing id for all instances of your device class. */
8285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint register_savevm_live(const char *idstr,
8295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         int instance_id,
8305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         int version_id,
8315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         SaveLiveStateHandler *save_live_state,
8325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         SaveStateHandler *save_state,
8335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         LoadStateHandler *load_state,
8345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                         void *opaque)
8355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveStateEntry *se, **pse;
8375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    static int global_section_id;
8385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    se = qemu_malloc(sizeof(SaveStateEntry));
8405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    pstrcpy(se->idstr, sizeof(se->idstr), idstr);
8415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    se->instance_id = (instance_id == -1) ? 0 : instance_id;
8425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    se->version_id = version_id;
8435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    se->section_id = global_section_id++;
8445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    se->save_live_state = save_live_state;
8455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    se->save_state = save_state;
8465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    se->load_state = load_state;
8475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    se->opaque = opaque;
8485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    se->next = NULL;
8495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* add at the end of list */
8515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    pse = &first_se;
8525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (*pse != NULL) {
8535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (instance_id == -1
8545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                && strcmp(se->idstr, (*pse)->idstr) == 0
8555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                && se->instance_id <= (*pse)->instance_id)
8565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            se->instance_id = (*pse)->instance_id + 1;
8575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        pse = &(*pse)->next;
8585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    *pse = se;
8605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
8615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint register_savevm(const char *idstr,
8645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    int instance_id,
8655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    int version_id,
8665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    SaveStateHandler *save_state,
8675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    LoadStateHandler *load_state,
8685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    void *opaque)
8695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return register_savevm_live(idstr, instance_id, version_id,
8715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                NULL, save_state, load_state, opaque);
8725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid unregister_savevm(const char *idstr, void *opaque)
8755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveStateEntry **pse;
8775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    pse = &first_se;
8795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (*pse != NULL) {
8805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (strcmp((*pse)->idstr, idstr) == 0 && (*pse)->opaque == opaque) {
8815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            SaveStateEntry *next = (*pse)->next;
8825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            qemu_free(*pse);
8835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *pse = next;
8845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            continue;
8855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
8865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        pse = &(*pse)->next;
8875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define QEMU_VM_FILE_MAGIC           0x5145564d
8915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define QEMU_VM_FILE_VERSION_COMPAT  0x00000002
8923e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner#define QEMU_VM_FILE_VERSION         0x00000004
8935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define QEMU_VM_EOF                  0x00
8955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define QEMU_VM_SECTION_START        0x01
8965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define QEMU_VM_SECTION_PART         0x02
8975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define QEMU_VM_SECTION_END          0x03
8985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define QEMU_VM_SECTION_FULL         0x04
8995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_savevm_state_begin(QEMUFile *f)
9015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
9025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveStateEntry *se;
9035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
9055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_be32(f, QEMU_VM_FILE_VERSION);
9065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (se = first_se; se != NULL; se = se->next) {
9085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int len;
9095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (se->save_live_state == NULL)
9115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            continue;
9125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Section type */
9145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_byte(f, QEMU_VM_SECTION_START);
9155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_be32(f, se->section_id);
9165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* ID string */
9185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        len = strlen(se->idstr);
9195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_byte(f, len);
9205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_buffer(f, (uint8_t *)se->idstr, len);
9215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_be32(f, se->instance_id);
9235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_be32(f, se->version_id);
9245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        se->save_live_state(f, QEMU_VM_SECTION_START, se->opaque);
9265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
9275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (qemu_file_has_error(f))
9295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
9305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
9325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
9335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_savevm_state_iterate(QEMUFile *f)
9355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
9365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveStateEntry *se;
9375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret = 1;
9385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (se = first_se; se != NULL; se = se->next) {
9405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (se->save_live_state == NULL)
9415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            continue;
9425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Section type */
9445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_byte(f, QEMU_VM_SECTION_PART);
9455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_be32(f, se->section_id);
9465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret &= !!se->save_live_state(f, QEMU_VM_SECTION_PART, se->opaque);
9485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
9495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ret)
9515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 1;
9525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (qemu_file_has_error(f))
9545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
9555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
9575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
9585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_savevm_state_complete(QEMUFile *f)
9605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
9615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveStateEntry *se;
9625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (se = first_se; se != NULL; se = se->next) {
9645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (se->save_live_state == NULL)
9655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            continue;
9665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Section type */
9685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_byte(f, QEMU_VM_SECTION_END);
9695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_be32(f, se->section_id);
9705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        se->save_live_state(f, QEMU_VM_SECTION_END, se->opaque);
9725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
9735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for(se = first_se; se != NULL; se = se->next) {
9755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int len;
9765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9778f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thije        if (se->save_state == NULL)
9788f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thije            continue;
9795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Section type */
9815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_byte(f, QEMU_VM_SECTION_FULL);
9825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_be32(f, se->section_id);
9835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* ID string */
9855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        len = strlen(se->idstr);
9865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_byte(f, len);
9875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_buffer(f, (uint8_t *)se->idstr, len);
9885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_be32(f, se->instance_id);
9905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_put_be32(f, se->version_id);
9915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        se->save_state(f, se->opaque);
9935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
9945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_put_byte(f, QEMU_VM_EOF);
9965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (qemu_file_has_error(f))
9985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
9995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
10015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_savevm_state(QEMUFile *f)
10045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int saved_vm_running;
10065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret;
10075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    saved_vm_running = vm_running;
10095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    vm_stop(0);
10105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bdrv_flush_all();
10125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = qemu_savevm_state_begin(f);
10145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ret < 0)
10155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto out;
10165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    do {
10185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = qemu_savevm_state_iterate(f);
10195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret < 0)
10205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto out;
10215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } while (ret == 0);
10225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = qemu_savevm_state_complete(f);
10245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerout:
10265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (qemu_file_has_error(f))
10275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = -EIO;
10285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!ret && saved_vm_running)
10305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        vm_start();
10315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
10335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic SaveStateEntry *find_se(const char *idstr, int instance_id)
10365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveStateEntry *se;
10385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for(se = first_se; se != NULL; se = se->next) {
10405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!strcmp(se->idstr, idstr) &&
10415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            instance_id == se->instance_id)
10425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return se;
10435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
10445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return NULL;
10455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct LoadStateEntry {
10485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveStateEntry *se;
10495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int section_id;
10505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int version_id;
10515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct LoadStateEntry *next;
10525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} LoadStateEntry;
10535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int qemu_loadvm_state_v2(QEMUFile *f)
10555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SaveStateEntry *se;
10575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int len, ret, instance_id, record_len, version_id;
10585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int64_t total_len, end_pos, cur_pos;
10595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char idstr[256];
10605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    total_len = qemu_get_be64(f);
10625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    end_pos = total_len + qemu_ftell(f);
10635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for(;;) {
10645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (qemu_ftell(f) >= end_pos)
10655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
10665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        len = qemu_get_byte(f);
10675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_get_buffer(f, (uint8_t *)idstr, len);
10685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        idstr[len] = '\0';
10695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        instance_id = qemu_get_be32(f);
10705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        version_id = qemu_get_be32(f);
10715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        record_len = qemu_get_be32(f);
10725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        cur_pos = qemu_ftell(f);
10735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        se = find_se(idstr, instance_id);
10745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!se) {
10755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            fprintf(stderr, "qemu: warning: instance 0x%x of device '%s' not present in current VM\n",
10765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    instance_id, idstr);
10775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
10785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret = se->load_state(f, se->opaque, version_id);
10795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (ret < 0) {
10805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n",
10815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        instance_id, idstr);
10825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return ret;
10835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
10845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
10855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* always seek to exact end of record */
10865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_fseek(f, cur_pos + record_len, SEEK_SET);
10875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
10885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (qemu_file_has_error(f))
10905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EIO;
10915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
10935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_loadvm_state(QEMUFile *f)
10965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    LoadStateEntry *first_le = NULL;
10985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t section_type;
10995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    unsigned int v;
11005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int ret;
11015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v = qemu_get_be32(f);
11035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (v != QEMU_VM_FILE_MAGIC)
11045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -EINVAL;
11055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    v = qemu_get_be32(f);
11075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (v == QEMU_VM_FILE_VERSION_COMPAT)
11085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return qemu_loadvm_state_v2(f);
11093e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    if (v < QEMU_VM_FILE_VERSION) {
11103e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner        fprintf(stderr, "Snapshot format %d is too old for this version of the emulator, please create a new one.\n", v);
11113e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner        return -ENOTSUP;
11123e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    } else if (v > QEMU_VM_FILE_VERSION) {
11133e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner        fprintf(stderr, "Snapshot format %d is more recent than the emulator, please update your Android SDK Tools.\n", v);
11145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOTSUP;
11153e92c2d49cb0e8752ce8c9a3c879c84ac3299061David 'Digit' Turner    }
11165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) {
11185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint32_t instance_id, version_id, section_id;
11195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LoadStateEntry *le;
11205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        SaveStateEntry *se;
11215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        char idstr[257];
11225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int len;
11235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        switch (section_type) {
11255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case QEMU_VM_SECTION_START:
11265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case QEMU_VM_SECTION_FULL:
11275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* Read section start */
11285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            section_id = qemu_get_be32(f);
11295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            len = qemu_get_byte(f);
11305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            qemu_get_buffer(f, (uint8_t *)idstr, len);
11315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            idstr[len] = 0;
11325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            instance_id = qemu_get_be32(f);
11335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            version_id = qemu_get_be32(f);
11345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* Find savevm section */
11365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            se = find_se(idstr, instance_id);
11375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (se == NULL) {
11385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                fprintf(stderr, "Unknown savevm section or instance '%s' %d\n", idstr, instance_id);
11395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ret = -EINVAL;
11405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                goto out;
11415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
11425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* Validate version */
11445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (version_id > se->version_id) {
11455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                fprintf(stderr, "savevm: unsupported version %d for '%s' v%d\n",
11465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        version_id, idstr, se->version_id);
11475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ret = -EINVAL;
11485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                goto out;
11495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
11505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* Add entry */
11525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            le = qemu_mallocz(sizeof(*le));
11535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            le->se = se;
11555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            le->section_id = section_id;
11565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            le->version_id = version_id;
11575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            le->next = first_le;
11585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            first_le = le;
11595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1160d0e2872813e1d37e8233befdfd13a4d6cb0d7431Vladimir Chtchetkine            if (le->se->load_state(f, le->se->opaque, le->version_id)) {
1161d0e2872813e1d37e8233befdfd13a4d6cb0d7431Vladimir Chtchetkine                fprintf(stderr, "savevm: unable to load section %s\n", idstr);
1162d0e2872813e1d37e8233befdfd13a4d6cb0d7431Vladimir Chtchetkine                ret = -EINVAL;
1163d0e2872813e1d37e8233befdfd13a4d6cb0d7431Vladimir Chtchetkine                goto out;
1164d0e2872813e1d37e8233befdfd13a4d6cb0d7431Vladimir Chtchetkine            }
11655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
11665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case QEMU_VM_SECTION_PART:
11675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case QEMU_VM_SECTION_END:
11685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            section_id = qemu_get_be32(f);
11695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            for (le = first_le; le && le->section_id != section_id; le = le->next);
11715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (le == NULL) {
11725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                fprintf(stderr, "Unknown savevm section %d\n", section_id);
11735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ret = -EINVAL;
11745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                goto out;
11755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
11765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            le->se->load_state(f, le->se->opaque, le->version_id);
11785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
11795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        default:
11805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            fprintf(stderr, "Unknown savevm section type %d\n", section_type);
11815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret = -EINVAL;
11825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto out;
11835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
11845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
11855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = 0;
11875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerout:
11895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (first_le) {
11905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LoadStateEntry *le = first_le;
11915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        first_le = first_le->next;
11925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_free(le);
11935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
11945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (qemu_file_has_error(f))
11965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = -EIO;
11975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
11995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1200cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#if 0
12015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverState *get_bs_snapshots(void)
12025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
12035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverState *bs;
12045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int i;
12055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bs_snapshots)
12075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return bs_snapshots;
12085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for(i = 0; i <= nb_drives; i++) {
12095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bs = drives_table[i].bdrv;
12105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bdrv_can_snapshot(bs))
12115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto ok;
12125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
12135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return NULL;
12145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ok:
12155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bs_snapshots = bs;
12165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return bs;
12175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1218cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#endif
12195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
12205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                              const char *name)
12215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
12225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUSnapshotInfo *sn_tab, *sn;
12235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int nb_sns, i, ret;
12245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = -ENOENT;
12265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
12275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (nb_sns < 0)
12285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return ret;
12295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for(i = 0; i < nb_sns; i++) {
12305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        sn = &sn_tab[i];
12315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
12325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            *sn_info = *sn;
12335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret = 0;
12345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
12355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
12365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
12375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(sn_tab);
12385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
12395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
12405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
124195a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turnervoid do_savevm(Monitor *err, const char *name)
12422ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
12435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverState *bs, *bs1;
12445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
1245cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int must_delete, ret;
12465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverInfo bdi1, *bdi = &bdi1;
12475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFile *f;
12485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int saved_vm_running;
12495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint32_t vm_state_size;
12505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32
12515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct _timeb tb;
12525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
12535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct timeval tv;
12545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
12555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1256cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs = bdrv_snapshots();
12575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bs) {
125895a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "No block device can accept snapshots\n");
12595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
12605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
12615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* ??? Should this occur after vm_stop?  */
12635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_aio_flush();
12645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    saved_vm_running = vm_running;
12665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    vm_stop(0);
12675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    must_delete = 0;
12695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (name) {
12705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = bdrv_snapshot_find(bs, old_sn, name);
12715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret >= 0) {
12725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            must_delete = 1;
12735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
12745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
12755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    memset(sn, 0, sizeof(*sn));
12765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (must_delete) {
12775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        pstrcpy(sn->name, sizeof(sn->name), old_sn->name);
12785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);
12795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
12805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (name)
12815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            pstrcpy(sn->name, sizeof(sn->name), name);
12825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
12835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* fill auxiliary fields */
12855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32
12865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    _ftime(&tb);
12875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    sn->date_sec = tb.time;
12885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    sn->date_nsec = tb.millitm * 1000000;
12895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
12905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    gettimeofday(&tv, NULL);
12915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    sn->date_sec = tv.tv_sec;
12925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    sn->date_nsec = tv.tv_usec * 1000;
12935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
12945973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turner    sn->vm_clock_nsec = qemu_get_clock_ns(vm_clock);
12955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
129795a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "Device %s does not support VM state snapshots\n",
12982ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije                              bdrv_get_device_name(bs));
12995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto the_end;
13005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
13015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* save the VM state */
1303986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    f = qemu_fopen_bdrv(bs, 1);
13045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!f) {
130595a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "Could not open VM state file\n");
13065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto the_end;
13075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
13085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = qemu_savevm_state(f);
13095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    vm_state_size = qemu_ftell(f);
13105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_fclose(f);
13115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ret < 0) {
131295a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "Error %d while writing VM\n", ret);
13135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto the_end;
13145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
13155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* create the snapshots */
13175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1318cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs1 = NULL;
1319cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    while ((bs1 = bdrv_next(bs1))) {
13208f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thije        if (bdrv_can_snapshot(bs1)) {
13215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (must_delete) {
13225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                ret = bdrv_snapshot_delete(bs1, old_sn->id_str);
13235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (ret < 0) {
132495a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner                    monitor_printf(err,
13252ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije                                          "Error while deleting snapshot on '%s'\n",
13262ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije                                          bdrv_get_device_name(bs1));
13275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
13285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
13295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* Write VM state size only to the image that contains the state */
13305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            sn->vm_state_size = (bs == bs1 ? vm_state_size : 0);
13315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret = bdrv_snapshot_create(bs1, sn);
13325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (ret < 0) {
133395a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner                monitor_printf(err, "Error while creating snapshot on '%s'\n",
13342ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije                                      bdrv_get_device_name(bs1));
13355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
13365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
13375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
13385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner the_end:
13405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (saved_vm_running)
13415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        vm_start();
13425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
134495a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turnervoid do_loadvm(Monitor *err, const char *name)
13452ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
13465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverState *bs, *bs1;
13475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverInfo bdi1, *bdi = &bdi1;
13485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUSnapshotInfo sn;
13495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUFile *f;
1350cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
13515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int saved_vm_running;
13525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1353cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs = bdrv_snapshots();
13545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bs) {
135595a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "No block device supports snapshots\n");
13565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
13575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
13585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Flush all IO requests so they don't interfere with the new state.  */
13605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_aio_flush();
13615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    saved_vm_running = vm_running;
13635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    vm_stop(0);
13645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
136505e074899c900b99adca7b37eee19a4ddc090e38Vladimir Chtchetkine    bs1 = bs;
136605e074899c900b99adca7b37eee19a4ddc090e38Vladimir Chtchetkine    do {
13678f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thije        if (bdrv_can_snapshot(bs1)) {
13685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret = bdrv_snapshot_goto(bs1, name);
13695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (ret < 0) {
13705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (bs != bs1)
137195a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner                    monitor_printf(err, "Warning: ");
13725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                switch(ret) {
13735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                case -ENOTSUP:
137495a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner                    monitor_printf(err,
13755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                   "Snapshots not supported on device '%s'\n",
13765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                   bdrv_get_device_name(bs1));
13775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    break;
13785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                case -ENOENT:
137995a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner                    monitor_printf(err, "Could not find snapshot '%s' on "
13805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                   "device '%s'\n",
13815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                   name, bdrv_get_device_name(bs1));
13825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    break;
13835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                default:
138495a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner                    monitor_printf(err, "Error %d while activating snapshot on"
13855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                   " '%s'\n", ret, bdrv_get_device_name(bs1));
13865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    break;
13875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
13885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* fatal on snapshot block device */
13895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (bs == bs1)
13905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    goto the_end;
13915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
13925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
139305e074899c900b99adca7b37eee19a4ddc090e38Vladimir Chtchetkine    } while ((bs1 = bdrv_next(bs)));
13945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
139695a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "Device %s does not support VM state snapshots\n",
13975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                       bdrv_get_device_name(bs));
13985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
13995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
14005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Don't even try to load empty VM states */
14025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = bdrv_snapshot_find(bs, &sn, name);
14035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if ((ret >= 0) && (sn.vm_state_size == 0))
14045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto the_end;
14055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* restore the VM state */
1407986acc9eba2cf7c9b468c2f84764fa478907ac66David 'Digit' Turner    f = qemu_fopen_bdrv(bs, 0);
14085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!f) {
140995a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "Could not open VM state file\n");
14105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto the_end;
14115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
14125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = qemu_loadvm_state(f);
14135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_fclose(f);
14145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ret < 0) {
141595a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "Error %d while loading VM state\n", ret);
14165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
14175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner the_end:
14185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (saved_vm_running)
14195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        vm_start();
14205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
142295a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turnervoid do_delvm(Monitor *err, const char *name)
14232ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
14245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverState *bs, *bs1;
1425cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
14265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1427cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs = bdrv_snapshots();
14285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bs) {
142995a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "No block device supports snapshots\n");
14305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
14315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
14325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1433cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs1 = NULL;
1434cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    while ((bs1 = bdrv_next(bs1))) {
14358f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thije        if (bdrv_can_snapshot(bs1)) {
14365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret = bdrv_snapshot_delete(bs1, name);
14375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (ret < 0) {
14385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (ret == -ENOTSUP)
143995a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner                    monitor_printf(err,
14402ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije                                          "Snapshots not supported on device '%s'\n",
14412ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije                                          bdrv_get_device_name(bs1));
14425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                else
144395a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner                    monitor_printf(err, "Error %d while deleting snapshot on "
14442ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije                                          "'%s'\n", ret, bdrv_get_device_name(bs1));
14455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
14465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
14475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
14485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
145095a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turnervoid do_info_snapshots(Monitor* out, Monitor* err)
14512ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
14525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriverState *bs, *bs1;
14535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUSnapshotInfo *sn_tab, *sn;
14545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int nb_sns, i;
14555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    char buf[256];
14565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1457cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs = bdrv_snapshots();
14585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bs) {
145995a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "No available block device supports snapshots\n");
14605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
14615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
146295a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    monitor_printf(out, "Snapshot devices:");
1463cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs1 = NULL;
1464cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    while ((bs1 = bdrv_next(bs1))) {
14658f2de6dd4f99bf15ab55b07b88f61c1ba4c65187Ot ten Thije        if (bdrv_can_snapshot(bs1)) {
14665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (bs == bs1)
146795a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner                monitor_printf(out, " %s", bdrv_get_device_name(bs1));
14685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
14695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
147095a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    monitor_printf(out, "\n");
14715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
14735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (nb_sns < 0) {
147495a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(err, "bdrv_snapshot_list: error %d\n", nb_sns);
14755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
14765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
147795a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    monitor_printf(out, "Snapshot list (from %s):\n",
14785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   bdrv_get_device_name(bs));
147995a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    monitor_printf(out, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
14805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for(i = 0; i < nb_sns; i++) {
14815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        sn = &sn_tab[i];
148295a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner        monitor_printf(out, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
14835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
14845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(sn_tab);
14855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1486