xref: /qemu/migration/qemu-file.c (revision 632e3a5c)
160fe637bSDr. David Alan Gilbert /*
260fe637bSDr. David Alan Gilbert  * QEMU System Emulator
360fe637bSDr. David Alan Gilbert  *
460fe637bSDr. David Alan Gilbert  * Copyright (c) 2003-2008 Fabrice Bellard
560fe637bSDr. David Alan Gilbert  *
660fe637bSDr. David Alan Gilbert  * Permission is hereby granted, free of charge, to any person obtaining a copy
760fe637bSDr. David Alan Gilbert  * of this software and associated documentation files (the "Software"), to deal
860fe637bSDr. David Alan Gilbert  * in the Software without restriction, including without limitation the rights
960fe637bSDr. David Alan Gilbert  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1060fe637bSDr. David Alan Gilbert  * copies of the Software, and to permit persons to whom the Software is
1160fe637bSDr. David Alan Gilbert  * furnished to do so, subject to the following conditions:
1260fe637bSDr. David Alan Gilbert  *
1360fe637bSDr. David Alan Gilbert  * The above copyright notice and this permission notice shall be included in
1460fe637bSDr. David Alan Gilbert  * all copies or substantial portions of the Software.
1560fe637bSDr. David Alan Gilbert  *
1660fe637bSDr. David Alan Gilbert  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1760fe637bSDr. David Alan Gilbert  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1860fe637bSDr. David Alan Gilbert  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1960fe637bSDr. David Alan Gilbert  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2060fe637bSDr. David Alan Gilbert  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2160fe637bSDr. David Alan Gilbert  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2260fe637bSDr. David Alan Gilbert  * THE SOFTWARE.
2360fe637bSDr. David Alan Gilbert  */
2444f0eadcSLiang Li #include <zlib.h>
2560fe637bSDr. David Alan Gilbert #include "qemu-common.h"
26d49b6836SMarkus Armbruster #include "qemu/error-report.h"
2760fe637bSDr. David Alan Gilbert #include "qemu/iov.h"
2860fe637bSDr. David Alan Gilbert #include "qemu/sockets.h"
2960fe637bSDr. David Alan Gilbert #include "block/coroutine.h"
3060fe637bSDr. David Alan Gilbert #include "migration/migration.h"
3160fe637bSDr. David Alan Gilbert #include "migration/qemu-file.h"
324f9d0900SDr. David Alan Gilbert #include "migration/qemu-file-internal.h"
3360fe637bSDr. David Alan Gilbert #include "trace.h"
3460fe637bSDr. David Alan Gilbert 
35e1a8c9b6SDr. David Alan Gilbert /*
36e1a8c9b6SDr. David Alan Gilbert  * Stop a file from being read/written - not all backing files can do this
37e1a8c9b6SDr. David Alan Gilbert  * typically only sockets can.
38e1a8c9b6SDr. David Alan Gilbert  */
39e1a8c9b6SDr. David Alan Gilbert int qemu_file_shutdown(QEMUFile *f)
40e1a8c9b6SDr. David Alan Gilbert {
41e1a8c9b6SDr. David Alan Gilbert     if (!f->ops->shut_down) {
42e1a8c9b6SDr. David Alan Gilbert         return -ENOSYS;
43e1a8c9b6SDr. David Alan Gilbert     }
44e1a8c9b6SDr. David Alan Gilbert     return f->ops->shut_down(f->opaque, true, true);
45e1a8c9b6SDr. David Alan Gilbert }
46e1a8c9b6SDr. David Alan Gilbert 
4760fe637bSDr. David Alan Gilbert bool qemu_file_mode_is_not_valid(const char *mode)
4860fe637bSDr. David Alan Gilbert {
4960fe637bSDr. David Alan Gilbert     if (mode == NULL ||
5060fe637bSDr. David Alan Gilbert         (mode[0] != 'r' && mode[0] != 'w') ||
5160fe637bSDr. David Alan Gilbert         mode[1] != 'b' || mode[2] != 0) {
5260fe637bSDr. David Alan Gilbert         fprintf(stderr, "qemu_fopen: Argument validity check failed\n");
5360fe637bSDr. David Alan Gilbert         return true;
5460fe637bSDr. David Alan Gilbert     }
5560fe637bSDr. David Alan Gilbert 
5660fe637bSDr. David Alan Gilbert     return false;
5760fe637bSDr. David Alan Gilbert }
5860fe637bSDr. David Alan Gilbert 
5960fe637bSDr. David Alan Gilbert QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops)
6060fe637bSDr. David Alan Gilbert {
6160fe637bSDr. David Alan Gilbert     QEMUFile *f;
6260fe637bSDr. David Alan Gilbert 
6360fe637bSDr. David Alan Gilbert     f = g_malloc0(sizeof(QEMUFile));
6460fe637bSDr. David Alan Gilbert 
6560fe637bSDr. David Alan Gilbert     f->opaque = opaque;
6660fe637bSDr. David Alan Gilbert     f->ops = ops;
6760fe637bSDr. David Alan Gilbert     return f;
6860fe637bSDr. David Alan Gilbert }
6960fe637bSDr. David Alan Gilbert 
7060fe637bSDr. David Alan Gilbert /*
7160fe637bSDr. David Alan Gilbert  * Get last error for stream f
7260fe637bSDr. David Alan Gilbert  *
7360fe637bSDr. David Alan Gilbert  * Return negative error value if there has been an error on previous
7460fe637bSDr. David Alan Gilbert  * operations, return 0 if no error happened.
7560fe637bSDr. David Alan Gilbert  *
7660fe637bSDr. David Alan Gilbert  */
7760fe637bSDr. David Alan Gilbert int qemu_file_get_error(QEMUFile *f)
7860fe637bSDr. David Alan Gilbert {
7960fe637bSDr. David Alan Gilbert     return f->last_error;
8060fe637bSDr. David Alan Gilbert }
8160fe637bSDr. David Alan Gilbert 
8260fe637bSDr. David Alan Gilbert void qemu_file_set_error(QEMUFile *f, int ret)
8360fe637bSDr. David Alan Gilbert {
8460fe637bSDr. David Alan Gilbert     if (f->last_error == 0) {
8560fe637bSDr. David Alan Gilbert         f->last_error = ret;
8660fe637bSDr. David Alan Gilbert     }
8760fe637bSDr. David Alan Gilbert }
8860fe637bSDr. David Alan Gilbert 
8960fe637bSDr. David Alan Gilbert bool qemu_file_is_writable(QEMUFile *f)
9060fe637bSDr. David Alan Gilbert {
9160fe637bSDr. David Alan Gilbert     return f->ops->writev_buffer || f->ops->put_buffer;
9260fe637bSDr. David Alan Gilbert }
9360fe637bSDr. David Alan Gilbert 
9460fe637bSDr. David Alan Gilbert /**
9560fe637bSDr. David Alan Gilbert  * Flushes QEMUFile buffer
9660fe637bSDr. David Alan Gilbert  *
9760fe637bSDr. David Alan Gilbert  * If there is writev_buffer QEMUFileOps it uses it otherwise uses
9860fe637bSDr. David Alan Gilbert  * put_buffer ops.
9960fe637bSDr. David Alan Gilbert  */
10060fe637bSDr. David Alan Gilbert void qemu_fflush(QEMUFile *f)
10160fe637bSDr. David Alan Gilbert {
10260fe637bSDr. David Alan Gilbert     ssize_t ret = 0;
10360fe637bSDr. David Alan Gilbert 
10460fe637bSDr. David Alan Gilbert     if (!qemu_file_is_writable(f)) {
10560fe637bSDr. David Alan Gilbert         return;
10660fe637bSDr. David Alan Gilbert     }
10760fe637bSDr. David Alan Gilbert 
10860fe637bSDr. David Alan Gilbert     if (f->ops->writev_buffer) {
10960fe637bSDr. David Alan Gilbert         if (f->iovcnt > 0) {
11060fe637bSDr. David Alan Gilbert             ret = f->ops->writev_buffer(f->opaque, f->iov, f->iovcnt, f->pos);
11160fe637bSDr. David Alan Gilbert         }
11260fe637bSDr. David Alan Gilbert     } else {
11360fe637bSDr. David Alan Gilbert         if (f->buf_index > 0) {
11460fe637bSDr. David Alan Gilbert             ret = f->ops->put_buffer(f->opaque, f->buf, f->pos, f->buf_index);
11560fe637bSDr. David Alan Gilbert         }
11660fe637bSDr. David Alan Gilbert     }
11760fe637bSDr. David Alan Gilbert     if (ret >= 0) {
11860fe637bSDr. David Alan Gilbert         f->pos += ret;
11960fe637bSDr. David Alan Gilbert     }
12060fe637bSDr. David Alan Gilbert     f->buf_index = 0;
12160fe637bSDr. David Alan Gilbert     f->iovcnt = 0;
12260fe637bSDr. David Alan Gilbert     if (ret < 0) {
12360fe637bSDr. David Alan Gilbert         qemu_file_set_error(f, ret);
12460fe637bSDr. David Alan Gilbert     }
12560fe637bSDr. David Alan Gilbert }
12660fe637bSDr. David Alan Gilbert 
12760fe637bSDr. David Alan Gilbert void ram_control_before_iterate(QEMUFile *f, uint64_t flags)
12860fe637bSDr. David Alan Gilbert {
12960fe637bSDr. David Alan Gilbert     int ret = 0;
13060fe637bSDr. David Alan Gilbert 
13160fe637bSDr. David Alan Gilbert     if (f->ops->before_ram_iterate) {
132*632e3a5cSDr. David Alan Gilbert         ret = f->ops->before_ram_iterate(f, f->opaque, flags, NULL);
13360fe637bSDr. David Alan Gilbert         if (ret < 0) {
13460fe637bSDr. David Alan Gilbert             qemu_file_set_error(f, ret);
13560fe637bSDr. David Alan Gilbert         }
13660fe637bSDr. David Alan Gilbert     }
13760fe637bSDr. David Alan Gilbert }
13860fe637bSDr. David Alan Gilbert 
13960fe637bSDr. David Alan Gilbert void ram_control_after_iterate(QEMUFile *f, uint64_t flags)
14060fe637bSDr. David Alan Gilbert {
14160fe637bSDr. David Alan Gilbert     int ret = 0;
14260fe637bSDr. David Alan Gilbert 
14360fe637bSDr. David Alan Gilbert     if (f->ops->after_ram_iterate) {
144*632e3a5cSDr. David Alan Gilbert         ret = f->ops->after_ram_iterate(f, f->opaque, flags, NULL);
14560fe637bSDr. David Alan Gilbert         if (ret < 0) {
14660fe637bSDr. David Alan Gilbert             qemu_file_set_error(f, ret);
14760fe637bSDr. David Alan Gilbert         }
14860fe637bSDr. David Alan Gilbert     }
14960fe637bSDr. David Alan Gilbert }
15060fe637bSDr. David Alan Gilbert 
151*632e3a5cSDr. David Alan Gilbert void ram_control_load_hook(QEMUFile *f, uint64_t flags, void *data)
15260fe637bSDr. David Alan Gilbert {
15360fe637bSDr. David Alan Gilbert     int ret = -EINVAL;
15460fe637bSDr. David Alan Gilbert 
15560fe637bSDr. David Alan Gilbert     if (f->ops->hook_ram_load) {
156*632e3a5cSDr. David Alan Gilbert         ret = f->ops->hook_ram_load(f, f->opaque, flags, data);
15760fe637bSDr. David Alan Gilbert         if (ret < 0) {
15860fe637bSDr. David Alan Gilbert             qemu_file_set_error(f, ret);
15960fe637bSDr. David Alan Gilbert         }
16060fe637bSDr. David Alan Gilbert     } else {
161*632e3a5cSDr. David Alan Gilbert         /*
162*632e3a5cSDr. David Alan Gilbert          * Hook is a hook specifically requested by the source sending a flag
163*632e3a5cSDr. David Alan Gilbert          * that expects there to be a hook on the destination.
164*632e3a5cSDr. David Alan Gilbert          */
165*632e3a5cSDr. David Alan Gilbert         if (flags == RAM_CONTROL_HOOK) {
16660fe637bSDr. David Alan Gilbert             qemu_file_set_error(f, ret);
16760fe637bSDr. David Alan Gilbert         }
16860fe637bSDr. David Alan Gilbert     }
169*632e3a5cSDr. David Alan Gilbert }
17060fe637bSDr. David Alan Gilbert 
17160fe637bSDr. David Alan Gilbert size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
1726e1dea46SJuan Quintela                              ram_addr_t offset, size_t size,
1736e1dea46SJuan Quintela                              uint64_t *bytes_sent)
17460fe637bSDr. David Alan Gilbert {
17560fe637bSDr. David Alan Gilbert     if (f->ops->save_page) {
17660fe637bSDr. David Alan Gilbert         int ret = f->ops->save_page(f, f->opaque, block_offset,
17760fe637bSDr. David Alan Gilbert                                     offset, size, bytes_sent);
17860fe637bSDr. David Alan Gilbert 
17960fe637bSDr. David Alan Gilbert         if (ret != RAM_SAVE_CONTROL_DELAYED) {
18060fe637bSDr. David Alan Gilbert             if (bytes_sent && *bytes_sent > 0) {
18160fe637bSDr. David Alan Gilbert                 qemu_update_position(f, *bytes_sent);
18260fe637bSDr. David Alan Gilbert             } else if (ret < 0) {
18360fe637bSDr. David Alan Gilbert                 qemu_file_set_error(f, ret);
18460fe637bSDr. David Alan Gilbert             }
18560fe637bSDr. David Alan Gilbert         }
18660fe637bSDr. David Alan Gilbert 
18760fe637bSDr. David Alan Gilbert         return ret;
18860fe637bSDr. David Alan Gilbert     }
18960fe637bSDr. David Alan Gilbert 
19060fe637bSDr. David Alan Gilbert     return RAM_SAVE_CONTROL_NOT_SUPP;
19160fe637bSDr. David Alan Gilbert }
19260fe637bSDr. David Alan Gilbert 
19360fe637bSDr. David Alan Gilbert /*
19460fe637bSDr. David Alan Gilbert  * Attempt to fill the buffer from the underlying file
19560fe637bSDr. David Alan Gilbert  * Returns the number of bytes read, or negative value for an error.
19660fe637bSDr. David Alan Gilbert  *
19760fe637bSDr. David Alan Gilbert  * Note that it can return a partially full buffer even in a not error/not EOF
19860fe637bSDr. David Alan Gilbert  * case if the underlying file descriptor gives a short read, and that can
19960fe637bSDr. David Alan Gilbert  * happen even on a blocking fd.
20060fe637bSDr. David Alan Gilbert  */
20160fe637bSDr. David Alan Gilbert static ssize_t qemu_fill_buffer(QEMUFile *f)
20260fe637bSDr. David Alan Gilbert {
20360fe637bSDr. David Alan Gilbert     int len;
20460fe637bSDr. David Alan Gilbert     int pending;
20560fe637bSDr. David Alan Gilbert 
20660fe637bSDr. David Alan Gilbert     assert(!qemu_file_is_writable(f));
20760fe637bSDr. David Alan Gilbert 
20860fe637bSDr. David Alan Gilbert     pending = f->buf_size - f->buf_index;
20960fe637bSDr. David Alan Gilbert     if (pending > 0) {
21060fe637bSDr. David Alan Gilbert         memmove(f->buf, f->buf + f->buf_index, pending);
21160fe637bSDr. David Alan Gilbert     }
21260fe637bSDr. David Alan Gilbert     f->buf_index = 0;
21360fe637bSDr. David Alan Gilbert     f->buf_size = pending;
21460fe637bSDr. David Alan Gilbert 
21560fe637bSDr. David Alan Gilbert     len = f->ops->get_buffer(f->opaque, f->buf + pending, f->pos,
21660fe637bSDr. David Alan Gilbert                         IO_BUF_SIZE - pending);
21760fe637bSDr. David Alan Gilbert     if (len > 0) {
21860fe637bSDr. David Alan Gilbert         f->buf_size += len;
21960fe637bSDr. David Alan Gilbert         f->pos += len;
22060fe637bSDr. David Alan Gilbert     } else if (len == 0) {
22160fe637bSDr. David Alan Gilbert         qemu_file_set_error(f, -EIO);
22260fe637bSDr. David Alan Gilbert     } else if (len != -EAGAIN) {
22360fe637bSDr. David Alan Gilbert         qemu_file_set_error(f, len);
22460fe637bSDr. David Alan Gilbert     }
22560fe637bSDr. David Alan Gilbert 
22660fe637bSDr. David Alan Gilbert     return len;
22760fe637bSDr. David Alan Gilbert }
22860fe637bSDr. David Alan Gilbert 
22960fe637bSDr. David Alan Gilbert int qemu_get_fd(QEMUFile *f)
23060fe637bSDr. David Alan Gilbert {
23160fe637bSDr. David Alan Gilbert     if (f->ops->get_fd) {
23260fe637bSDr. David Alan Gilbert         return f->ops->get_fd(f->opaque);
23360fe637bSDr. David Alan Gilbert     }
23460fe637bSDr. David Alan Gilbert     return -1;
23560fe637bSDr. David Alan Gilbert }
23660fe637bSDr. David Alan Gilbert 
23760fe637bSDr. David Alan Gilbert void qemu_update_position(QEMUFile *f, size_t size)
23860fe637bSDr. David Alan Gilbert {
23960fe637bSDr. David Alan Gilbert     f->pos += size;
24060fe637bSDr. David Alan Gilbert }
24160fe637bSDr. David Alan Gilbert 
24260fe637bSDr. David Alan Gilbert /** Closes the file
24360fe637bSDr. David Alan Gilbert  *
24460fe637bSDr. David Alan Gilbert  * Returns negative error value if any error happened on previous operations or
24560fe637bSDr. David Alan Gilbert  * while closing the file. Returns 0 or positive number on success.
24660fe637bSDr. David Alan Gilbert  *
24760fe637bSDr. David Alan Gilbert  * The meaning of return value on success depends on the specific backend
24860fe637bSDr. David Alan Gilbert  * being used.
24960fe637bSDr. David Alan Gilbert  */
25060fe637bSDr. David Alan Gilbert int qemu_fclose(QEMUFile *f)
25160fe637bSDr. David Alan Gilbert {
25260fe637bSDr. David Alan Gilbert     int ret;
25360fe637bSDr. David Alan Gilbert     qemu_fflush(f);
25460fe637bSDr. David Alan Gilbert     ret = qemu_file_get_error(f);
25560fe637bSDr. David Alan Gilbert 
25660fe637bSDr. David Alan Gilbert     if (f->ops->close) {
25760fe637bSDr. David Alan Gilbert         int ret2 = f->ops->close(f->opaque);
25860fe637bSDr. David Alan Gilbert         if (ret >= 0) {
25960fe637bSDr. David Alan Gilbert             ret = ret2;
26060fe637bSDr. David Alan Gilbert         }
26160fe637bSDr. David Alan Gilbert     }
26260fe637bSDr. David Alan Gilbert     /* If any error was spotted before closing, we should report it
26360fe637bSDr. David Alan Gilbert      * instead of the close() return value.
26460fe637bSDr. David Alan Gilbert      */
26560fe637bSDr. David Alan Gilbert     if (f->last_error) {
26660fe637bSDr. David Alan Gilbert         ret = f->last_error;
26760fe637bSDr. David Alan Gilbert     }
26860fe637bSDr. David Alan Gilbert     g_free(f);
26960fe637bSDr. David Alan Gilbert     trace_qemu_file_fclose();
27060fe637bSDr. David Alan Gilbert     return ret;
27160fe637bSDr. David Alan Gilbert }
27260fe637bSDr. David Alan Gilbert 
27360fe637bSDr. David Alan Gilbert static void add_to_iovec(QEMUFile *f, const uint8_t *buf, int size)
27460fe637bSDr. David Alan Gilbert {
27560fe637bSDr. David Alan Gilbert     /* check for adjacent buffer and coalesce them */
27660fe637bSDr. David Alan Gilbert     if (f->iovcnt > 0 && buf == f->iov[f->iovcnt - 1].iov_base +
27760fe637bSDr. David Alan Gilbert         f->iov[f->iovcnt - 1].iov_len) {
27860fe637bSDr. David Alan Gilbert         f->iov[f->iovcnt - 1].iov_len += size;
27960fe637bSDr. David Alan Gilbert     } else {
28060fe637bSDr. David Alan Gilbert         f->iov[f->iovcnt].iov_base = (uint8_t *)buf;
28160fe637bSDr. David Alan Gilbert         f->iov[f->iovcnt++].iov_len = size;
28260fe637bSDr. David Alan Gilbert     }
28360fe637bSDr. David Alan Gilbert 
28460fe637bSDr. David Alan Gilbert     if (f->iovcnt >= MAX_IOV_SIZE) {
28560fe637bSDr. David Alan Gilbert         qemu_fflush(f);
28660fe637bSDr. David Alan Gilbert     }
28760fe637bSDr. David Alan Gilbert }
28860fe637bSDr. David Alan Gilbert 
28960fe637bSDr. David Alan Gilbert void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, int size)
29060fe637bSDr. David Alan Gilbert {
29160fe637bSDr. David Alan Gilbert     if (!f->ops->writev_buffer) {
29260fe637bSDr. David Alan Gilbert         qemu_put_buffer(f, buf, size);
29360fe637bSDr. David Alan Gilbert         return;
29460fe637bSDr. David Alan Gilbert     }
29560fe637bSDr. David Alan Gilbert 
29660fe637bSDr. David Alan Gilbert     if (f->last_error) {
29760fe637bSDr. David Alan Gilbert         return;
29860fe637bSDr. David Alan Gilbert     }
29960fe637bSDr. David Alan Gilbert 
30060fe637bSDr. David Alan Gilbert     f->bytes_xfer += size;
30160fe637bSDr. David Alan Gilbert     add_to_iovec(f, buf, size);
30260fe637bSDr. David Alan Gilbert }
30360fe637bSDr. David Alan Gilbert 
30460fe637bSDr. David Alan Gilbert void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
30560fe637bSDr. David Alan Gilbert {
30660fe637bSDr. David Alan Gilbert     int l;
30760fe637bSDr. David Alan Gilbert 
30860fe637bSDr. David Alan Gilbert     if (f->last_error) {
30960fe637bSDr. David Alan Gilbert         return;
31060fe637bSDr. David Alan Gilbert     }
31160fe637bSDr. David Alan Gilbert 
31260fe637bSDr. David Alan Gilbert     while (size > 0) {
31360fe637bSDr. David Alan Gilbert         l = IO_BUF_SIZE - f->buf_index;
31460fe637bSDr. David Alan Gilbert         if (l > size) {
31560fe637bSDr. David Alan Gilbert             l = size;
31660fe637bSDr. David Alan Gilbert         }
31760fe637bSDr. David Alan Gilbert         memcpy(f->buf + f->buf_index, buf, l);
31860fe637bSDr. David Alan Gilbert         f->bytes_xfer += l;
31960fe637bSDr. David Alan Gilbert         if (f->ops->writev_buffer) {
32060fe637bSDr. David Alan Gilbert             add_to_iovec(f, f->buf + f->buf_index, l);
32160fe637bSDr. David Alan Gilbert         }
32260fe637bSDr. David Alan Gilbert         f->buf_index += l;
32360fe637bSDr. David Alan Gilbert         if (f->buf_index == IO_BUF_SIZE) {
32460fe637bSDr. David Alan Gilbert             qemu_fflush(f);
32560fe637bSDr. David Alan Gilbert         }
32660fe637bSDr. David Alan Gilbert         if (qemu_file_get_error(f)) {
32760fe637bSDr. David Alan Gilbert             break;
32860fe637bSDr. David Alan Gilbert         }
32960fe637bSDr. David Alan Gilbert         buf += l;
33060fe637bSDr. David Alan Gilbert         size -= l;
33160fe637bSDr. David Alan Gilbert     }
33260fe637bSDr. David Alan Gilbert }
33360fe637bSDr. David Alan Gilbert 
33460fe637bSDr. David Alan Gilbert void qemu_put_byte(QEMUFile *f, int v)
33560fe637bSDr. David Alan Gilbert {
33660fe637bSDr. David Alan Gilbert     if (f->last_error) {
33760fe637bSDr. David Alan Gilbert         return;
33860fe637bSDr. David Alan Gilbert     }
33960fe637bSDr. David Alan Gilbert 
34060fe637bSDr. David Alan Gilbert     f->buf[f->buf_index] = v;
34160fe637bSDr. David Alan Gilbert     f->bytes_xfer++;
34260fe637bSDr. David Alan Gilbert     if (f->ops->writev_buffer) {
34360fe637bSDr. David Alan Gilbert         add_to_iovec(f, f->buf + f->buf_index, 1);
34460fe637bSDr. David Alan Gilbert     }
34560fe637bSDr. David Alan Gilbert     f->buf_index++;
34660fe637bSDr. David Alan Gilbert     if (f->buf_index == IO_BUF_SIZE) {
34760fe637bSDr. David Alan Gilbert         qemu_fflush(f);
34860fe637bSDr. David Alan Gilbert     }
34960fe637bSDr. David Alan Gilbert }
35060fe637bSDr. David Alan Gilbert 
35160fe637bSDr. David Alan Gilbert void qemu_file_skip(QEMUFile *f, int size)
35260fe637bSDr. David Alan Gilbert {
35360fe637bSDr. David Alan Gilbert     if (f->buf_index + size <= f->buf_size) {
35460fe637bSDr. David Alan Gilbert         f->buf_index += size;
35560fe637bSDr. David Alan Gilbert     }
35660fe637bSDr. David Alan Gilbert }
35760fe637bSDr. David Alan Gilbert 
35860fe637bSDr. David Alan Gilbert /*
3597c1e52baSDr. David Alan Gilbert  * Read 'size' bytes from file (at 'offset') without moving the
3607c1e52baSDr. David Alan Gilbert  * pointer and set 'buf' to point to that data.
36160fe637bSDr. David Alan Gilbert  *
36260fe637bSDr. David Alan Gilbert  * It will return size bytes unless there was an error, in which case it will
36360fe637bSDr. David Alan Gilbert  * return as many as it managed to read (assuming blocking fd's which
36460fe637bSDr. David Alan Gilbert  * all current QEMUFile are)
36560fe637bSDr. David Alan Gilbert  */
3667c1e52baSDr. David Alan Gilbert int qemu_peek_buffer(QEMUFile *f, uint8_t **buf, int size, size_t offset)
36760fe637bSDr. David Alan Gilbert {
36860fe637bSDr. David Alan Gilbert     int pending;
36960fe637bSDr. David Alan Gilbert     int index;
37060fe637bSDr. David Alan Gilbert 
37160fe637bSDr. David Alan Gilbert     assert(!qemu_file_is_writable(f));
37260fe637bSDr. David Alan Gilbert     assert(offset < IO_BUF_SIZE);
37360fe637bSDr. David Alan Gilbert     assert(size <= IO_BUF_SIZE - offset);
37460fe637bSDr. David Alan Gilbert 
37560fe637bSDr. David Alan Gilbert     /* The 1st byte to read from */
37660fe637bSDr. David Alan Gilbert     index = f->buf_index + offset;
37760fe637bSDr. David Alan Gilbert     /* The number of available bytes starting at index */
37860fe637bSDr. David Alan Gilbert     pending = f->buf_size - index;
37960fe637bSDr. David Alan Gilbert 
38060fe637bSDr. David Alan Gilbert     /*
38160fe637bSDr. David Alan Gilbert      * qemu_fill_buffer might return just a few bytes, even when there isn't
38260fe637bSDr. David Alan Gilbert      * an error, so loop collecting them until we get enough.
38360fe637bSDr. David Alan Gilbert      */
38460fe637bSDr. David Alan Gilbert     while (pending < size) {
38560fe637bSDr. David Alan Gilbert         int received = qemu_fill_buffer(f);
38660fe637bSDr. David Alan Gilbert 
38760fe637bSDr. David Alan Gilbert         if (received <= 0) {
38860fe637bSDr. David Alan Gilbert             break;
38960fe637bSDr. David Alan Gilbert         }
39060fe637bSDr. David Alan Gilbert 
39160fe637bSDr. David Alan Gilbert         index = f->buf_index + offset;
39260fe637bSDr. David Alan Gilbert         pending = f->buf_size - index;
39360fe637bSDr. David Alan Gilbert     }
39460fe637bSDr. David Alan Gilbert 
39560fe637bSDr. David Alan Gilbert     if (pending <= 0) {
39660fe637bSDr. David Alan Gilbert         return 0;
39760fe637bSDr. David Alan Gilbert     }
39860fe637bSDr. David Alan Gilbert     if (size > pending) {
39960fe637bSDr. David Alan Gilbert         size = pending;
40060fe637bSDr. David Alan Gilbert     }
40160fe637bSDr. David Alan Gilbert 
4027c1e52baSDr. David Alan Gilbert     *buf = f->buf + index;
40360fe637bSDr. David Alan Gilbert     return size;
40460fe637bSDr. David Alan Gilbert }
40560fe637bSDr. David Alan Gilbert 
40660fe637bSDr. David Alan Gilbert /*
40760fe637bSDr. David Alan Gilbert  * Read 'size' bytes of data from the file into buf.
40860fe637bSDr. David Alan Gilbert  * 'size' can be larger than the internal buffer.
40960fe637bSDr. David Alan Gilbert  *
41060fe637bSDr. David Alan Gilbert  * It will return size bytes unless there was an error, in which case it will
41160fe637bSDr. David Alan Gilbert  * return as many as it managed to read (assuming blocking fd's which
41260fe637bSDr. David Alan Gilbert  * all current QEMUFile are)
41360fe637bSDr. David Alan Gilbert  */
41460fe637bSDr. David Alan Gilbert int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
41560fe637bSDr. David Alan Gilbert {
41660fe637bSDr. David Alan Gilbert     int pending = size;
41760fe637bSDr. David Alan Gilbert     int done = 0;
41860fe637bSDr. David Alan Gilbert 
41960fe637bSDr. David Alan Gilbert     while (pending > 0) {
42060fe637bSDr. David Alan Gilbert         int res;
4217c1e52baSDr. David Alan Gilbert         uint8_t *src;
42260fe637bSDr. David Alan Gilbert 
4237c1e52baSDr. David Alan Gilbert         res = qemu_peek_buffer(f, &src, MIN(pending, IO_BUF_SIZE), 0);
42460fe637bSDr. David Alan Gilbert         if (res == 0) {
42560fe637bSDr. David Alan Gilbert             return done;
42660fe637bSDr. David Alan Gilbert         }
4277c1e52baSDr. David Alan Gilbert         memcpy(buf, src, res);
42860fe637bSDr. David Alan Gilbert         qemu_file_skip(f, res);
42960fe637bSDr. David Alan Gilbert         buf += res;
43060fe637bSDr. David Alan Gilbert         pending -= res;
43160fe637bSDr. David Alan Gilbert         done += res;
43260fe637bSDr. David Alan Gilbert     }
43360fe637bSDr. David Alan Gilbert     return done;
43460fe637bSDr. David Alan Gilbert }
43560fe637bSDr. David Alan Gilbert 
43660fe637bSDr. David Alan Gilbert /*
43760fe637bSDr. David Alan Gilbert  * Peeks a single byte from the buffer; this isn't guaranteed to work if
43860fe637bSDr. David Alan Gilbert  * offset leaves a gap after the previous read/peeked data.
43960fe637bSDr. David Alan Gilbert  */
44060fe637bSDr. David Alan Gilbert int qemu_peek_byte(QEMUFile *f, int offset)
44160fe637bSDr. David Alan Gilbert {
44260fe637bSDr. David Alan Gilbert     int index = f->buf_index + offset;
44360fe637bSDr. David Alan Gilbert 
44460fe637bSDr. David Alan Gilbert     assert(!qemu_file_is_writable(f));
44560fe637bSDr. David Alan Gilbert     assert(offset < IO_BUF_SIZE);
44660fe637bSDr. David Alan Gilbert 
44760fe637bSDr. David Alan Gilbert     if (index >= f->buf_size) {
44860fe637bSDr. David Alan Gilbert         qemu_fill_buffer(f);
44960fe637bSDr. David Alan Gilbert         index = f->buf_index + offset;
45060fe637bSDr. David Alan Gilbert         if (index >= f->buf_size) {
45160fe637bSDr. David Alan Gilbert             return 0;
45260fe637bSDr. David Alan Gilbert         }
45360fe637bSDr. David Alan Gilbert     }
45460fe637bSDr. David Alan Gilbert     return f->buf[index];
45560fe637bSDr. David Alan Gilbert }
45660fe637bSDr. David Alan Gilbert 
45760fe637bSDr. David Alan Gilbert int qemu_get_byte(QEMUFile *f)
45860fe637bSDr. David Alan Gilbert {
45960fe637bSDr. David Alan Gilbert     int result;
46060fe637bSDr. David Alan Gilbert 
46160fe637bSDr. David Alan Gilbert     result = qemu_peek_byte(f, 0);
46260fe637bSDr. David Alan Gilbert     qemu_file_skip(f, 1);
46360fe637bSDr. David Alan Gilbert     return result;
46460fe637bSDr. David Alan Gilbert }
46560fe637bSDr. David Alan Gilbert 
46697221400SAlexander Graf int64_t qemu_ftell_fast(QEMUFile *f)
46797221400SAlexander Graf {
46897221400SAlexander Graf     int64_t ret = f->pos;
46997221400SAlexander Graf     int i;
47097221400SAlexander Graf 
47197221400SAlexander Graf     if (f->ops->writev_buffer) {
47297221400SAlexander Graf         for (i = 0; i < f->iovcnt; i++) {
47397221400SAlexander Graf             ret += f->iov[i].iov_len;
47497221400SAlexander Graf         }
47597221400SAlexander Graf     } else {
47697221400SAlexander Graf         ret += f->buf_index;
47797221400SAlexander Graf     }
47897221400SAlexander Graf 
47997221400SAlexander Graf     return ret;
48097221400SAlexander Graf }
48197221400SAlexander Graf 
48260fe637bSDr. David Alan Gilbert int64_t qemu_ftell(QEMUFile *f)
48360fe637bSDr. David Alan Gilbert {
48460fe637bSDr. David Alan Gilbert     qemu_fflush(f);
48560fe637bSDr. David Alan Gilbert     return f->pos;
48660fe637bSDr. David Alan Gilbert }
48760fe637bSDr. David Alan Gilbert 
48860fe637bSDr. David Alan Gilbert int qemu_file_rate_limit(QEMUFile *f)
48960fe637bSDr. David Alan Gilbert {
49060fe637bSDr. David Alan Gilbert     if (qemu_file_get_error(f)) {
49160fe637bSDr. David Alan Gilbert         return 1;
49260fe637bSDr. David Alan Gilbert     }
49360fe637bSDr. David Alan Gilbert     if (f->xfer_limit > 0 && f->bytes_xfer > f->xfer_limit) {
49460fe637bSDr. David Alan Gilbert         return 1;
49560fe637bSDr. David Alan Gilbert     }
49660fe637bSDr. David Alan Gilbert     return 0;
49760fe637bSDr. David Alan Gilbert }
49860fe637bSDr. David Alan Gilbert 
49960fe637bSDr. David Alan Gilbert int64_t qemu_file_get_rate_limit(QEMUFile *f)
50060fe637bSDr. David Alan Gilbert {
50160fe637bSDr. David Alan Gilbert     return f->xfer_limit;
50260fe637bSDr. David Alan Gilbert }
50360fe637bSDr. David Alan Gilbert 
50460fe637bSDr. David Alan Gilbert void qemu_file_set_rate_limit(QEMUFile *f, int64_t limit)
50560fe637bSDr. David Alan Gilbert {
50660fe637bSDr. David Alan Gilbert     f->xfer_limit = limit;
50760fe637bSDr. David Alan Gilbert }
50860fe637bSDr. David Alan Gilbert 
50960fe637bSDr. David Alan Gilbert void qemu_file_reset_rate_limit(QEMUFile *f)
51060fe637bSDr. David Alan Gilbert {
51160fe637bSDr. David Alan Gilbert     f->bytes_xfer = 0;
51260fe637bSDr. David Alan Gilbert }
51360fe637bSDr. David Alan Gilbert 
51460fe637bSDr. David Alan Gilbert void qemu_put_be16(QEMUFile *f, unsigned int v)
51560fe637bSDr. David Alan Gilbert {
51660fe637bSDr. David Alan Gilbert     qemu_put_byte(f, v >> 8);
51760fe637bSDr. David Alan Gilbert     qemu_put_byte(f, v);
51860fe637bSDr. David Alan Gilbert }
51960fe637bSDr. David Alan Gilbert 
52060fe637bSDr. David Alan Gilbert void qemu_put_be32(QEMUFile *f, unsigned int v)
52160fe637bSDr. David Alan Gilbert {
52260fe637bSDr. David Alan Gilbert     qemu_put_byte(f, v >> 24);
52360fe637bSDr. David Alan Gilbert     qemu_put_byte(f, v >> 16);
52460fe637bSDr. David Alan Gilbert     qemu_put_byte(f, v >> 8);
52560fe637bSDr. David Alan Gilbert     qemu_put_byte(f, v);
52660fe637bSDr. David Alan Gilbert }
52760fe637bSDr. David Alan Gilbert 
52860fe637bSDr. David Alan Gilbert void qemu_put_be64(QEMUFile *f, uint64_t v)
52960fe637bSDr. David Alan Gilbert {
53060fe637bSDr. David Alan Gilbert     qemu_put_be32(f, v >> 32);
53160fe637bSDr. David Alan Gilbert     qemu_put_be32(f, v);
53260fe637bSDr. David Alan Gilbert }
53360fe637bSDr. David Alan Gilbert 
53460fe637bSDr. David Alan Gilbert unsigned int qemu_get_be16(QEMUFile *f)
53560fe637bSDr. David Alan Gilbert {
53660fe637bSDr. David Alan Gilbert     unsigned int v;
53760fe637bSDr. David Alan Gilbert     v = qemu_get_byte(f) << 8;
53860fe637bSDr. David Alan Gilbert     v |= qemu_get_byte(f);
53960fe637bSDr. David Alan Gilbert     return v;
54060fe637bSDr. David Alan Gilbert }
54160fe637bSDr. David Alan Gilbert 
54260fe637bSDr. David Alan Gilbert unsigned int qemu_get_be32(QEMUFile *f)
54360fe637bSDr. David Alan Gilbert {
54460fe637bSDr. David Alan Gilbert     unsigned int v;
54590d6a673SPeter Maydell     v = (unsigned int)qemu_get_byte(f) << 24;
54660fe637bSDr. David Alan Gilbert     v |= qemu_get_byte(f) << 16;
54760fe637bSDr. David Alan Gilbert     v |= qemu_get_byte(f) << 8;
54860fe637bSDr. David Alan Gilbert     v |= qemu_get_byte(f);
54960fe637bSDr. David Alan Gilbert     return v;
55060fe637bSDr. David Alan Gilbert }
55160fe637bSDr. David Alan Gilbert 
55260fe637bSDr. David Alan Gilbert uint64_t qemu_get_be64(QEMUFile *f)
55360fe637bSDr. David Alan Gilbert {
55460fe637bSDr. David Alan Gilbert     uint64_t v;
55560fe637bSDr. David Alan Gilbert     v = (uint64_t)qemu_get_be32(f) << 32;
55660fe637bSDr. David Alan Gilbert     v |= qemu_get_be32(f);
55760fe637bSDr. David Alan Gilbert     return v;
55860fe637bSDr. David Alan Gilbert }
55944f0eadcSLiang Li 
56044f0eadcSLiang Li /* compress size bytes of data start at p with specific compression
56144f0eadcSLiang Li  * level and store the compressed data to the buffer of f.
56244f0eadcSLiang Li  */
56344f0eadcSLiang Li 
56444f0eadcSLiang Li ssize_t qemu_put_compression_data(QEMUFile *f, const uint8_t *p, size_t size,
56544f0eadcSLiang Li                                   int level)
56644f0eadcSLiang Li {
56744f0eadcSLiang Li     ssize_t blen = IO_BUF_SIZE - f->buf_index - sizeof(int32_t);
56844f0eadcSLiang Li 
56944f0eadcSLiang Li     if (blen < compressBound(size)) {
57044f0eadcSLiang Li         return 0;
57144f0eadcSLiang Li     }
57244f0eadcSLiang Li     if (compress2(f->buf + f->buf_index + sizeof(int32_t), (uLongf *)&blen,
57344f0eadcSLiang Li                   (Bytef *)p, size, level) != Z_OK) {
57444f0eadcSLiang Li         error_report("Compress Failed!");
57544f0eadcSLiang Li         return 0;
57644f0eadcSLiang Li     }
57744f0eadcSLiang Li     qemu_put_be32(f, blen);
57844f0eadcSLiang Li     f->buf_index += blen;
57944f0eadcSLiang Li     return blen + sizeof(int32_t);
58044f0eadcSLiang Li }
58144f0eadcSLiang Li 
58244f0eadcSLiang Li /* Put the data in the buffer of f_src to the buffer of f_des, and
58344f0eadcSLiang Li  * then reset the buf_index of f_src to 0.
58444f0eadcSLiang Li  */
58544f0eadcSLiang Li 
58644f0eadcSLiang Li int qemu_put_qemu_file(QEMUFile *f_des, QEMUFile *f_src)
58744f0eadcSLiang Li {
58844f0eadcSLiang Li     int len = 0;
58944f0eadcSLiang Li 
59044f0eadcSLiang Li     if (f_src->buf_index > 0) {
59144f0eadcSLiang Li         len = f_src->buf_index;
59244f0eadcSLiang Li         qemu_put_buffer(f_des, f_src->buf, f_src->buf_index);
59344f0eadcSLiang Li         f_src->buf_index = 0;
59444f0eadcSLiang Li     }
59544f0eadcSLiang Li     return len;
59644f0eadcSLiang Li }
597b3af1bc9SDr. David Alan Gilbert 
598b3af1bc9SDr. David Alan Gilbert /*
599b3af1bc9SDr. David Alan Gilbert  * Get a string whose length is determined by a single preceding byte
600b3af1bc9SDr. David Alan Gilbert  * A preallocated 256 byte buffer must be passed in.
601b3af1bc9SDr. David Alan Gilbert  * Returns: len on success and a 0 terminated string in the buffer
602b3af1bc9SDr. David Alan Gilbert  *          else 0
603b3af1bc9SDr. David Alan Gilbert  *          (Note a 0 length string will return 0 either way)
604b3af1bc9SDr. David Alan Gilbert  */
605b3af1bc9SDr. David Alan Gilbert size_t qemu_get_counted_string(QEMUFile *f, char buf[256])
606b3af1bc9SDr. David Alan Gilbert {
607b3af1bc9SDr. David Alan Gilbert     size_t len = qemu_get_byte(f);
608b3af1bc9SDr. David Alan Gilbert     size_t res = qemu_get_buffer(f, (uint8_t *)buf, len);
609b3af1bc9SDr. David Alan Gilbert 
610b3af1bc9SDr. David Alan Gilbert     buf[res] = 0;
611b3af1bc9SDr. David Alan Gilbert 
612b3af1bc9SDr. David Alan Gilbert     return res == len ? res : 0;
613b3af1bc9SDr. David Alan Gilbert }
614