blob: 0f3ca5315c1558f1ed24f539f787dbdf578f67a8 [file] [log] [blame]
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001/*
2 * QEMU System Emulator
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24#include <unistd.h>
25#include <fcntl.h>
26#include <signal.h>
27#include <time.h>
28#include <errno.h>
29#include <sys/time.h>
30#include <zlib.h>
31
David 'Digit' Turner2c538c82010-05-10 16:48:20 -070032/* Needed early for CONFIG_BSD etc. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070033#include "config-host.h"
34
35#ifndef _WIN32
36#include <sys/times.h>
37#include <sys/wait.h>
38#include <termios.h>
39#include <sys/mman.h>
40#include <sys/ioctl.h>
41#include <sys/resource.h>
42#include <sys/socket.h>
43#include <netinet/in.h>
44#include <net/if.h>
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070045#include <arpa/inet.h>
46#include <dirent.h>
47#include <netdb.h>
48#include <sys/select.h>
David 'Digit' Turner2c538c82010-05-10 16:48:20 -070049#ifdef CONFIG_BSD
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070050#include <sys/stat.h>
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +010051#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070052#include <libutil.h>
53#else
54#include <util.h>
55#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070056#ifdef __linux__
57#include <pty.h>
58#include <malloc.h>
59#include <linux/rtc.h>
60#endif
61#endif
62#endif
63
64#ifdef _WIN32
65#include <windows.h>
66#include <malloc.h>
67#include <sys/timeb.h>
68#include <mmsystem.h>
69#define getopt_long_only getopt_long
70#define memalign(align, size) malloc(size)
71#endif
72
73#include "qemu-common.h"
74#include "hw/hw.h"
David 'Digit' Turnercc330d42013-12-14 23:26:42 +010075#include "net/net.h"
David 'Digit' Turner6af67652013-12-14 23:49:32 +010076#include "monitor/monitor.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010077#include "sysemu/sysemu.h"
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +010078#include "qemu/iov.h"
David 'Digit' Turner7a78db72013-12-14 11:46:01 +010079#include "qemu/timer.h"
David 'Digit' Turnere7216d82013-12-15 00:51:13 +010080#include "sysemu/char.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010081#include "sysemu/blockdev.h"
David 'Digit' Turnere1e03df2013-12-15 00:42:21 +010082#include "block/block.h"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070083#include "audio/audio.h"
David 'Digit' Turner28a09b62013-12-15 00:16:00 +010084#include "migration/migration.h"
David 'Digit' Turnerd0edecb2013-12-17 09:32:26 +010085#include "qemu/sockets.h"
David 'Digit' Turner031d6552013-12-15 00:52:36 +010086#include "qemu/queue.h"
David 'Digit' Turner28a09b62013-12-15 00:16:00 +010087#include "migration/qemu-file.h"
Tim Baverstock622b8f42010-12-07 11:36:59 +000088#include "android/snapshot.h"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070089
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070090
91#define SELF_ANNOUNCE_ROUNDS 5
David 'Digit' Turner986acc92011-05-10 16:50:01 +020092
93#ifndef ETH_P_RARP
94#define ETH_P_RARP 0x8035
95#endif
96#define ARP_HTYPE_ETH 0x0001
97#define ARP_PTYPE_IP 0x0800
98#define ARP_OP_REQUEST_REV 0x3
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070099
David 'Digit' Turner5973c772011-05-10 07:06:00 +0200100static int announce_self_create(uint8_t *buf,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700101 uint8_t *mac_addr)
102{
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200103 /* Ethernet header. */
104 memset(buf, 0xff, 6); /* destination MAC addr */
105 memcpy(buf + 6, mac_addr, 6); /* source MAC addr */
106 *(uint16_t *)(buf + 12) = htons(ETH_P_RARP); /* ethertype */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700107
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200108 /* RARP header. */
109 *(uint16_t *)(buf + 14) = htons(ARP_HTYPE_ETH); /* hardware addr space */
110 *(uint16_t *)(buf + 16) = htons(ARP_PTYPE_IP); /* protocol addr space */
111 *(buf + 18) = 6; /* hardware addr length (ethernet) */
112 *(buf + 19) = 4; /* protocol addr length (IPv4) */
113 *(uint16_t *)(buf + 20) = htons(ARP_OP_REQUEST_REV); /* opcode */
114 memcpy(buf + 22, mac_addr, 6); /* source hw addr */
115 memset(buf + 28, 0x00, 4); /* source protocol addr */
116 memcpy(buf + 32, mac_addr, 6); /* target hw addr */
117 memset(buf + 38, 0x00, 4); /* target protocol addr */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700118
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200119 /* Padding to get up to 60 bytes (ethernet min packet size, minus FCS). */
120 memset(buf + 42, 0x00, 18);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700121
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200122 return 60; /* len (FCS will be added by hardware) */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700123}
124
125static void qemu_announce_self_once(void *opaque)
126{
127 int i, len;
128 VLANState *vlan;
129 VLANClientState *vc;
130 uint8_t buf[256];
131 static int count = SELF_ANNOUNCE_ROUNDS;
132 QEMUTimer *timer = *(QEMUTimer **)opaque;
133
134 for (i = 0; i < MAX_NICS; i++) {
135 if (!nd_table[i].used)
136 continue;
137 len = announce_self_create(buf, nd_table[i].macaddr);
138 vlan = nd_table[i].vlan;
139 for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
140 vc->receive(vc, buf, len);
141 }
142 }
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200143 if (--count) {
144 /* delay 50ms, 150ms, 250ms, ... */
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100145 timer_mod(timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) +
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200146 50 + (SELF_ANNOUNCE_ROUNDS - count - 1) * 100);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700147 } else {
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100148 timer_del(timer);
149 timer_free(timer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700150 }
151}
152
153void qemu_announce_self(void)
154{
155 static QEMUTimer *timer;
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +0100156 timer = timer_new_ms(QEMU_CLOCK_REALTIME, qemu_announce_self_once, &timer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700157 qemu_announce_self_once(&timer);
158}
159
160/***********************************************************/
161/* savevm/loadvm support */
162
163#define IO_BUF_SIZE 32768
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100164#define MAX_IOV_SIZE MIN(IOV_MAX, 64)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700165
166struct QEMUFile {
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100167 const QEMUFileOps *ops;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700168 void *opaque;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700169
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100170 int64_t bytes_xfer;
171 int64_t xfer_limit;
172
173 int64_t pos; /* start of buffer when writing, end of buffer
174 when reading */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700175 int buf_index;
176 int buf_size; /* 0 when writing */
177 uint8_t buf[IO_BUF_SIZE];
178
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100179 struct iovec iov[MAX_IOV_SIZE];
180 unsigned int iovcnt;
181
182 int last_error;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700183};
184
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200185typedef struct QEMUFileStdio
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700186{
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200187 FILE *stdio_file;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700188 QEMUFile *file;
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200189} QEMUFileStdio;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700190
191typedef struct QEMUFileSocket
192{
193 int fd;
194 QEMUFile *file;
195} QEMUFileSocket;
196
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100197static ssize_t socket_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
198 int64_t pos)
199{
200 QEMUFileSocket *s = opaque;
201 ssize_t len;
202 ssize_t size = iov_size(iov, iovcnt);
203
204 len = iov_send(s->fd, iov, iovcnt, 0, size);
205 if (len < size) {
206 len = -socket_error();
207 }
208 return len;
209}
210
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100211static int socket_get_fd(void *opaque)
212{
213 QEMUFileSocket *s = opaque;
214
215 return s->fd;
216}
217
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200218static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700219{
220 QEMUFileSocket *s = opaque;
221 ssize_t len;
222
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100223 for (;;) {
224 len = qemu_recv(s->fd, buf, size, 0);
225 if (len != -1) {
226 break;
227 }
228#ifndef CONFIG_ANDROID
229 if (socket_error() == EAGAIN) {
230 yield_until_fd_readable(s->fd);
231 } else if (socket_error() != EINTR) {
232 break;
233 }
234#else
235 if (socket_error() != EINTR)
236 break;
237#endif
238 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700239
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100240 if (len == -1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700241 len = -socket_error();
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100242 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700243 return len;
244}
245
246static int file_socket_close(void *opaque)
247{
248 QEMUFileSocket *s = opaque;
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100249 if (s->fd >= 0)
250 socket_close(s->fd);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100251 g_free(s);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700252 return 0;
253}
254
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100255static int stdio_get_fd(void *opaque)
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100256{
257 QEMUFileStdio *s = opaque;
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100258
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100259 return fileno(s->stdio_file);
260}
261
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200262static int stdio_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700263{
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200264 QEMUFileStdio *s = opaque;
265 return fwrite(buf, 1, size, s->stdio_file);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700266}
267
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200268static int stdio_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700269{
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200270 QEMUFileStdio *s = opaque;
271 FILE *fp = s->stdio_file;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700272 int bytes;
273
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100274 for (;;) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700275 clearerr(fp);
276 bytes = fread(buf, 1, size, fp);
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100277 if (bytes != 0 || !ferror(fp)) {
278 break;
279 }
280#ifndef CONFIG_ANDROID
281 if (errno == EAGAIN) {
282 yield_until_fd_readable(fileno(fp));
283 } else if (errno != EINTR) {
284 break;
285 }
286#else
287 if (errno != EINTR)
288 break;
289#endif
290 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700291 return bytes;
292}
293
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200294static int stdio_pclose(void *opaque)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700295{
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200296 QEMUFileStdio *s = opaque;
297 int ret;
298 ret = pclose(s->stdio_file);
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100299 if (ret == -1) {
300 ret = -errno;
301 } else if (!WIFEXITED(ret) || WEXITSTATUS(ret) != 0) {
302 /* close succeeded, but non-zero exit code: */
303 ret = -EIO; /* fake errno value */
304 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100305 g_free(s);
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200306 return ret;
307}
308
309static int stdio_fclose(void *opaque)
310{
311 QEMUFileStdio *s = opaque;
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100312 int ret = 0;
313
314 if (s->file->ops->put_buffer || s->file->ops->writev_buffer) {
315 int fd = fileno(s->stdio_file);
316 struct stat st;
317
318 ret = fstat(fd, &st);
319 if (ret == 0 && S_ISREG(st.st_mode)) {
320 /*
321 * If the file handle is a regular file make sure the
322 * data is flushed to disk before signaling success.
323 */
324 ret = fsync(fd);
325 if (ret != 0) {
326 ret = -errno;
327 return ret;
328 }
329 }
330 }
331 if (fclose(s->stdio_file) == EOF) {
332 ret = -errno;
333 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100334 g_free(s);
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100335 return ret;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700336}
337
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100338static const QEMUFileOps stdio_pipe_read_ops = {
339 .get_fd = stdio_get_fd,
340 .get_buffer = stdio_get_buffer,
341 .close = stdio_pclose
342};
343
344static const QEMUFileOps stdio_pipe_write_ops = {
345 .get_fd = stdio_get_fd,
346 .put_buffer = stdio_put_buffer,
347 .close = stdio_pclose
348};
349
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100350QEMUFile *qemu_popen_cmd(const char *command, const char *mode)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700351{
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100352 FILE *stdio_file;
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200353 QEMUFileStdio *s;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700354
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100355 if (mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700356 fprintf(stderr, "qemu_popen: Argument validity check failed\n");
357 return NULL;
358 }
359
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100360 stdio_file = popen(command, mode);
361 if (stdio_file == NULL) {
362 return NULL;
363 }
364
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100365 s = g_malloc0(sizeof(QEMUFileStdio));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700366
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200367 s->stdio_file = stdio_file;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700368
369 if(mode[0] == 'r') {
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100370 s->file = qemu_fopen_ops(s, &stdio_pipe_read_ops);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700371 } else {
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100372 s->file = qemu_fopen_ops(s, &stdio_pipe_write_ops);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700373 }
374 return s->file;
375}
376
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100377static const QEMUFileOps stdio_file_read_ops = {
378 .get_fd = stdio_get_fd,
379 .get_buffer = stdio_get_buffer,
380 .close = stdio_fclose
381};
382
383static const QEMUFileOps stdio_file_write_ops = {
384 .get_fd = stdio_get_fd,
385 .put_buffer = stdio_put_buffer,
386 .close = stdio_fclose
387};
388
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100389static ssize_t unix_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
390 int64_t pos)
391{
392 QEMUFileSocket *s = opaque;
393 ssize_t len, offset;
394 ssize_t size = iov_size(iov, iovcnt);
395 ssize_t total = 0;
396
397 assert(iovcnt > 0);
398 offset = 0;
399 while (size > 0) {
400 /* Find the next start position; skip all full-sized vector elements */
401 while (offset >= iov[0].iov_len) {
402 offset -= iov[0].iov_len;
403 iov++, iovcnt--;
404 }
405
406 /* skip `offset' bytes from the (now) first element, undo it on exit */
407 assert(iovcnt > 0);
408 iov[0].iov_base += offset;
409 iov[0].iov_len -= offset;
410
411 do {
412 len = writev(s->fd, iov, iovcnt);
413 } while (len == -1 && errno == EINTR);
414 if (len == -1) {
415 return -errno;
416 }
417
418 /* Undo the changes above */
419 iov[0].iov_base -= offset;
420 iov[0].iov_len += offset;
421
422 /* Prepare for the next iteration */
423 offset += len;
424 total += len;
425 size -= len;
426 }
427
428 return total;
429}
430
431static int unix_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
432{
433 QEMUFileSocket *s = opaque;
434 ssize_t len;
435
436 for (;;) {
437 len = read(s->fd, buf, size);
438 if (len != -1) {
439 break;
440 }
441 if (errno == EAGAIN) {
442 yield_until_fd_readable(s->fd);
443 } else if (errno != EINTR) {
444 break;
445 }
446 }
447
448 if (len == -1) {
449 len = -errno;
450 }
451 return len;
452}
453
454static int unix_close(void *opaque)
455{
456 QEMUFileSocket *s = opaque;
457 close(s->fd);
458 g_free(s);
459 return 0;
460}
461
462static const QEMUFileOps unix_read_ops = {
463 .get_fd = socket_get_fd,
464 .get_buffer = unix_get_buffer,
465 .close = unix_close
466};
467
468static const QEMUFileOps unix_write_ops = {
469 .get_fd = socket_get_fd,
470 .writev_buffer = unix_writev_buffer,
471 .close = unix_close
472};
473
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200474QEMUFile *qemu_fdopen(int fd, const char *mode)
475{
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100476 QEMUFileSocket *s;
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200477
478 if (mode == NULL ||
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100479 (mode[0] != 'r' && mode[0] != 'w') ||
480 mode[1] != 'b' || mode[2] != 0) {
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200481 fprintf(stderr, "qemu_fdopen: Argument validity check failed\n");
482 return NULL;
483 }
484
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100485 s = g_malloc0(sizeof(QEMUFileSocket));
486 s->fd = fd;
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200487
488 if(mode[0] == 'r') {
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100489 s->file = qemu_fopen_ops(s, &unix_read_ops);
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200490 } else {
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100491 s->file = qemu_fopen_ops(s, &unix_write_ops);
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200492 }
493 return s->file;
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200494}
495
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100496static const QEMUFileOps socket_read_ops = {
497 .get_fd = socket_get_fd,
498 .get_buffer = socket_get_buffer,
499 .close = file_socket_close
500};
501
502static const QEMUFileOps socket_write_ops = {
503 .get_fd = socket_get_fd,
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100504 .writev_buffer = socket_writev_buffer,
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100505 .close = file_socket_close
506};
507
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100508bool qemu_file_mode_is_not_valid(const char *mode)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700509{
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100510 if (mode == NULL ||
511 (mode[0] != 'r' && mode[0] != 'w') ||
512 mode[1] != 'b' || mode[2] != 0) {
513 fprintf(stderr, "qemu_fopen: Argument validity check failed\n");
514 return true;
515 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700516
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100517 return false;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700518}
519
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100520QEMUFile *qemu_fopen_socket(int fd, const char *mode)
521{
522 QEMUFileSocket *s;
523
524 if (qemu_file_mode_is_not_valid(mode)) {
525 return NULL;
526 }
527
528 s = g_malloc0(sizeof(QEMUFileSocket));
529 s->fd = fd;
530 if (mode[0] == 'w') {
531 qemu_set_block(s->fd);
532 s->file = qemu_fopen_ops(s, &socket_write_ops);
533 } else {
534 s->file = qemu_fopen_ops(s, &socket_read_ops);
535 }
536 return s->file;
537}
538
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700539QEMUFile *qemu_fopen(const char *filename, const char *mode)
540{
541 QEMUFileStdio *s;
542
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100543 if (qemu_file_mode_is_not_valid(mode)) {
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200544 return NULL;
545 }
546
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100547 s = g_malloc0(sizeof(QEMUFileStdio));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700548
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200549 s->stdio_file = fopen(filename, mode);
550 if (!s->stdio_file)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700551 goto fail;
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100552
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200553 if(mode[0] == 'w') {
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100554 s->file = qemu_fopen_ops(s, &stdio_file_write_ops);
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200555 } else {
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100556 s->file = qemu_fopen_ops(s, &stdio_file_read_ops);
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200557 }
558 return s->file;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700559fail:
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100560 g_free(s);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700561 return NULL;
562}
563
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100564#ifndef CONFIG_ANDROID
565// TODO(digit): Once bdrv_writev_vmstate() is implemented.
566static ssize_t block_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
567 int64_t pos)
568{
569 int ret;
570 QEMUIOVector qiov;
571
572 qemu_iovec_init_external(&qiov, iov, iovcnt);
573 ret = bdrv_writev_vmstate(opaque, &qiov, pos);
574 if (ret < 0) {
575 return ret;
576 }
577
578 return qiov.size;
579}
580#endif
581
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700582static int block_put_buffer(void *opaque, const uint8_t *buf,
583 int64_t pos, int size)
584{
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200585 bdrv_save_vmstate(opaque, buf, pos, size);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700586 return size;
587}
588
589static int block_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
590{
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200591 return bdrv_load_vmstate(opaque, buf, pos, size);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700592}
593
594static int bdrv_fclose(void *opaque)
595{
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100596 // TODO(digit): bdrv_flush() should return error code.
597 bdrv_flush(opaque);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700598 return 0;
599}
600
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100601static const QEMUFileOps bdrv_read_ops = {
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100602 .get_buffer = block_get_buffer,
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100603 .close = bdrv_fclose
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100604};
605
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100606static const QEMUFileOps bdrv_write_ops = {
607 .put_buffer = block_put_buffer,
608 //.writev_buffer = block_writev_buffer,
609 .close = bdrv_fclose
David 'Digit' Turner0e051542014-01-23 02:41:42 +0100610};
611
David 'Digit' Turner986acc92011-05-10 16:50:01 +0200612static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700613{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700614 if (is_writable)
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100615 return qemu_fopen_ops(bs, &bdrv_write_ops);
616 return qemu_fopen_ops(bs, &bdrv_read_ops);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700617}
618
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100619QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700620{
621 QEMUFile *f;
622
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100623 f = g_malloc0(sizeof(QEMUFile));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700624
625 f->opaque = opaque;
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100626 f->ops = ops;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700627 return f;
628}
629
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100630/*
631 * Get last error for stream f
632 *
633 * Return negative error value if there has been an error on previous
634 * operations, return 0 if no error happened.
635 *
636 */
637int qemu_file_get_error(QEMUFile *f)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700638{
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100639 return f->last_error;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700640}
641
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100642void qemu_file_set_error(QEMUFile *f, int ret)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700643{
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100644 if (f->last_error == 0) {
645 f->last_error = ret;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700646 }
647}
648
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100649static inline bool qemu_file_is_writable(QEMUFile *f)
650{
651 return f->ops->writev_buffer || f->ops->put_buffer;
652}
653
654/**
655 * Flushes QEMUFile buffer
656 *
657 * If there is writev_buffer QEMUFileOps it uses it otherwise uses
658 * put_buffer ops.
659 */
660void qemu_fflush(QEMUFile *f)
661{
662 ssize_t ret = 0;
663
664 if (!qemu_file_is_writable(f)) {
665 return;
666 }
667
668 if (f->ops->writev_buffer) {
669 if (f->iovcnt > 0) {
670 ret = f->ops->writev_buffer(f->opaque, f->iov, f->iovcnt, f->pos);
671 }
672 } else {
673 if (f->buf_index > 0) {
674 ret = f->ops->put_buffer(f->opaque, f->buf, f->pos, f->buf_index);
675 }
676 }
677 if (ret >= 0) {
678 f->pos += ret;
679 }
680 f->buf_index = 0;
681 f->iovcnt = 0;
682 if (ret < 0) {
683 qemu_file_set_error(f, ret);
684 }
685}
686
687#ifndef CONFIG_ANDROID
688// TODO(digit).
689void ram_control_before_iterate(QEMUFile *f, uint64_t flags)
690{
691 int ret = 0;
692
693 if (f->ops->before_ram_iterate) {
694 ret = f->ops->before_ram_iterate(f, f->opaque, flags);
695 if (ret < 0) {
696 qemu_file_set_error(f, ret);
697 }
698 }
699}
700
701void ram_control_after_iterate(QEMUFile *f, uint64_t flags)
702{
703 int ret = 0;
704
705 if (f->ops->after_ram_iterate) {
706 ret = f->ops->after_ram_iterate(f, f->opaque, flags);
707 if (ret < 0) {
708 qemu_file_set_error(f, ret);
709 }
710 }
711}
712
713void ram_control_load_hook(QEMUFile *f, uint64_t flags)
714{
715 int ret = -EINVAL;
716
717 if (f->ops->hook_ram_load) {
718 ret = f->ops->hook_ram_load(f, f->opaque, flags);
719 if (ret < 0) {
720 qemu_file_set_error(f, ret);
721 }
722 } else {
723 qemu_file_set_error(f, ret);
724 }
725}
726
727size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
728 ram_addr_t offset, size_t size, int *bytes_sent)
729{
730 if (f->ops->save_page) {
731 int ret = f->ops->save_page(f, f->opaque, block_offset,
732 offset, size, bytes_sent);
733
734 if (ret != RAM_SAVE_CONTROL_DELAYED) {
735 if (bytes_sent && *bytes_sent > 0) {
736 qemu_update_position(f, *bytes_sent);
737 } else if (ret < 0) {
738 qemu_file_set_error(f, ret);
739 }
740 }
741
742 return ret;
743 }
744
745 return RAM_SAVE_CONTROL_NOT_SUPP;
746}
747#endif // !CONFIG_ANDROID
748
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700749static void qemu_fill_buffer(QEMUFile *f)
750{
751 int len;
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100752 int pending;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700753
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100754 assert(!qemu_file_is_writable(f));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700755
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100756 pending = f->buf_size - f->buf_index;
757 if (pending > 0) {
758 memmove(f->buf, f->buf + f->buf_index, pending);
759 }
760 f->buf_index = 0;
761 f->buf_size = pending;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700762
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100763 len = f->ops->get_buffer(f->opaque, f->buf + pending, f->pos,
764 IO_BUF_SIZE - pending);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700765 if (len > 0) {
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100766 f->buf_size += len;
767 f->pos += len;
768 } else if (len == 0) {
769 qemu_file_set_error(f, -EIO);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700770 } else if (len != -EAGAIN)
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100771 qemu_file_set_error(f, len);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700772}
773
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100774int qemu_get_fd(QEMUFile *f)
775{
776 if (f->ops->get_fd) {
777 return f->ops->get_fd(f->opaque);
778 }
779 return -1;
780}
781
782void qemu_update_position(QEMUFile *f, size_t size)
783{
784 f->pos += size;
785}
786
787/** Closes the file
788 *
789 * Returns negative error value if any error happened on previous operations or
790 * while closing the file. Returns 0 or positive number on success.
791 *
792 * The meaning of return value on success depends on the specific backend
793 * being used.
794 */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700795int qemu_fclose(QEMUFile *f)
796{
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100797 int ret;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700798 qemu_fflush(f);
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100799 ret = qemu_file_get_error(f);
800
801 if (f->ops->close) {
802 int ret2 = f->ops->close(f->opaque);
803 if (ret >= 0) {
804 ret = ret2;
805 }
806 }
807 /* If any error was spotted before closing, we should report it
808 * instead of the close() return value.
809 */
810 if (f->last_error) {
811 ret = f->last_error;
812 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100813 g_free(f);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700814 return ret;
815}
816
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100817static void add_to_iovec(QEMUFile *f, const uint8_t *buf, int size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700818{
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100819 /* check for adjacent buffer and coalesce them */
820 if (f->iovcnt > 0 && buf == f->iov[f->iovcnt - 1].iov_base +
821 f->iov[f->iovcnt - 1].iov_len) {
822 f->iov[f->iovcnt - 1].iov_len += size;
823 } else {
824 f->iov[f->iovcnt].iov_base = (uint8_t *)buf;
825 f->iov[f->iovcnt++].iov_len = size;
826 }
827
828 if (f->iovcnt >= MAX_IOV_SIZE) {
829 qemu_fflush(f);
830 }
831}
832
833void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, int size)
834{
835 if (!f->ops->writev_buffer) {
836 qemu_put_buffer(f, buf, size);
837 return;
838 }
839
840 if (f->last_error) {
841 return;
842 }
843
844 f->bytes_xfer += size;
845 add_to_iovec(f, buf, size);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700846}
847
848void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
849{
850 int l;
851
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100852 if (f->last_error) {
853 return;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700854 }
855
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100856 while (size > 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700857 l = IO_BUF_SIZE - f->buf_index;
858 if (l > size)
859 l = size;
860 memcpy(f->buf + f->buf_index, buf, l);
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100861 f->bytes_xfer += l;
862 if (f->ops->writev_buffer) {
863 add_to_iovec(f, f->buf + f->buf_index, l);
864 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700865 f->buf_index += l;
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100866 if (f->buf_index == IO_BUF_SIZE) {
867 qemu_fflush(f);
868 }
869 if (qemu_file_get_error(f)) {
870 break;
871 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700872 buf += l;
873 size -= l;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700874 }
875}
876
877void qemu_put_byte(QEMUFile *f, int v)
878{
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100879 if (f->last_error) {
880 return;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700881 }
882
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100883 f->buf[f->buf_index] = v;
884 f->bytes_xfer++;
885 if (f->ops->writev_buffer) {
886 add_to_iovec(f, f->buf + f->buf_index, 1);
887 }
888 f->buf_index++;
889 if (f->buf_index == IO_BUF_SIZE) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700890 qemu_fflush(f);
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100891 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700892}
893
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100894static void qemu_file_skip(QEMUFile *f, int size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700895{
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100896 if (f->buf_index + size <= f->buf_size) {
897 f->buf_index += size;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700898 }
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100899}
900
901static int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset)
902{
903 int pending;
904 int index;
905
906 assert(!qemu_file_is_writable(f));
907
908 index = f->buf_index + offset;
909 pending = f->buf_size - index;
910 if (pending < size) {
911 qemu_fill_buffer(f);
912 index = f->buf_index + offset;
913 pending = f->buf_size - index;
914 }
915
916 if (pending <= 0) {
917 return 0;
918 }
919 if (size > pending) {
920 size = pending;
921 }
922
923 memcpy(buf, f->buf + index, size);
924 return size;
925}
926
927int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
928{
929 int pending = size;
930 int done = 0;
931
932 while (pending > 0) {
933 int res;
934
935 res = qemu_peek_buffer(f, buf, pending, 0);
936 if (res == 0) {
937 return done;
938 }
939 qemu_file_skip(f, res);
940 buf += res;
941 pending -= res;
942 done += res;
943 }
944 return done;
945}
946
947static int qemu_peek_byte(QEMUFile *f, int offset)
948{
949 int index = f->buf_index + offset;
950
951 assert(!qemu_file_is_writable(f));
952
953 if (index >= f->buf_size) {
954 qemu_fill_buffer(f);
955 index = f->buf_index + offset;
956 if (index >= f->buf_size) {
957 return 0;
958 }
959 }
960 return f->buf[index];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700961}
962
963int qemu_get_byte(QEMUFile *f)
964{
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100965 int result;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700966
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +0100967 result = qemu_peek_byte(f, 0);
968 qemu_file_skip(f, 1);
969 return result;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700970}
971
David 'Digit' Turner3e92c2d2011-10-11 03:02:41 +0200972#ifdef CONFIG_ANDROID
973void qemu_put_string(QEMUFile *f, const char* str)
974{
975 /* We will encode NULL and the empty string in the same way */
976 int slen;
977 if (str == NULL) {
978 str = "";
979 }
980 slen = strlen(str);
981 qemu_put_be32(f, slen);
982 qemu_put_buffer(f, (const uint8_t*)str, slen);
983}
984
985char* qemu_get_string(QEMUFile *f)
986{
987 int slen = qemu_get_be32(f);
988 char* str;
989 if (slen == 0)
990 return NULL;
991
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100992 str = g_malloc(slen+1);
David 'Digit' Turner3e92c2d2011-10-11 03:02:41 +0200993 if (qemu_get_buffer(f, (uint8_t*)str, slen) != slen) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100994 g_free(str);
David 'Digit' Turner3e92c2d2011-10-11 03:02:41 +0200995 return NULL;
996 }
997 str[slen] = '\0';
998 return str;
999}
1000#endif
1001
1002
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001003int64_t qemu_ftell(QEMUFile *f)
1004{
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +01001005 qemu_fflush(f);
1006 return f->pos;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001007}
1008
1009int qemu_file_rate_limit(QEMUFile *f)
1010{
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +01001011 if (qemu_file_get_error(f)) {
1012 return 1;
1013 }
1014 if (f->xfer_limit > 0 && f->bytes_xfer > f->xfer_limit) {
1015 return 1;
1016 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001017 return 0;
1018}
1019
David 'Digit' Turner986acc92011-05-10 16:50:01 +02001020int64_t qemu_file_get_rate_limit(QEMUFile *f)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001021{
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +01001022 return f->xfer_limit;
David 'Digit' Turner986acc92011-05-10 16:50:01 +02001023}
1024
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +01001025void qemu_file_set_rate_limit(QEMUFile *f, int64_t limit)
David 'Digit' Turner986acc92011-05-10 16:50:01 +02001026{
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +01001027 f->xfer_limit = limit;
1028}
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001029
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +01001030void qemu_file_reset_rate_limit(QEMUFile *f)
1031{
1032 f->bytes_xfer = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001033}
1034
1035void qemu_put_be16(QEMUFile *f, unsigned int v)
1036{
1037 qemu_put_byte(f, v >> 8);
1038 qemu_put_byte(f, v);
1039}
1040
1041void qemu_put_be32(QEMUFile *f, unsigned int v)
1042{
1043 qemu_put_byte(f, v >> 24);
1044 qemu_put_byte(f, v >> 16);
1045 qemu_put_byte(f, v >> 8);
1046 qemu_put_byte(f, v);
1047}
1048
1049void qemu_put_be64(QEMUFile *f, uint64_t v)
1050{
1051 qemu_put_be32(f, v >> 32);
1052 qemu_put_be32(f, v);
1053}
1054
1055unsigned int qemu_get_be16(QEMUFile *f)
1056{
1057 unsigned int v;
1058 v = qemu_get_byte(f) << 8;
1059 v |= qemu_get_byte(f);
1060 return v;
1061}
1062
1063unsigned int qemu_get_be32(QEMUFile *f)
1064{
1065 unsigned int v;
1066 v = qemu_get_byte(f) << 24;
1067 v |= qemu_get_byte(f) << 16;
1068 v |= qemu_get_byte(f) << 8;
1069 v |= qemu_get_byte(f);
1070 return v;
1071}
1072
1073uint64_t qemu_get_be64(QEMUFile *f)
1074{
1075 uint64_t v;
1076 v = (uint64_t)qemu_get_be32(f) << 32;
1077 v |= qemu_get_be32(f);
1078 return v;
1079}
1080
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +01001081
1082/* timer */
1083
1084void timer_put(QEMUFile *f, QEMUTimer *ts)
1085{
1086 uint64_t expire_time;
1087
1088 expire_time = timer_expire_time_ns(ts);
1089 qemu_put_be64(f, expire_time);
1090}
1091
1092void timer_get(QEMUFile *f, QEMUTimer *ts)
1093{
1094 uint64_t expire_time;
1095
1096 expire_time = qemu_get_be64(f);
1097 if (expire_time != -1) {
1098 timer_mod_ns(ts, expire_time);
1099 } else {
1100 timer_del(ts);
1101 }
1102}
1103
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001104void qemu_put_struct(QEMUFile* f, const QField* fields, const void* s)
1105{
1106 const QField* qf = fields;
1107
Ot ten Thije7fd67eb2010-07-29 10:26:01 +01001108 /* Iterate over struct fields */
1109 while (qf->type != Q_FIELD_END) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001110 uint8_t* p = (uint8_t*)s + qf->offset;
1111
1112 switch (qf->type) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001113 case Q_FIELD_BYTE:
1114 qemu_put_byte(f, p[0]);
1115 break;
1116 case Q_FIELD_INT16:
1117 qemu_put_be16(f, ((uint16_t*)p)[0]);
1118 break;
1119 case Q_FIELD_INT32:
1120 qemu_put_be32(f, ((uint32_t*)p)[0]);
1121 break;
1122 case Q_FIELD_INT64:
1123 qemu_put_be64(f, ((uint64_t*)p)[0]);
1124 break;
1125 case Q_FIELD_BUFFER:
Ot ten Thije7fd67eb2010-07-29 10:26:01 +01001126 if (qf[1].type != Q_FIELD_BUFFER_SIZE ||
1127 qf[2].type != Q_FIELD_BUFFER_SIZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001128 {
1129 fprintf(stderr, "%s: invalid QFIELD_BUFFER item passed as argument. aborting\n",
1130 __FUNCTION__ );
1131 exit(1);
1132 }
1133 else
1134 {
Ot ten Thije7fd67eb2010-07-29 10:26:01 +01001135 uint32_t size = ((uint32_t)qf[1].offset << 16) | (uint32_t)qf[2].offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001136
1137 qemu_put_buffer(f, p, size);
1138 qf += 2;
1139 }
1140 break;
1141 default:
1142 fprintf(stderr, "%s: invalid fields list passed as argument. aborting\n", __FUNCTION__);
1143 exit(1);
1144 }
1145 qf++;
1146 }
1147}
1148
1149int qemu_get_struct(QEMUFile* f, const QField* fields, void* s)
1150{
1151 const QField* qf = fields;
1152
Ot ten Thije7fd67eb2010-07-29 10:26:01 +01001153 /* Iterate over struct fields */
1154 while (qf->type != Q_FIELD_END) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001155 uint8_t* p = (uint8_t*)s + qf->offset;
1156
1157 switch (qf->type) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001158 case Q_FIELD_BYTE:
1159 p[0] = qemu_get_byte(f);
1160 break;
1161 case Q_FIELD_INT16:
1162 ((uint16_t*)p)[0] = qemu_get_be16(f);
1163 break;
1164 case Q_FIELD_INT32:
1165 ((uint32_t*)p)[0] = qemu_get_be32(f);
1166 break;
1167 case Q_FIELD_INT64:
1168 ((uint64_t*)p)[0] = qemu_get_be64(f);
1169 break;
1170 case Q_FIELD_BUFFER:
Ot ten Thije7fd67eb2010-07-29 10:26:01 +01001171 if (qf[1].type != Q_FIELD_BUFFER_SIZE ||
1172 qf[2].type != Q_FIELD_BUFFER_SIZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001173 {
1174 fprintf(stderr, "%s: invalid QFIELD_BUFFER item passed as argument.\n",
1175 __FUNCTION__ );
1176 return -1;
1177 }
1178 else
1179 {
Ot ten Thije7fd67eb2010-07-29 10:26:01 +01001180 uint32_t size = ((uint32_t)qf[1].offset << 16) | (uint32_t)qf[2].offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001181 int ret = qemu_get_buffer(f, p, size);
1182
1183 if (ret != size) {
1184 fprintf(stderr, "%s: not enough bytes to load structure\n", __FUNCTION__);
1185 return -1;
1186 }
1187 qf += 2;
1188 }
1189 break;
1190 default:
1191 fprintf(stderr, "%s: invalid fields list passed as argument. aborting\n", __FUNCTION__);
1192 exit(1);
1193 }
1194 qf++;
1195 }
1196 return 0;
1197}
1198
Ot ten Thije871da2a2010-09-20 10:29:22 +01001199/* write a float to file */
1200void qemu_put_float(QEMUFile *f, float v)
1201{
1202 uint8_t *bytes = (uint8_t*) &v;
1203 qemu_put_buffer(f, bytes, sizeof(float));
1204}
1205
1206/* read a float from file */
1207float qemu_get_float(QEMUFile *f)
1208{
1209 uint8_t bytes[sizeof(float)];
1210 qemu_get_buffer(f, bytes, sizeof(float));
1211
1212 return *((float*) bytes);
1213}
1214
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001215typedef struct SaveStateEntry {
1216 char idstr[256];
1217 int instance_id;
1218 int version_id;
1219 int section_id;
1220 SaveLiveStateHandler *save_live_state;
1221 SaveStateHandler *save_state;
1222 LoadStateHandler *load_state;
1223 void *opaque;
1224 struct SaveStateEntry *next;
1225} SaveStateEntry;
1226
1227static SaveStateEntry *first_se;
1228
1229/* TODO: Individual devices generally have very little idea about the rest
1230 of the system, so instance_id should be removed/replaced.
1231 Meanwhile pass -1 as instance_id if you do not already have a clearly
1232 distinguishing id for all instances of your device class. */
1233int register_savevm_live(const char *idstr,
1234 int instance_id,
1235 int version_id,
1236 SaveLiveStateHandler *save_live_state,
1237 SaveStateHandler *save_state,
1238 LoadStateHandler *load_state,
1239 void *opaque)
1240{
1241 SaveStateEntry *se, **pse;
1242 static int global_section_id;
1243
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001244 se = g_malloc(sizeof(SaveStateEntry));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001245 pstrcpy(se->idstr, sizeof(se->idstr), idstr);
1246 se->instance_id = (instance_id == -1) ? 0 : instance_id;
1247 se->version_id = version_id;
1248 se->section_id = global_section_id++;
1249 se->save_live_state = save_live_state;
1250 se->save_state = save_state;
1251 se->load_state = load_state;
1252 se->opaque = opaque;
1253 se->next = NULL;
1254
1255 /* add at the end of list */
1256 pse = &first_se;
1257 while (*pse != NULL) {
1258 if (instance_id == -1
1259 && strcmp(se->idstr, (*pse)->idstr) == 0
1260 && se->instance_id <= (*pse)->instance_id)
1261 se->instance_id = (*pse)->instance_id + 1;
1262 pse = &(*pse)->next;
1263 }
1264 *pse = se;
1265 return 0;
1266}
1267
1268int register_savevm(const char *idstr,
1269 int instance_id,
1270 int version_id,
1271 SaveStateHandler *save_state,
1272 LoadStateHandler *load_state,
1273 void *opaque)
1274{
1275 return register_savevm_live(idstr, instance_id, version_id,
1276 NULL, save_state, load_state, opaque);
1277}
1278
1279void unregister_savevm(const char *idstr, void *opaque)
1280{
1281 SaveStateEntry **pse;
1282
1283 pse = &first_se;
1284 while (*pse != NULL) {
1285 if (strcmp((*pse)->idstr, idstr) == 0 && (*pse)->opaque == opaque) {
1286 SaveStateEntry *next = (*pse)->next;
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001287 g_free(*pse);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001288 *pse = next;
1289 continue;
1290 }
1291 pse = &(*pse)->next;
1292 }
1293}
1294
1295#define QEMU_VM_FILE_MAGIC 0x5145564d
1296#define QEMU_VM_FILE_VERSION_COMPAT 0x00000002
David 'Digit' Turner3e92c2d2011-10-11 03:02:41 +02001297#define QEMU_VM_FILE_VERSION 0x00000004
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001298
1299#define QEMU_VM_EOF 0x00
1300#define QEMU_VM_SECTION_START 0x01
1301#define QEMU_VM_SECTION_PART 0x02
1302#define QEMU_VM_SECTION_END 0x03
1303#define QEMU_VM_SECTION_FULL 0x04
1304
1305int qemu_savevm_state_begin(QEMUFile *f)
1306{
1307 SaveStateEntry *se;
1308
1309 qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
1310 qemu_put_be32(f, QEMU_VM_FILE_VERSION);
1311
1312 for (se = first_se; se != NULL; se = se->next) {
1313 int len;
1314
1315 if (se->save_live_state == NULL)
1316 continue;
1317
1318 /* Section type */
1319 qemu_put_byte(f, QEMU_VM_SECTION_START);
1320 qemu_put_be32(f, se->section_id);
1321
1322 /* ID string */
1323 len = strlen(se->idstr);
1324 qemu_put_byte(f, len);
1325 qemu_put_buffer(f, (uint8_t *)se->idstr, len);
1326
1327 qemu_put_be32(f, se->instance_id);
1328 qemu_put_be32(f, se->version_id);
1329
1330 se->save_live_state(f, QEMU_VM_SECTION_START, se->opaque);
1331 }
1332
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +01001333 return qemu_file_get_error(f);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001334}
1335
1336int qemu_savevm_state_iterate(QEMUFile *f)
1337{
1338 SaveStateEntry *se;
1339 int ret = 1;
1340
1341 for (se = first_se; se != NULL; se = se->next) {
1342 if (se->save_live_state == NULL)
1343 continue;
1344
1345 /* Section type */
1346 qemu_put_byte(f, QEMU_VM_SECTION_PART);
1347 qemu_put_be32(f, se->section_id);
1348
1349 ret &= !!se->save_live_state(f, QEMU_VM_SECTION_PART, se->opaque);
1350 }
1351
1352 if (ret)
1353 return 1;
1354
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +01001355 return qemu_file_get_error(f);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001356}
1357
1358int qemu_savevm_state_complete(QEMUFile *f)
1359{
1360 SaveStateEntry *se;
1361
1362 for (se = first_se; se != NULL; se = se->next) {
1363 if (se->save_live_state == NULL)
1364 continue;
1365
1366 /* Section type */
1367 qemu_put_byte(f, QEMU_VM_SECTION_END);
1368 qemu_put_be32(f, se->section_id);
1369
1370 se->save_live_state(f, QEMU_VM_SECTION_END, se->opaque);
1371 }
1372
1373 for(se = first_se; se != NULL; se = se->next) {
1374 int len;
1375
Ot ten Thije8f2de6d2010-09-30 14:17:10 +01001376 if (se->save_state == NULL)
1377 continue;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001378
1379 /* Section type */
1380 qemu_put_byte(f, QEMU_VM_SECTION_FULL);
1381 qemu_put_be32(f, se->section_id);
1382
1383 /* ID string */
1384 len = strlen(se->idstr);
1385 qemu_put_byte(f, len);
1386 qemu_put_buffer(f, (uint8_t *)se->idstr, len);
1387
1388 qemu_put_be32(f, se->instance_id);
1389 qemu_put_be32(f, se->version_id);
1390
1391 se->save_state(f, se->opaque);
1392 }
1393
1394 qemu_put_byte(f, QEMU_VM_EOF);
1395
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +01001396 return qemu_file_get_error(f);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001397}
1398
1399int qemu_savevm_state(QEMUFile *f)
1400{
1401 int saved_vm_running;
1402 int ret;
1403
1404 saved_vm_running = vm_running;
1405 vm_stop(0);
1406
1407 bdrv_flush_all();
1408
1409 ret = qemu_savevm_state_begin(f);
1410 if (ret < 0)
1411 goto out;
1412
1413 do {
1414 ret = qemu_savevm_state_iterate(f);
1415 if (ret < 0)
1416 goto out;
1417 } while (ret == 0);
1418
1419 ret = qemu_savevm_state_complete(f);
1420
1421out:
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +01001422 ret = qemu_file_get_error(f);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001423
1424 if (!ret && saved_vm_running)
1425 vm_start();
1426
1427 return ret;
1428}
1429
1430static SaveStateEntry *find_se(const char *idstr, int instance_id)
1431{
1432 SaveStateEntry *se;
1433
1434 for(se = first_se; se != NULL; se = se->next) {
1435 if (!strcmp(se->idstr, idstr) &&
1436 instance_id == se->instance_id)
1437 return se;
1438 }
1439 return NULL;
1440}
1441
1442typedef struct LoadStateEntry {
1443 SaveStateEntry *se;
1444 int section_id;
1445 int version_id;
1446 struct LoadStateEntry *next;
1447} LoadStateEntry;
1448
1449static int qemu_loadvm_state_v2(QEMUFile *f)
1450{
1451 SaveStateEntry *se;
1452 int len, ret, instance_id, record_len, version_id;
1453 int64_t total_len, end_pos, cur_pos;
1454 char idstr[256];
1455
1456 total_len = qemu_get_be64(f);
1457 end_pos = total_len + qemu_ftell(f);
1458 for(;;) {
1459 if (qemu_ftell(f) >= end_pos)
1460 break;
1461 len = qemu_get_byte(f);
1462 qemu_get_buffer(f, (uint8_t *)idstr, len);
1463 idstr[len] = '\0';
1464 instance_id = qemu_get_be32(f);
1465 version_id = qemu_get_be32(f);
1466 record_len = qemu_get_be32(f);
1467 cur_pos = qemu_ftell(f);
1468 se = find_se(idstr, instance_id);
1469 if (!se) {
1470 fprintf(stderr, "qemu: warning: instance 0x%x of device '%s' not present in current VM\n",
1471 instance_id, idstr);
1472 } else {
1473 ret = se->load_state(f, se->opaque, version_id);
1474 if (ret < 0) {
1475 fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n",
1476 instance_id, idstr);
1477 return ret;
1478 }
1479 }
1480 /* always seek to exact end of record */
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +01001481 qemu_file_skip(f, cur_pos + record_len - qemu_ftell(f));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001482 }
1483
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +01001484 return qemu_file_get_error(f);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001485}
1486
1487int qemu_loadvm_state(QEMUFile *f)
1488{
1489 LoadStateEntry *first_le = NULL;
1490 uint8_t section_type;
1491 unsigned int v;
1492 int ret;
1493
1494 v = qemu_get_be32(f);
1495 if (v != QEMU_VM_FILE_MAGIC)
1496 return -EINVAL;
1497
1498 v = qemu_get_be32(f);
1499 if (v == QEMU_VM_FILE_VERSION_COMPAT)
1500 return qemu_loadvm_state_v2(f);
David 'Digit' Turner3e92c2d2011-10-11 03:02:41 +02001501 if (v < QEMU_VM_FILE_VERSION) {
1502 fprintf(stderr, "Snapshot format %d is too old for this version of the emulator, please create a new one.\n", v);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001503 return -ENOTSUP;
David 'Digit' Turner3e92c2d2011-10-11 03:02:41 +02001504 } else if (v > QEMU_VM_FILE_VERSION) {
1505 fprintf(stderr, "Snapshot format %d is more recent than the emulator, please update your Android SDK Tools.\n", v);
1506 return -ENOTSUP;
1507 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001508
1509 while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) {
1510 uint32_t instance_id, version_id, section_id;
1511 LoadStateEntry *le;
1512 SaveStateEntry *se;
1513 char idstr[257];
1514 int len;
1515
1516 switch (section_type) {
1517 case QEMU_VM_SECTION_START:
1518 case QEMU_VM_SECTION_FULL:
1519 /* Read section start */
1520 section_id = qemu_get_be32(f);
1521 len = qemu_get_byte(f);
1522 qemu_get_buffer(f, (uint8_t *)idstr, len);
1523 idstr[len] = 0;
1524 instance_id = qemu_get_be32(f);
1525 version_id = qemu_get_be32(f);
1526
1527 /* Find savevm section */
1528 se = find_se(idstr, instance_id);
1529 if (se == NULL) {
1530 fprintf(stderr, "Unknown savevm section or instance '%s' %d\n", idstr, instance_id);
1531 ret = -EINVAL;
1532 goto out;
1533 }
1534
1535 /* Validate version */
1536 if (version_id > se->version_id) {
1537 fprintf(stderr, "savevm: unsupported version %d for '%s' v%d\n",
1538 version_id, idstr, se->version_id);
1539 ret = -EINVAL;
1540 goto out;
1541 }
1542
1543 /* Add entry */
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001544 le = g_malloc0(sizeof(*le));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001545
1546 le->se = se;
1547 le->section_id = section_id;
1548 le->version_id = version_id;
1549 le->next = first_le;
1550 first_le = le;
1551
Vladimir Chtchetkined0e28722011-10-05 14:25:07 -07001552 if (le->se->load_state(f, le->se->opaque, le->version_id)) {
1553 fprintf(stderr, "savevm: unable to load section %s\n", idstr);
1554 ret = -EINVAL;
1555 goto out;
1556 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001557 break;
1558 case QEMU_VM_SECTION_PART:
1559 case QEMU_VM_SECTION_END:
1560 section_id = qemu_get_be32(f);
1561
1562 for (le = first_le; le && le->section_id != section_id; le = le->next);
1563 if (le == NULL) {
1564 fprintf(stderr, "Unknown savevm section %d\n", section_id);
1565 ret = -EINVAL;
1566 goto out;
1567 }
1568
1569 le->se->load_state(f, le->se->opaque, le->version_id);
1570 break;
1571 default:
1572 fprintf(stderr, "Unknown savevm section type %d\n", section_type);
1573 ret = -EINVAL;
1574 goto out;
1575 }
1576 }
1577
1578 ret = 0;
1579
1580out:
1581 while (first_le) {
1582 LoadStateEntry *le = first_le;
1583 first_le = first_le->next;
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001584 g_free(le);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001585 }
1586
David 'Digit' Turnerc79de3c2014-01-23 04:17:24 +01001587 if (qemu_file_get_error(f))
1588 ret = qemu_file_get_error(f);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001589
1590 return ret;
1591}
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001592#if 0
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001593static BlockDriverState *get_bs_snapshots(void)
1594{
1595 BlockDriverState *bs;
1596 int i;
1597
1598 if (bs_snapshots)
1599 return bs_snapshots;
1600 for(i = 0; i <= nb_drives; i++) {
1601 bs = drives_table[i].bdrv;
1602 if (bdrv_can_snapshot(bs))
1603 goto ok;
1604 }
1605 return NULL;
1606 ok:
1607 bs_snapshots = bs;
1608 return bs;
1609}
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001610#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001611static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
1612 const char *name)
1613{
1614 QEMUSnapshotInfo *sn_tab, *sn;
1615 int nb_sns, i, ret;
1616
1617 ret = -ENOENT;
1618 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
1619 if (nb_sns < 0)
1620 return ret;
1621 for(i = 0; i < nb_sns; i++) {
1622 sn = &sn_tab[i];
1623 if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
1624 *sn_info = *sn;
1625 ret = 0;
1626 break;
1627 }
1628 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001629 g_free(sn_tab);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001630 return ret;
1631}
1632
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001633void do_savevm(Monitor *err, const char *name)
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001634{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001635 BlockDriverState *bs, *bs1;
1636 QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001637 int must_delete, ret;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001638 BlockDriverInfo bdi1, *bdi = &bdi1;
1639 QEMUFile *f;
1640 int saved_vm_running;
1641 uint32_t vm_state_size;
1642#ifdef _WIN32
1643 struct _timeb tb;
1644#else
1645 struct timeval tv;
1646#endif
1647
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001648 bs = bdrv_snapshots();
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001649 if (!bs) {
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001650 monitor_printf(err, "No block device can accept snapshots\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001651 return;
1652 }
1653
1654 /* ??? Should this occur after vm_stop? */
1655 qemu_aio_flush();
1656
1657 saved_vm_running = vm_running;
1658 vm_stop(0);
1659
1660 must_delete = 0;
1661 if (name) {
1662 ret = bdrv_snapshot_find(bs, old_sn, name);
1663 if (ret >= 0) {
1664 must_delete = 1;
1665 }
1666 }
1667 memset(sn, 0, sizeof(*sn));
1668 if (must_delete) {
1669 pstrcpy(sn->name, sizeof(sn->name), old_sn->name);
1670 pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);
1671 } else {
1672 if (name)
1673 pstrcpy(sn->name, sizeof(sn->name), name);
1674 }
1675
1676 /* fill auxiliary fields */
1677#ifdef _WIN32
1678 _ftime(&tb);
1679 sn->date_sec = tb.time;
1680 sn->date_nsec = tb.millitm * 1000000;
1681#else
1682 gettimeofday(&tv, NULL);
1683 sn->date_sec = tv.tv_sec;
1684 sn->date_nsec = tv.tv_usec * 1000;
1685#endif
David 'Digit' Turnerdcda9492014-02-16 15:13:55 +01001686 sn->vm_clock_nsec = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001687
1688 if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001689 monitor_printf(err, "Device %s does not support VM state snapshots\n",
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001690 bdrv_get_device_name(bs));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001691 goto the_end;
1692 }
1693
1694 /* save the VM state */
David 'Digit' Turner986acc92011-05-10 16:50:01 +02001695 f = qemu_fopen_bdrv(bs, 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001696 if (!f) {
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001697 monitor_printf(err, "Could not open VM state file\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001698 goto the_end;
1699 }
1700 ret = qemu_savevm_state(f);
1701 vm_state_size = qemu_ftell(f);
1702 qemu_fclose(f);
1703 if (ret < 0) {
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001704 monitor_printf(err, "Error %d while writing VM\n", ret);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001705 goto the_end;
1706 }
1707
1708 /* create the snapshots */
1709
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001710 bs1 = NULL;
1711 while ((bs1 = bdrv_next(bs1))) {
Ot ten Thije8f2de6d2010-09-30 14:17:10 +01001712 if (bdrv_can_snapshot(bs1)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001713 if (must_delete) {
1714 ret = bdrv_snapshot_delete(bs1, old_sn->id_str);
1715 if (ret < 0) {
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001716 monitor_printf(err,
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001717 "Error while deleting snapshot on '%s'\n",
1718 bdrv_get_device_name(bs1));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001719 }
1720 }
1721 /* Write VM state size only to the image that contains the state */
1722 sn->vm_state_size = (bs == bs1 ? vm_state_size : 0);
1723 ret = bdrv_snapshot_create(bs1, sn);
1724 if (ret < 0) {
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001725 monitor_printf(err, "Error while creating snapshot on '%s'\n",
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001726 bdrv_get_device_name(bs1));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001727 }
1728 }
1729 }
1730
1731 the_end:
1732 if (saved_vm_running)
1733 vm_start();
1734}
1735
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001736void do_loadvm(Monitor *err, const char *name)
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001737{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001738 BlockDriverState *bs, *bs1;
1739 BlockDriverInfo bdi1, *bdi = &bdi1;
1740 QEMUSnapshotInfo sn;
1741 QEMUFile *f;
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001742 int ret;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001743 int saved_vm_running;
1744
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001745 bs = bdrv_snapshots();
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001746 if (!bs) {
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001747 monitor_printf(err, "No block device supports snapshots\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001748 return;
1749 }
1750
1751 /* Flush all IO requests so they don't interfere with the new state. */
1752 qemu_aio_flush();
1753
1754 saved_vm_running = vm_running;
1755 vm_stop(0);
1756
Vladimir Chtchetkine05e07482012-02-03 10:02:50 -08001757 bs1 = bs;
1758 do {
Ot ten Thije8f2de6d2010-09-30 14:17:10 +01001759 if (bdrv_can_snapshot(bs1)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001760 ret = bdrv_snapshot_goto(bs1, name);
1761 if (ret < 0) {
1762 if (bs != bs1)
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001763 monitor_printf(err, "Warning: ");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001764 switch(ret) {
1765 case -ENOTSUP:
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001766 monitor_printf(err,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001767 "Snapshots not supported on device '%s'\n",
1768 bdrv_get_device_name(bs1));
1769 break;
1770 case -ENOENT:
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001771 monitor_printf(err, "Could not find snapshot '%s' on "
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001772 "device '%s'\n",
1773 name, bdrv_get_device_name(bs1));
1774 break;
1775 default:
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001776 monitor_printf(err, "Error %d while activating snapshot on"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001777 " '%s'\n", ret, bdrv_get_device_name(bs1));
1778 break;
1779 }
1780 /* fatal on snapshot block device */
1781 if (bs == bs1)
1782 goto the_end;
1783 }
1784 }
Vladimir Chtchetkine05e07482012-02-03 10:02:50 -08001785 } while ((bs1 = bdrv_next(bs)));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001786
1787 if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001788 monitor_printf(err, "Device %s does not support VM state snapshots\n",
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001789 bdrv_get_device_name(bs));
1790 return;
1791 }
1792
1793 /* Don't even try to load empty VM states */
1794 ret = bdrv_snapshot_find(bs, &sn, name);
1795 if ((ret >= 0) && (sn.vm_state_size == 0))
1796 goto the_end;
1797
1798 /* restore the VM state */
David 'Digit' Turner986acc92011-05-10 16:50:01 +02001799 f = qemu_fopen_bdrv(bs, 0);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001800 if (!f) {
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001801 monitor_printf(err, "Could not open VM state file\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001802 goto the_end;
1803 }
1804 ret = qemu_loadvm_state(f);
1805 qemu_fclose(f);
1806 if (ret < 0) {
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001807 monitor_printf(err, "Error %d while loading VM state\n", ret);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001808 }
1809 the_end:
1810 if (saved_vm_running)
1811 vm_start();
1812}
1813
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001814void do_delvm(Monitor *err, const char *name)
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001815{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001816 BlockDriverState *bs, *bs1;
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001817 int ret;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001818
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001819 bs = bdrv_snapshots();
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001820 if (!bs) {
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001821 monitor_printf(err, "No block device supports snapshots\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001822 return;
1823 }
1824
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001825 bs1 = NULL;
1826 while ((bs1 = bdrv_next(bs1))) {
Ot ten Thije8f2de6d2010-09-30 14:17:10 +01001827 if (bdrv_can_snapshot(bs1)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001828 ret = bdrv_snapshot_delete(bs1, name);
1829 if (ret < 0) {
1830 if (ret == -ENOTSUP)
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001831 monitor_printf(err,
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001832 "Snapshots not supported on device '%s'\n",
1833 bdrv_get_device_name(bs1));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001834 else
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001835 monitor_printf(err, "Error %d while deleting snapshot on "
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001836 "'%s'\n", ret, bdrv_get_device_name(bs1));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001837 }
1838 }
1839 }
1840}
1841
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001842void do_info_snapshots(Monitor* out, Monitor* err)
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001843{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001844 BlockDriverState *bs, *bs1;
1845 QEMUSnapshotInfo *sn_tab, *sn;
1846 int nb_sns, i;
1847 char buf[256];
1848
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001849 bs = bdrv_snapshots();
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001850 if (!bs) {
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001851 monitor_printf(err, "No available block device supports snapshots\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001852 return;
1853 }
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001854 monitor_printf(out, "Snapshot devices:");
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001855 bs1 = NULL;
1856 while ((bs1 = bdrv_next(bs1))) {
Ot ten Thije8f2de6d2010-09-30 14:17:10 +01001857 if (bdrv_can_snapshot(bs1)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001858 if (bs == bs1)
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001859 monitor_printf(out, " %s", bdrv_get_device_name(bs1));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001860 }
1861 }
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001862 monitor_printf(out, "\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001863
1864 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
1865 if (nb_sns < 0) {
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001866 monitor_printf(err, "bdrv_snapshot_list: error %d\n", nb_sns);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001867 return;
1868 }
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001869 monitor_printf(out, "Snapshot list (from %s):\n",
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001870 bdrv_get_device_name(bs));
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001871 monitor_printf(out, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001872 for(i = 0; i < nb_sns; i++) {
1873 sn = &sn_tab[i];
David 'Digit' Turner95a83ce2011-05-10 17:31:15 +02001874 monitor_printf(out, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001875 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001876 g_free(sn_tab);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001877}