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