xref: /qemu/migration/qemu-file.c (revision 6e1dea46)
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  */
2460fe637bSDr. David Alan Gilbert #include "qemu-common.h"
2560fe637bSDr. David Alan Gilbert #include "qemu/iov.h"
2660fe637bSDr. David Alan Gilbert #include "qemu/sockets.h"
2760fe637bSDr. David Alan Gilbert #include "block/coroutine.h"
2860fe637bSDr. David Alan Gilbert #include "migration/migration.h"
2960fe637bSDr. David Alan Gilbert #include "migration/qemu-file.h"
304f9d0900SDr. David Alan Gilbert #include "migration/qemu-file-internal.h"
3160fe637bSDr. David Alan Gilbert #include "trace.h"
3260fe637bSDr. David Alan Gilbert 
33e1a8c9b6SDr. David Alan Gilbert /*
34e1a8c9b6SDr. David Alan Gilbert  * Stop a file from being read/written - not all backing files can do this
35e1a8c9b6SDr. David Alan Gilbert  * typically only sockets can.
36e1a8c9b6SDr. David Alan Gilbert  */
37e1a8c9b6SDr. David Alan Gilbert int qemu_file_shutdown(QEMUFile *f)
38e1a8c9b6SDr. David Alan Gilbert {
39e1a8c9b6SDr. David Alan Gilbert     if (!f->ops->shut_down) {
40e1a8c9b6SDr. David Alan Gilbert         return -ENOSYS;
41e1a8c9b6SDr. David Alan Gilbert     }
42e1a8c9b6SDr. David Alan Gilbert     return f->ops->shut_down(f->opaque, true, true);
43e1a8c9b6SDr. David Alan Gilbert }
44e1a8c9b6SDr. David Alan Gilbert 
4560fe637bSDr. David Alan Gilbert bool qemu_file_mode_is_not_valid(const char *mode)
4660fe637bSDr. David Alan Gilbert {
4760fe637bSDr. David Alan Gilbert     if (mode == NULL ||
4860fe637bSDr. David Alan Gilbert         (mode[0] != 'r' && mode[0] != 'w') ||
4960fe637bSDr. David Alan Gilbert         mode[1] != 'b' || mode[2] != 0) {
5060fe637bSDr. David Alan Gilbert         fprintf(stderr, "qemu_fopen: Argument validity check failed\n");
5160fe637bSDr. David Alan Gilbert         return true;
5260fe637bSDr. David Alan Gilbert     }
5360fe637bSDr. David Alan Gilbert 
5460fe637bSDr. David Alan Gilbert     return false;
5560fe637bSDr. David Alan Gilbert }
5660fe637bSDr. David Alan Gilbert 
5760fe637bSDr. David Alan Gilbert QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops)
5860fe637bSDr. David Alan Gilbert {
5960fe637bSDr. David Alan Gilbert     QEMUFile *f;
6060fe637bSDr. David Alan Gilbert 
6160fe637bSDr. David Alan Gilbert     f = g_malloc0(sizeof(QEMUFile));
6260fe637bSDr. David Alan Gilbert 
6360fe637bSDr. David Alan Gilbert     f->opaque = opaque;
6460fe637bSDr. David Alan Gilbert     f->ops = ops;
6560fe637bSDr. David Alan Gilbert     return f;
6660fe637bSDr. David Alan Gilbert }
6760fe637bSDr. David Alan Gilbert 
6860fe637bSDr. David Alan Gilbert /*
6960fe637bSDr. David Alan Gilbert  * Get last error for stream f
7060fe637bSDr. David Alan Gilbert  *
7160fe637bSDr. David Alan Gilbert  * Return negative error value if there has been an error on previous
7260fe637bSDr. David Alan Gilbert  * operations, return 0 if no error happened.
7360fe637bSDr. David Alan Gilbert  *
7460fe637bSDr. David Alan Gilbert  */
7560fe637bSDr. David Alan Gilbert int qemu_file_get_error(QEMUFile *f)
7660fe637bSDr. David Alan Gilbert {
7760fe637bSDr. David Alan Gilbert     return f->last_error;
7860fe637bSDr. David Alan Gilbert }
7960fe637bSDr. David Alan Gilbert 
8060fe637bSDr. David Alan Gilbert void qemu_file_set_error(QEMUFile *f, int ret)
8160fe637bSDr. David Alan Gilbert {
8260fe637bSDr. David Alan Gilbert     if (f->last_error == 0) {
8360fe637bSDr. David Alan Gilbert         f->last_error = ret;
8460fe637bSDr. David Alan Gilbert     }
8560fe637bSDr. David Alan Gilbert }
8660fe637bSDr. David Alan Gilbert 
8760fe637bSDr. David Alan Gilbert bool qemu_file_is_writable(QEMUFile *f)
8860fe637bSDr. David Alan Gilbert {
8960fe637bSDr. David Alan Gilbert     return f->ops->writev_buffer || f->ops->put_buffer;
9060fe637bSDr. David Alan Gilbert }
9160fe637bSDr. David Alan Gilbert 
9260fe637bSDr. David Alan Gilbert /**
9360fe637bSDr. David Alan Gilbert  * Flushes QEMUFile buffer
9460fe637bSDr. David Alan Gilbert  *
9560fe637bSDr. David Alan Gilbert  * If there is writev_buffer QEMUFileOps it uses it otherwise uses
9660fe637bSDr. David Alan Gilbert  * put_buffer ops.
9760fe637bSDr. David Alan Gilbert  */
9860fe637bSDr. David Alan Gilbert void qemu_fflush(QEMUFile *f)
9960fe637bSDr. David Alan Gilbert {
10060fe637bSDr. David Alan Gilbert     ssize_t ret = 0;
10160fe637bSDr. David Alan Gilbert 
10260fe637bSDr. David Alan Gilbert     if (!qemu_file_is_writable(f)) {
10360fe637bSDr. David Alan Gilbert         return;
10460fe637bSDr. David Alan Gilbert     }
10560fe637bSDr. David Alan Gilbert 
10660fe637bSDr. David Alan Gilbert     if (f->ops->writev_buffer) {
10760fe637bSDr. David Alan Gilbert         if (f->iovcnt > 0) {
10860fe637bSDr. David Alan Gilbert             ret = f->ops->writev_buffer(f->opaque, f->iov, f->iovcnt, f->pos);
10960fe637bSDr. David Alan Gilbert         }
11060fe637bSDr. David Alan Gilbert     } else {
11160fe637bSDr. David Alan Gilbert         if (f->buf_index > 0) {
11260fe637bSDr. David Alan Gilbert             ret = f->ops->put_buffer(f->opaque, f->buf, f->pos, f->buf_index);
11360fe637bSDr. David Alan Gilbert         }
11460fe637bSDr. David Alan Gilbert     }
11560fe637bSDr. David Alan Gilbert     if (ret >= 0) {
11660fe637bSDr. David Alan Gilbert         f->pos += ret;
11760fe637bSDr. David Alan Gilbert     }
11860fe637bSDr. David Alan Gilbert     f->buf_index = 0;
11960fe637bSDr. David Alan Gilbert     f->iovcnt = 0;
12060fe637bSDr. David Alan Gilbert     if (ret < 0) {
12160fe637bSDr. David Alan Gilbert         qemu_file_set_error(f, ret);
12260fe637bSDr. David Alan Gilbert     }
12360fe637bSDr. David Alan Gilbert }
12460fe637bSDr. David Alan Gilbert 
12560fe637bSDr. David Alan Gilbert void ram_control_before_iterate(QEMUFile *f, uint64_t flags)
12660fe637bSDr. David Alan Gilbert {
12760fe637bSDr. David Alan Gilbert     int ret = 0;
12860fe637bSDr. David Alan Gilbert 
12960fe637bSDr. David Alan Gilbert     if (f->ops->before_ram_iterate) {
13060fe637bSDr. David Alan Gilbert         ret = f->ops->before_ram_iterate(f, f->opaque, flags);
13160fe637bSDr. David Alan Gilbert         if (ret < 0) {
13260fe637bSDr. David Alan Gilbert             qemu_file_set_error(f, ret);
13360fe637bSDr. David Alan Gilbert         }
13460fe637bSDr. David Alan Gilbert     }
13560fe637bSDr. David Alan Gilbert }
13660fe637bSDr. David Alan Gilbert 
13760fe637bSDr. David Alan Gilbert void ram_control_after_iterate(QEMUFile *f, uint64_t flags)
13860fe637bSDr. David Alan Gilbert {
13960fe637bSDr. David Alan Gilbert     int ret = 0;
14060fe637bSDr. David Alan Gilbert 
14160fe637bSDr. David Alan Gilbert     if (f->ops->after_ram_iterate) {
14260fe637bSDr. David Alan Gilbert         ret = f->ops->after_ram_iterate(f, f->opaque, flags);
14360fe637bSDr. David Alan Gilbert         if (ret < 0) {
14460fe637bSDr. David Alan Gilbert             qemu_file_set_error(f, ret);
14560fe637bSDr. David Alan Gilbert         }
14660fe637bSDr. David Alan Gilbert     }
14760fe637bSDr. David Alan Gilbert }
14860fe637bSDr. David Alan Gilbert 
14960fe637bSDr. David Alan Gilbert void ram_control_load_hook(QEMUFile *f, uint64_t flags)
15060fe637bSDr. David Alan Gilbert {
15160fe637bSDr. David Alan Gilbert     int ret = -EINVAL;
15260fe637bSDr. David Alan Gilbert 
15360fe637bSDr. David Alan Gilbert     if (f->ops->hook_ram_load) {
15460fe637bSDr. David Alan Gilbert         ret = f->ops->hook_ram_load(f, f->opaque, flags);
15560fe637bSDr. David Alan Gilbert         if (ret < 0) {
15660fe637bSDr. David Alan Gilbert             qemu_file_set_error(f, ret);
15760fe637bSDr. David Alan Gilbert         }
15860fe637bSDr. David Alan Gilbert     } else {
15960fe637bSDr. David Alan Gilbert         qemu_file_set_error(f, ret);
16060fe637bSDr. David Alan Gilbert     }
16160fe637bSDr. David Alan Gilbert }
16260fe637bSDr. David Alan Gilbert 
16360fe637bSDr. David Alan Gilbert size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
164*6e1dea46SJuan Quintela                              ram_addr_t offset, size_t size,
165*6e1dea46SJuan Quintela                              uint64_t *bytes_sent)
16660fe637bSDr. David Alan Gilbert {
16760fe637bSDr. David Alan Gilbert     if (f->ops->save_page) {
16860fe637bSDr. David Alan Gilbert         int ret = f->ops->save_page(f, f->opaque, block_offset,
16960fe637bSDr. David Alan Gilbert                                     offset, size, bytes_sent);
17060fe637bSDr. David Alan Gilbert 
17160fe637bSDr. David Alan Gilbert         if (ret != RAM_SAVE_CONTROL_DELAYED) {
17260fe637bSDr. David Alan Gilbert             if (bytes_sent && *bytes_sent > 0) {
17360fe637bSDr. David Alan Gilbert                 qemu_update_position(f, *bytes_sent);
17460fe637bSDr. David Alan Gilbert             } else if (ret < 0) {
17560fe637bSDr. David Alan Gilbert                 qemu_file_set_error(f, ret);
17660fe637bSDr. David Alan Gilbert             }
17760fe637bSDr. David Alan Gilbert         }
17860fe637bSDr. David Alan Gilbert 
17960fe637bSDr. David Alan Gilbert         return ret;
18060fe637bSDr. David Alan Gilbert     }
18160fe637bSDr. David Alan Gilbert 
18260fe637bSDr. David Alan Gilbert     return RAM_SAVE_CONTROL_NOT_SUPP;
18360fe637bSDr. David Alan Gilbert }
18460fe637bSDr. David Alan Gilbert 
18560fe637bSDr. David Alan Gilbert /*
18660fe637bSDr. David Alan Gilbert  * Attempt to fill the buffer from the underlying file
18760fe637bSDr. David Alan Gilbert  * Returns the number of bytes read, or negative value for an error.
18860fe637bSDr. David Alan Gilbert  *
18960fe637bSDr. David Alan Gilbert  * Note that it can return a partially full buffer even in a not error/not EOF
19060fe637bSDr. David Alan Gilbert  * case if the underlying file descriptor gives a short read, and that can
19160fe637bSDr. David Alan Gilbert  * happen even on a blocking fd.
19260fe637bSDr. David Alan Gilbert  */
19360fe637bSDr. David Alan Gilbert static ssize_t qemu_fill_buffer(QEMUFile *f)
19460fe637bSDr. David Alan Gilbert {
19560fe637bSDr. David Alan Gilbert     int len;
19660fe637bSDr. David Alan Gilbert     int pending;
19760fe637bSDr. David Alan Gilbert 
19860fe637bSDr. David Alan Gilbert     assert(!qemu_file_is_writable(f));
19960fe637bSDr. David Alan Gilbert 
20060fe637bSDr. David Alan Gilbert     pending = f->buf_size - f->buf_index;
20160fe637bSDr. David Alan Gilbert     if (pending > 0) {
20260fe637bSDr. David Alan Gilbert         memmove(f->buf, f->buf + f->buf_index, pending);
20360fe637bSDr. David Alan Gilbert     }
20460fe637bSDr. David Alan Gilbert     f->buf_index = 0;
20560fe637bSDr. David Alan Gilbert     f->buf_size = pending;
20660fe637bSDr. David Alan Gilbert 
20760fe637bSDr. David Alan Gilbert     len = f->ops->get_buffer(f->opaque, f->buf + pending, f->pos,
20860fe637bSDr. David Alan Gilbert                         IO_BUF_SIZE - pending);
20960fe637bSDr. David Alan Gilbert     if (len > 0) {
21060fe637bSDr. David Alan Gilbert         f->buf_size += len;
21160fe637bSDr. David Alan Gilbert         f->pos += len;
21260fe637bSDr. David Alan Gilbert     } else if (len == 0) {
21360fe637bSDr. David Alan Gilbert         qemu_file_set_error(f, -EIO);
21460fe637bSDr. David Alan Gilbert     } else if (len != -EAGAIN) {
21560fe637bSDr. David Alan Gilbert         qemu_file_set_error(f, len);
21660fe637bSDr. David Alan Gilbert     }
21760fe637bSDr. David Alan Gilbert 
21860fe637bSDr. David Alan Gilbert     return len;
21960fe637bSDr. David Alan Gilbert }
22060fe637bSDr. David Alan Gilbert 
22160fe637bSDr. David Alan Gilbert int qemu_get_fd(QEMUFile *f)
22260fe637bSDr. David Alan Gilbert {
22360fe637bSDr. David Alan Gilbert     if (f->ops->get_fd) {
22460fe637bSDr. David Alan Gilbert         return f->ops->get_fd(f->opaque);
22560fe637bSDr. David Alan Gilbert     }
22660fe637bSDr. David Alan Gilbert     return -1;
22760fe637bSDr. David Alan Gilbert }
22860fe637bSDr. David Alan Gilbert 
22960fe637bSDr. David Alan Gilbert void qemu_update_position(QEMUFile *f, size_t size)
23060fe637bSDr. David Alan Gilbert {
23160fe637bSDr. David Alan Gilbert     f->pos += size;
23260fe637bSDr. David Alan Gilbert }
23360fe637bSDr. David Alan Gilbert 
23460fe637bSDr. David Alan Gilbert /** Closes the file
23560fe637bSDr. David Alan Gilbert  *
23660fe637bSDr. David Alan Gilbert  * Returns negative error value if any error happened on previous operations or
23760fe637bSDr. David Alan Gilbert  * while closing the file. Returns 0 or positive number on success.
23860fe637bSDr. David Alan Gilbert  *
23960fe637bSDr. David Alan Gilbert  * The meaning of return value on success depends on the specific backend
24060fe637bSDr. David Alan Gilbert  * being used.
24160fe637bSDr. David Alan Gilbert  */
24260fe637bSDr. David Alan Gilbert int qemu_fclose(QEMUFile *f)
24360fe637bSDr. David Alan Gilbert {
24460fe637bSDr. David Alan Gilbert     int ret;
24560fe637bSDr. David Alan Gilbert     qemu_fflush(f);
24660fe637bSDr. David Alan Gilbert     ret = qemu_file_get_error(f);
24760fe637bSDr. David Alan Gilbert 
24860fe637bSDr. David Alan Gilbert     if (f->ops->close) {
24960fe637bSDr. David Alan Gilbert         int ret2 = f->ops->close(f->opaque);
25060fe637bSDr. David Alan Gilbert         if (ret >= 0) {
25160fe637bSDr. David Alan Gilbert             ret = ret2;
25260fe637bSDr. David Alan Gilbert         }
25360fe637bSDr. David Alan Gilbert     }
25460fe637bSDr. David Alan Gilbert     /* If any error was spotted before closing, we should report it
25560fe637bSDr. David Alan Gilbert      * instead of the close() return value.
25660fe637bSDr. David Alan Gilbert      */
25760fe637bSDr. David Alan Gilbert     if (f->last_error) {
25860fe637bSDr. David Alan Gilbert         ret = f->last_error;
25960fe637bSDr. David Alan Gilbert     }
26060fe637bSDr. David Alan Gilbert     g_free(f);
26160fe637bSDr. David Alan Gilbert     trace_qemu_file_fclose();
26260fe637bSDr. David Alan Gilbert     return ret;
26360fe637bSDr. David Alan Gilbert }
26460fe637bSDr. David Alan Gilbert 
26560fe637bSDr. David Alan Gilbert static void add_to_iovec(QEMUFile *f, const uint8_t *buf, int size)
26660fe637bSDr. David Alan Gilbert {
26760fe637bSDr. David Alan Gilbert     /* check for adjacent buffer and coalesce them */
26860fe637bSDr. David Alan Gilbert     if (f->iovcnt > 0 && buf == f->iov[f->iovcnt - 1].iov_base +
26960fe637bSDr. David Alan Gilbert         f->iov[f->iovcnt - 1].iov_len) {
27060fe637bSDr. David Alan Gilbert         f->iov[f->iovcnt - 1].iov_len += size;
27160fe637bSDr. David Alan Gilbert     } else {
27260fe637bSDr. David Alan Gilbert         f->iov[f->iovcnt].iov_base = (uint8_t *)buf;
27360fe637bSDr. David Alan Gilbert         f->iov[f->iovcnt++].iov_len = size;
27460fe637bSDr. David Alan Gilbert     }
27560fe637bSDr. David Alan Gilbert 
27660fe637bSDr. David Alan Gilbert     if (f->iovcnt >= MAX_IOV_SIZE) {
27760fe637bSDr. David Alan Gilbert         qemu_fflush(f);
27860fe637bSDr. David Alan Gilbert     }
27960fe637bSDr. David Alan Gilbert }
28060fe637bSDr. David Alan Gilbert 
28160fe637bSDr. David Alan Gilbert void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, int size)
28260fe637bSDr. David Alan Gilbert {
28360fe637bSDr. David Alan Gilbert     if (!f->ops->writev_buffer) {
28460fe637bSDr. David Alan Gilbert         qemu_put_buffer(f, buf, size);
28560fe637bSDr. David Alan Gilbert         return;
28660fe637bSDr. David Alan Gilbert     }
28760fe637bSDr. David Alan Gilbert 
28860fe637bSDr. David Alan Gilbert     if (f->last_error) {
28960fe637bSDr. David Alan Gilbert         return;
29060fe637bSDr. David Alan Gilbert     }
29160fe637bSDr. David Alan Gilbert 
29260fe637bSDr. David Alan Gilbert     f->bytes_xfer += size;
29360fe637bSDr. David Alan Gilbert     add_to_iovec(f, buf, size);
29460fe637bSDr. David Alan Gilbert }
29560fe637bSDr. David Alan Gilbert 
29660fe637bSDr. David Alan Gilbert void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
29760fe637bSDr. David Alan Gilbert {
29860fe637bSDr. David Alan Gilbert     int l;
29960fe637bSDr. David Alan Gilbert 
30060fe637bSDr. David Alan Gilbert     if (f->last_error) {
30160fe637bSDr. David Alan Gilbert         return;
30260fe637bSDr. David Alan Gilbert     }
30360fe637bSDr. David Alan Gilbert 
30460fe637bSDr. David Alan Gilbert     while (size > 0) {
30560fe637bSDr. David Alan Gilbert         l = IO_BUF_SIZE - f->buf_index;
30660fe637bSDr. David Alan Gilbert         if (l > size) {
30760fe637bSDr. David Alan Gilbert             l = size;
30860fe637bSDr. David Alan Gilbert         }
30960fe637bSDr. David Alan Gilbert         memcpy(f->buf + f->buf_index, buf, l);
31060fe637bSDr. David Alan Gilbert         f->bytes_xfer += l;
31160fe637bSDr. David Alan Gilbert         if (f->ops->writev_buffer) {
31260fe637bSDr. David Alan Gilbert             add_to_iovec(f, f->buf + f->buf_index, l);
31360fe637bSDr. David Alan Gilbert         }
31460fe637bSDr. David Alan Gilbert         f->buf_index += l;
31560fe637bSDr. David Alan Gilbert         if (f->buf_index == IO_BUF_SIZE) {
31660fe637bSDr. David Alan Gilbert             qemu_fflush(f);
31760fe637bSDr. David Alan Gilbert         }
31860fe637bSDr. David Alan Gilbert         if (qemu_file_get_error(f)) {
31960fe637bSDr. David Alan Gilbert             break;
32060fe637bSDr. David Alan Gilbert         }
32160fe637bSDr. David Alan Gilbert         buf += l;
32260fe637bSDr. David Alan Gilbert         size -= l;
32360fe637bSDr. David Alan Gilbert     }
32460fe637bSDr. David Alan Gilbert }
32560fe637bSDr. David Alan Gilbert 
32660fe637bSDr. David Alan Gilbert void qemu_put_byte(QEMUFile *f, int v)
32760fe637bSDr. David Alan Gilbert {
32860fe637bSDr. David Alan Gilbert     if (f->last_error) {
32960fe637bSDr. David Alan Gilbert         return;
33060fe637bSDr. David Alan Gilbert     }
33160fe637bSDr. David Alan Gilbert 
33260fe637bSDr. David Alan Gilbert     f->buf[f->buf_index] = v;
33360fe637bSDr. David Alan Gilbert     f->bytes_xfer++;
33460fe637bSDr. David Alan Gilbert     if (f->ops->writev_buffer) {
33560fe637bSDr. David Alan Gilbert         add_to_iovec(f, f->buf + f->buf_index, 1);
33660fe637bSDr. David Alan Gilbert     }
33760fe637bSDr. David Alan Gilbert     f->buf_index++;
33860fe637bSDr. David Alan Gilbert     if (f->buf_index == IO_BUF_SIZE) {
33960fe637bSDr. David Alan Gilbert         qemu_fflush(f);
34060fe637bSDr. David Alan Gilbert     }
34160fe637bSDr. David Alan Gilbert }
34260fe637bSDr. David Alan Gilbert 
34360fe637bSDr. David Alan Gilbert void qemu_file_skip(QEMUFile *f, int size)
34460fe637bSDr. David Alan Gilbert {
34560fe637bSDr. David Alan Gilbert     if (f->buf_index + size <= f->buf_size) {
34660fe637bSDr. David Alan Gilbert         f->buf_index += size;
34760fe637bSDr. David Alan Gilbert     }
34860fe637bSDr. David Alan Gilbert }
34960fe637bSDr. David Alan Gilbert 
35060fe637bSDr. David Alan Gilbert /*
35160fe637bSDr. David Alan Gilbert  * Read 'size' bytes from file (at 'offset') into buf without moving the
35260fe637bSDr. David Alan Gilbert  * pointer.
35360fe637bSDr. David Alan Gilbert  *
35460fe637bSDr. David Alan Gilbert  * It will return size bytes unless there was an error, in which case it will
35560fe637bSDr. David Alan Gilbert  * return as many as it managed to read (assuming blocking fd's which
35660fe637bSDr. David Alan Gilbert  * all current QEMUFile are)
35760fe637bSDr. David Alan Gilbert  */
35860fe637bSDr. David Alan Gilbert int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset)
35960fe637bSDr. David Alan Gilbert {
36060fe637bSDr. David Alan Gilbert     int pending;
36160fe637bSDr. David Alan Gilbert     int index;
36260fe637bSDr. David Alan Gilbert 
36360fe637bSDr. David Alan Gilbert     assert(!qemu_file_is_writable(f));
36460fe637bSDr. David Alan Gilbert     assert(offset < IO_BUF_SIZE);
36560fe637bSDr. David Alan Gilbert     assert(size <= IO_BUF_SIZE - offset);
36660fe637bSDr. David Alan Gilbert 
36760fe637bSDr. David Alan Gilbert     /* The 1st byte to read from */
36860fe637bSDr. David Alan Gilbert     index = f->buf_index + offset;
36960fe637bSDr. David Alan Gilbert     /* The number of available bytes starting at index */
37060fe637bSDr. David Alan Gilbert     pending = f->buf_size - index;
37160fe637bSDr. David Alan Gilbert 
37260fe637bSDr. David Alan Gilbert     /*
37360fe637bSDr. David Alan Gilbert      * qemu_fill_buffer might return just a few bytes, even when there isn't
37460fe637bSDr. David Alan Gilbert      * an error, so loop collecting them until we get enough.
37560fe637bSDr. David Alan Gilbert      */
37660fe637bSDr. David Alan Gilbert     while (pending < size) {
37760fe637bSDr. David Alan Gilbert         int received = qemu_fill_buffer(f);
37860fe637bSDr. David Alan Gilbert 
37960fe637bSDr. David Alan Gilbert         if (received <= 0) {
38060fe637bSDr. David Alan Gilbert             break;
38160fe637bSDr. David Alan Gilbert         }
38260fe637bSDr. David Alan Gilbert 
38360fe637bSDr. David Alan Gilbert         index = f->buf_index + offset;
38460fe637bSDr. David Alan Gilbert         pending = f->buf_size - index;
38560fe637bSDr. David Alan Gilbert     }
38660fe637bSDr. David Alan Gilbert 
38760fe637bSDr. David Alan Gilbert     if (pending <= 0) {
38860fe637bSDr. David Alan Gilbert         return 0;
38960fe637bSDr. David Alan Gilbert     }
39060fe637bSDr. David Alan Gilbert     if (size > pending) {
39160fe637bSDr. David Alan Gilbert         size = pending;
39260fe637bSDr. David Alan Gilbert     }
39360fe637bSDr. David Alan Gilbert 
39460fe637bSDr. David Alan Gilbert     memcpy(buf, f->buf + index, size);
39560fe637bSDr. David Alan Gilbert     return size;
39660fe637bSDr. David Alan Gilbert }
39760fe637bSDr. David Alan Gilbert 
39860fe637bSDr. David Alan Gilbert /*
39960fe637bSDr. David Alan Gilbert  * Read 'size' bytes of data from the file into buf.
40060fe637bSDr. David Alan Gilbert  * 'size' can be larger than the internal buffer.
40160fe637bSDr. David Alan Gilbert  *
40260fe637bSDr. David Alan Gilbert  * It will return size bytes unless there was an error, in which case it will
40360fe637bSDr. David Alan Gilbert  * return as many as it managed to read (assuming blocking fd's which
40460fe637bSDr. David Alan Gilbert  * all current QEMUFile are)
40560fe637bSDr. David Alan Gilbert  */
40660fe637bSDr. David Alan Gilbert int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
40760fe637bSDr. David Alan Gilbert {
40860fe637bSDr. David Alan Gilbert     int pending = size;
40960fe637bSDr. David Alan Gilbert     int done = 0;
41060fe637bSDr. David Alan Gilbert 
41160fe637bSDr. David Alan Gilbert     while (pending > 0) {
41260fe637bSDr. David Alan Gilbert         int res;
41360fe637bSDr. David Alan Gilbert 
41460fe637bSDr. David Alan Gilbert         res = qemu_peek_buffer(f, buf, MIN(pending, IO_BUF_SIZE), 0);
41560fe637bSDr. David Alan Gilbert         if (res == 0) {
41660fe637bSDr. David Alan Gilbert             return done;
41760fe637bSDr. David Alan Gilbert         }
41860fe637bSDr. David Alan Gilbert         qemu_file_skip(f, res);
41960fe637bSDr. David Alan Gilbert         buf += res;
42060fe637bSDr. David Alan Gilbert         pending -= res;
42160fe637bSDr. David Alan Gilbert         done += res;
42260fe637bSDr. David Alan Gilbert     }
42360fe637bSDr. David Alan Gilbert     return done;
42460fe637bSDr. David Alan Gilbert }
42560fe637bSDr. David Alan Gilbert 
42660fe637bSDr. David Alan Gilbert /*
42760fe637bSDr. David Alan Gilbert  * Peeks a single byte from the buffer; this isn't guaranteed to work if
42860fe637bSDr. David Alan Gilbert  * offset leaves a gap after the previous read/peeked data.
42960fe637bSDr. David Alan Gilbert  */
43060fe637bSDr. David Alan Gilbert int qemu_peek_byte(QEMUFile *f, int offset)
43160fe637bSDr. David Alan Gilbert {
43260fe637bSDr. David Alan Gilbert     int index = f->buf_index + offset;
43360fe637bSDr. David Alan Gilbert 
43460fe637bSDr. David Alan Gilbert     assert(!qemu_file_is_writable(f));
43560fe637bSDr. David Alan Gilbert     assert(offset < IO_BUF_SIZE);
43660fe637bSDr. David Alan Gilbert 
43760fe637bSDr. David Alan Gilbert     if (index >= f->buf_size) {
43860fe637bSDr. David Alan Gilbert         qemu_fill_buffer(f);
43960fe637bSDr. David Alan Gilbert         index = f->buf_index + offset;
44060fe637bSDr. David Alan Gilbert         if (index >= f->buf_size) {
44160fe637bSDr. David Alan Gilbert             return 0;
44260fe637bSDr. David Alan Gilbert         }
44360fe637bSDr. David Alan Gilbert     }
44460fe637bSDr. David Alan Gilbert     return f->buf[index];
44560fe637bSDr. David Alan Gilbert }
44660fe637bSDr. David Alan Gilbert 
44760fe637bSDr. David Alan Gilbert int qemu_get_byte(QEMUFile *f)
44860fe637bSDr. David Alan Gilbert {
44960fe637bSDr. David Alan Gilbert     int result;
45060fe637bSDr. David Alan Gilbert 
45160fe637bSDr. David Alan Gilbert     result = qemu_peek_byte(f, 0);
45260fe637bSDr. David Alan Gilbert     qemu_file_skip(f, 1);
45360fe637bSDr. David Alan Gilbert     return result;
45460fe637bSDr. David Alan Gilbert }
45560fe637bSDr. David Alan Gilbert 
45697221400SAlexander Graf int64_t qemu_ftell_fast(QEMUFile *f)
45797221400SAlexander Graf {
45897221400SAlexander Graf     int64_t ret = f->pos;
45997221400SAlexander Graf     int i;
46097221400SAlexander Graf 
46197221400SAlexander Graf     if (f->ops->writev_buffer) {
46297221400SAlexander Graf         for (i = 0; i < f->iovcnt; i++) {
46397221400SAlexander Graf             ret += f->iov[i].iov_len;
46497221400SAlexander Graf         }
46597221400SAlexander Graf     } else {
46697221400SAlexander Graf         ret += f->buf_index;
46797221400SAlexander Graf     }
46897221400SAlexander Graf 
46997221400SAlexander Graf     return ret;
47097221400SAlexander Graf }
47197221400SAlexander Graf 
47260fe637bSDr. David Alan Gilbert int64_t qemu_ftell(QEMUFile *f)
47360fe637bSDr. David Alan Gilbert {
47460fe637bSDr. David Alan Gilbert     qemu_fflush(f);
47560fe637bSDr. David Alan Gilbert     return f->pos;
47660fe637bSDr. David Alan Gilbert }
47760fe637bSDr. David Alan Gilbert 
47860fe637bSDr. David Alan Gilbert int qemu_file_rate_limit(QEMUFile *f)
47960fe637bSDr. David Alan Gilbert {
48060fe637bSDr. David Alan Gilbert     if (qemu_file_get_error(f)) {
48160fe637bSDr. David Alan Gilbert         return 1;
48260fe637bSDr. David Alan Gilbert     }
48360fe637bSDr. David Alan Gilbert     if (f->xfer_limit > 0 && f->bytes_xfer > f->xfer_limit) {
48460fe637bSDr. David Alan Gilbert         return 1;
48560fe637bSDr. David Alan Gilbert     }
48660fe637bSDr. David Alan Gilbert     return 0;
48760fe637bSDr. David Alan Gilbert }
48860fe637bSDr. David Alan Gilbert 
48960fe637bSDr. David Alan Gilbert int64_t qemu_file_get_rate_limit(QEMUFile *f)
49060fe637bSDr. David Alan Gilbert {
49160fe637bSDr. David Alan Gilbert     return f->xfer_limit;
49260fe637bSDr. David Alan Gilbert }
49360fe637bSDr. David Alan Gilbert 
49460fe637bSDr. David Alan Gilbert void qemu_file_set_rate_limit(QEMUFile *f, int64_t limit)
49560fe637bSDr. David Alan Gilbert {
49660fe637bSDr. David Alan Gilbert     f->xfer_limit = limit;
49760fe637bSDr. David Alan Gilbert }
49860fe637bSDr. David Alan Gilbert 
49960fe637bSDr. David Alan Gilbert void qemu_file_reset_rate_limit(QEMUFile *f)
50060fe637bSDr. David Alan Gilbert {
50160fe637bSDr. David Alan Gilbert     f->bytes_xfer = 0;
50260fe637bSDr. David Alan Gilbert }
50360fe637bSDr. David Alan Gilbert 
50460fe637bSDr. David Alan Gilbert void qemu_put_be16(QEMUFile *f, unsigned int v)
50560fe637bSDr. David Alan Gilbert {
50660fe637bSDr. David Alan Gilbert     qemu_put_byte(f, v >> 8);
50760fe637bSDr. David Alan Gilbert     qemu_put_byte(f, v);
50860fe637bSDr. David Alan Gilbert }
50960fe637bSDr. David Alan Gilbert 
51060fe637bSDr. David Alan Gilbert void qemu_put_be32(QEMUFile *f, unsigned int v)
51160fe637bSDr. David Alan Gilbert {
51260fe637bSDr. David Alan Gilbert     qemu_put_byte(f, v >> 24);
51360fe637bSDr. David Alan Gilbert     qemu_put_byte(f, v >> 16);
51460fe637bSDr. David Alan Gilbert     qemu_put_byte(f, v >> 8);
51560fe637bSDr. David Alan Gilbert     qemu_put_byte(f, v);
51660fe637bSDr. David Alan Gilbert }
51760fe637bSDr. David Alan Gilbert 
51860fe637bSDr. David Alan Gilbert void qemu_put_be64(QEMUFile *f, uint64_t v)
51960fe637bSDr. David Alan Gilbert {
52060fe637bSDr. David Alan Gilbert     qemu_put_be32(f, v >> 32);
52160fe637bSDr. David Alan Gilbert     qemu_put_be32(f, v);
52260fe637bSDr. David Alan Gilbert }
52360fe637bSDr. David Alan Gilbert 
52460fe637bSDr. David Alan Gilbert unsigned int qemu_get_be16(QEMUFile *f)
52560fe637bSDr. David Alan Gilbert {
52660fe637bSDr. David Alan Gilbert     unsigned int v;
52760fe637bSDr. David Alan Gilbert     v = qemu_get_byte(f) << 8;
52860fe637bSDr. David Alan Gilbert     v |= qemu_get_byte(f);
52960fe637bSDr. David Alan Gilbert     return v;
53060fe637bSDr. David Alan Gilbert }
53160fe637bSDr. David Alan Gilbert 
53260fe637bSDr. David Alan Gilbert unsigned int qemu_get_be32(QEMUFile *f)
53360fe637bSDr. David Alan Gilbert {
53460fe637bSDr. David Alan Gilbert     unsigned int v;
53590d6a673SPeter Maydell     v = (unsigned int)qemu_get_byte(f) << 24;
53660fe637bSDr. David Alan Gilbert     v |= qemu_get_byte(f) << 16;
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 uint64_t qemu_get_be64(QEMUFile *f)
54360fe637bSDr. David Alan Gilbert {
54460fe637bSDr. David Alan Gilbert     uint64_t v;
54560fe637bSDr. David Alan Gilbert     v = (uint64_t)qemu_get_be32(f) << 32;
54660fe637bSDr. David Alan Gilbert     v |= qemu_get_be32(f);
54760fe637bSDr. David Alan Gilbert     return v;
54860fe637bSDr. David Alan Gilbert }
549