| 
									
										
										
										
											2014-10-01 14:47:33 -03:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * QEMU System Emulator | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2003-2008 Fabrice Bellard | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | 
					
						
							|  |  |  |  * of this software and associated documentation files (the "Software"), to deal | 
					
						
							|  |  |  |  * in the Software without restriction, including without limitation the rights | 
					
						
							|  |  |  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
					
						
							|  |  |  |  * copies of the Software, and to permit persons to whom the Software is | 
					
						
							|  |  |  |  * furnished to do so, subject to the following conditions: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The above copyright notice and this permission notice shall be included in | 
					
						
							|  |  |  |  * all copies or substantial portions of the Software. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
					
						
							|  |  |  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
					
						
							|  |  |  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | 
					
						
							|  |  |  |  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
					
						
							|  |  |  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
					
						
							|  |  |  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 
					
						
							|  |  |  |  * THE SOFTWARE. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-01-26 18:16:54 +00:00
										 |  |  | #include "qemu/osdep.h"
 | 
					
						
							| 
									
										
										
										
											2015-03-23 16:32:19 +08:00
										 |  |  | #include <zlib.h>
 | 
					
						
							| 
									
										
										
										
											2015-03-17 18:29:20 +01:00
										 |  |  | #include "qemu/error-report.h"
 | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | #include "qemu/iov.h"
 | 
					
						
							| 
									
										
										
										
											2017-04-24 20:07:27 +02:00
										 |  |  | #include "migration.h"
 | 
					
						
							| 
									
										
										
										
											2017-04-20 18:52:18 +02:00
										 |  |  | #include "qemu-file.h"
 | 
					
						
							| 
									
										
										
										
											2014-03-11 10:42:29 +11:00
										 |  |  | #include "trace.h"
 | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  | #include "qapi/error.h"
 | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-27 11:05:13 +01:00
										 |  |  | #define IO_BUF_SIZE 32768
 | 
					
						
							| 
									
										
											  
											
												osdep: Make MIN/MAX evaluate arguments only once
I'm not aware of any immediate bugs in qemu where a second runtime
evaluation of the arguments to MIN() or MAX() causes a problem, but
proactively preventing such abuse is easier than falling prey to an
unintended case down the road.  At any rate, here's the conversation
that sparked the current patch:
https://lists.gnu.org/archive/html/qemu-devel/2018-12/msg05718.html
Update the MIN/MAX macros to only evaluate their argument once at
runtime; this uses typeof(1 ? (a) : (b)) to ensure that we are
promoting the temporaries to the same type as the final comparison (we
have to trigger type promotion, as typeof(bitfield) won't compile; and
we can't use typeof((a) + (b)) or even typeof((a) + 0), as some of our
uses of MAX are on void* pointers where such addition is undefined).
However, we are unable to work around gcc refusing to compile ({}) in
a constant context (such as the array length of a static variable),
even when only used in the dead branch of a __builtin_choose_expr(),
so we have to provide a second macro pair MIN_CONST and MAX_CONST for
use when both arguments are known to be compile-time constants and
where the result must also be usable as a constant; this second form
evaluates arguments multiple times but that doesn't matter for
constants.  By using a void expression as the expansion if a
non-constant is presented to this second form, we can enlist the
compiler to ensure the double evaluation is not attempted on
non-constants.
Alas, as both macros now rely on compiler intrinsics, they are no
longer usable in preprocessor #if conditions; those will just have to
be open-coded or the logic rewritten into #define or runtime 'if'
conditions (but where the compiler dead-code-elimination will probably
still apply).
I tested that both gcc 10.1.1 and clang 10.0.0 produce errors for all
forms of macro mis-use.  As the errors can sometimes be cryptic, I'm
demonstrating the gcc output:
Use of MIN when MIN_CONST is needed:
In file included from /home/eblake/qemu/qemu-img.c:25:
/home/eblake/qemu/include/qemu/osdep.h:249:5: error: braced-group within expression allowed only inside a function
  249 |     ({                                                  \
      |     ^
/home/eblake/qemu/qemu-img.c:92:12: note: in expansion of macro ‘MIN’
   92 | char array[MIN(1, 2)] = "";
      |            ^~~
Use of MIN_CONST when MIN is needed:
/home/eblake/qemu/qemu-img.c: In function ‘is_allocated_sectors’:
/home/eblake/qemu/qemu-img.c:1225:15: error: void value not ignored as it ought to be
 1225 |             i = MIN_CONST(i, n);
      |               ^
Use of MIN in the preprocessor:
In file included from /home/eblake/qemu/accel/tcg/translate-all.c:20:
/home/eblake/qemu/accel/tcg/translate-all.c: In function ‘page_check_range’:
/home/eblake/qemu/include/qemu/osdep.h:249:6: error: token "{" is not valid in preprocessor expressions
  249 |     ({                                                  \
      |      ^
Fix the resulting callsites that used #if or computed a compile-time
constant min or max to use the new macros.  cpu-defs.h is interesting,
as CPU_TLB_DYN_MAX_BITS is sometimes used as a constant and sometimes
dynamic.
It may be worth improving glib's MIN/MAX definitions to be saner, but
that is a task for another day.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20200625162602.700741-1-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
											
										 
											2020-06-25 11:26:02 -05:00
										 |  |  | #define MAX_IOV_SIZE MIN_CONST(IOV_MAX, 64)
 | 
					
						
							| 
									
										
										
										
											2016-04-27 11:05:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | struct QEMUFile { | 
					
						
							|  |  |  |     const QEMUFileOps *ops; | 
					
						
							|  |  |  |     const QEMUFileHooks *hooks; | 
					
						
							|  |  |  |     void *opaque; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int64_t bytes_xfer; | 
					
						
							|  |  |  |     int64_t xfer_limit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int64_t pos; /* start of buffer when writing, end of buffer
 | 
					
						
							|  |  |  |                     when reading */ | 
					
						
							|  |  |  |     int buf_index; | 
					
						
							|  |  |  |     int buf_size; /* 0 when writing */ | 
					
						
							|  |  |  |     uint8_t buf[IO_BUF_SIZE]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-03 18:23:20 +03:00
										 |  |  |     DECLARE_BITMAP(may_free, MAX_IOV_SIZE); | 
					
						
							| 
									
										
										
										
											2016-04-27 11:05:13 +01:00
										 |  |  |     struct iovec iov[MAX_IOV_SIZE]; | 
					
						
							|  |  |  |     unsigned int iovcnt; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int last_error; | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  |     Error *last_error_obj; | 
					
						
							| 
									
										
										
										
											2019-12-18 05:11:31 +01:00
										 |  |  |     /* has the file has been shutdown */ | 
					
						
							|  |  |  |     bool shutdown; | 
					
						
							| 
									
										
										
										
											2016-04-27 11:05:13 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-08 11:11:30 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Stop a file from being read/written - not all backing files can do this | 
					
						
							|  |  |  |  * typically only sockets can. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int qemu_file_shutdown(QEMUFile *f) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-12-18 05:11:31 +01:00
										 |  |  |     int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     f->shutdown = true; | 
					
						
							| 
									
										
										
										
											2015-01-08 11:11:30 +00:00
										 |  |  |     if (!f->ops->shut_down) { | 
					
						
							|  |  |  |         return -ENOSYS; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-12-18 05:11:31 +01:00
										 |  |  |     ret = f->ops->shut_down(f->opaque, true, true, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!f->last_error) { | 
					
						
							|  |  |  |         qemu_file_set_error(f, -EIO); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2015-01-08 11:11:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-05 18:10:43 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Result: QEMUFile* for a 'return path' for comms in the opposite direction | 
					
						
							|  |  |  |  *         NULL if not available | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | QEMUFile *qemu_file_get_return_path(QEMUFile *f) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!f->ops->get_return_path) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return f->ops->get_return_path(f->opaque); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | bool qemu_file_mode_is_not_valid(const char *mode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (mode == NULL || | 
					
						
							|  |  |  |         (mode[0] != 'r' && mode[0] != 'w') || | 
					
						
							|  |  |  |         mode[1] != 'b' || mode[2] != 0) { | 
					
						
							|  |  |  |         fprintf(stderr, "qemu_fopen: Argument validity check failed\n"); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QEMUFile *f; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-14 13:51:31 +02:00
										 |  |  |     f = g_new0(QEMUFile, 1); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     f->opaque = opaque; | 
					
						
							|  |  |  |     f->ops = ops; | 
					
						
							|  |  |  |     return f; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-27 11:04:55 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | void qemu_file_set_hooks(QEMUFile *f, const QEMUFileHooks *hooks) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     f->hooks = hooks; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  |  * Get last error for stream f with optional Error* | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Return negative error value if there has been an error on previous | 
					
						
							|  |  |  |  * operations, return 0 if no error happened. | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  |  * Optional, it returns Error* in errp, but it may be NULL even if return value | 
					
						
							|  |  |  |  * is not 0. | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  | int qemu_file_get_error_obj(QEMUFile *f, Error **errp) | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  |     if (errp) { | 
					
						
							|  |  |  |         *errp = f->last_error_obj ? error_copy(f->last_error_obj) : NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |     return f->last_error; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Set the last error for stream f with optional Error* | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void qemu_file_set_error_obj(QEMUFile *f, int ret, Error *err) | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  |     if (f->last_error == 0 && ret) { | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |         f->last_error = ret; | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  |         error_propagate(&f->last_error_obj, err); | 
					
						
							|  |  |  |     } else if (err) { | 
					
						
							|  |  |  |         error_report_err(err); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Get last error for stream f | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Return negative error value if there has been an error on previous | 
					
						
							|  |  |  |  * operations, return 0 if no error happened. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int qemu_file_get_error(QEMUFile *f) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return qemu_file_get_error_obj(f, NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Set the last error for stream f | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void qemu_file_set_error(QEMUFile *f, int ret) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qemu_file_set_error_obj(f, ret, NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-01 17:34:34 -03:00
										 |  |  | bool qemu_file_is_writable(QEMUFile *f) | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-04-27 11:05:17 +01:00
										 |  |  |     return f->ops->writev_buffer; | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-03 18:23:20 +03:00
										 |  |  | static void qemu_iovec_release_ram(QEMUFile *f) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct iovec iov; | 
					
						
							|  |  |  |     unsigned long idx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Find and release all the contiguous memory ranges marked as may_free. */ | 
					
						
							|  |  |  |     idx = find_next_bit(f->may_free, f->iovcnt, 0); | 
					
						
							|  |  |  |     if (idx >= f->iovcnt) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     iov = f->iov[idx]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* The madvise() in the loop is called for iov within a continuous range and
 | 
					
						
							|  |  |  |      * then reinitialize the iov. And in the end, madvise() is called for the | 
					
						
							|  |  |  |      * last iov. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     while ((idx = find_next_bit(f->may_free, f->iovcnt, idx + 1)) < f->iovcnt) { | 
					
						
							|  |  |  |         /* check for adjacent buffer and coalesce them */ | 
					
						
							|  |  |  |         if (iov.iov_base + iov.iov_len == f->iov[idx].iov_base) { | 
					
						
							|  |  |  |             iov.iov_len += f->iov[idx].iov_len; | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (qemu_madvise(iov.iov_base, iov.iov_len, QEMU_MADV_DONTNEED) < 0) { | 
					
						
							|  |  |  |             error_report("migrate: madvise DONTNEED failed %p %zd: %s", | 
					
						
							|  |  |  |                          iov.iov_base, iov.iov_len, strerror(errno)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         iov = f->iov[idx]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (qemu_madvise(iov.iov_base, iov.iov_len, QEMU_MADV_DONTNEED) < 0) { | 
					
						
							|  |  |  |             error_report("migrate: madvise DONTNEED failed %p %zd: %s", | 
					
						
							|  |  |  |                          iov.iov_base, iov.iov_len, strerror(errno)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     memset(f->may_free, 0, sizeof(f->may_free)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Flushes QEMUFile buffer | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-08-23 11:39:46 +01:00
										 |  |  |  * This will flush all pending data. If data was only partially flushed, it | 
					
						
							|  |  |  |  * will set an error state. | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |  */ | 
					
						
							|  |  |  | void qemu_fflush(QEMUFile *f) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ssize_t ret = 0; | 
					
						
							| 
									
										
										
										
											2016-04-27 11:04:54 +01:00
										 |  |  |     ssize_t expect = 0; | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  |     Error *local_error = NULL; | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!qemu_file_is_writable(f)) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-18 05:11:31 +01:00
										 |  |  |     if (f->shutdown) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-04-27 11:05:17 +01:00
										 |  |  |     if (f->iovcnt > 0) { | 
					
						
							|  |  |  |         expect = iov_size(f->iov, f->iovcnt); | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  |         ret = f->ops->writev_buffer(f->opaque, f->iov, f->iovcnt, f->pos, | 
					
						
							|  |  |  |                                     &local_error); | 
					
						
							| 
									
										
										
										
											2017-02-03 18:23:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |         qemu_iovec_release_ram(f); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-04-27 11:04:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |     if (ret >= 0) { | 
					
						
							|  |  |  |         f->pos += ret; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-04-27 11:04:54 +01:00
										 |  |  |     /* We expect the QEMUFile write impl to send the full
 | 
					
						
							|  |  |  |      * data set we requested, so sanity check that. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (ret != expect) { | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  |         qemu_file_set_error_obj(f, ret < 0 ? ret : -EIO, local_error); | 
					
						
							| 
									
										
										
										
											2016-04-27 11:04:54 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |     f->buf_index = 0; | 
					
						
							|  |  |  |     f->iovcnt = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ram_control_before_iterate(QEMUFile *f, uint64_t flags) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int ret = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-27 11:04:55 +01:00
										 |  |  |     if (f->hooks && f->hooks->before_ram_iterate) { | 
					
						
							|  |  |  |         ret = f->hooks->before_ram_iterate(f, f->opaque, flags, NULL); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |         if (ret < 0) { | 
					
						
							|  |  |  |             qemu_file_set_error(f, ret); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ram_control_after_iterate(QEMUFile *f, uint64_t flags) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int ret = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-27 11:04:55 +01:00
										 |  |  |     if (f->hooks && f->hooks->after_ram_iterate) { | 
					
						
							|  |  |  |         ret = f->hooks->after_ram_iterate(f, f->opaque, flags, NULL); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |         if (ret < 0) { | 
					
						
							|  |  |  |             qemu_file_set_error(f, ret); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-11 18:17:23 +01:00
										 |  |  | void ram_control_load_hook(QEMUFile *f, uint64_t flags, void *data) | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | { | 
					
						
							|  |  |  |     int ret = -EINVAL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-27 11:04:55 +01:00
										 |  |  |     if (f->hooks && f->hooks->hook_ram_load) { | 
					
						
							|  |  |  |         ret = f->hooks->hook_ram_load(f, f->opaque, flags, data); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |         if (ret < 0) { | 
					
						
							|  |  |  |             qemu_file_set_error(f, ret); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2015-06-11 18:17:23 +01:00
										 |  |  |         /*
 | 
					
						
							|  |  |  |          * Hook is a hook specifically requested by the source sending a flag | 
					
						
							|  |  |  |          * that expects there to be a hook on the destination. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if (flags == RAM_CONTROL_HOOK) { | 
					
						
							|  |  |  |             qemu_file_set_error(f, ret); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset, | 
					
						
							| 
									
										
										
										
											2015-02-12 19:02:42 +01:00
										 |  |  |                              ram_addr_t offset, size_t size, | 
					
						
							|  |  |  |                              uint64_t *bytes_sent) | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-04-27 11:04:55 +01:00
										 |  |  |     if (f->hooks && f->hooks->save_page) { | 
					
						
							|  |  |  |         int ret = f->hooks->save_page(f, f->opaque, block_offset, | 
					
						
							|  |  |  |                                       offset, size, bytes_sent); | 
					
						
							| 
									
										
										
										
											2018-08-06 21:29:27 +08:00
										 |  |  |         if (ret != RAM_SAVE_CONTROL_NOT_SUPP) { | 
					
						
							|  |  |  |             f->bytes_xfer += size; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (ret != RAM_SAVE_CONTROL_DELAYED && | 
					
						
							|  |  |  |             ret != RAM_SAVE_CONTROL_NOT_SUPP) { | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |             if (bytes_sent && *bytes_sent > 0) { | 
					
						
							|  |  |  |                 qemu_update_position(f, *bytes_sent); | 
					
						
							|  |  |  |             } else if (ret < 0) { | 
					
						
							|  |  |  |                 qemu_file_set_error(f, ret); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return ret; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return RAM_SAVE_CONTROL_NOT_SUPP; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-08 15:29:37 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Attempt to fill the buffer from the underlying file | 
					
						
							|  |  |  |  * Returns the number of bytes read, or negative value for an error. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Note that it can return a partially full buffer even in a not error/not EOF | 
					
						
							|  |  |  |  * case if the underlying file descriptor gives a short read, and that can | 
					
						
							|  |  |  |  * happen even on a blocking fd. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static ssize_t qemu_fill_buffer(QEMUFile *f) | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | { | 
					
						
							|  |  |  |     int len; | 
					
						
							|  |  |  |     int pending; | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  |     Error *local_error = NULL; | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     assert(!qemu_file_is_writable(f)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pending = f->buf_size - f->buf_index; | 
					
						
							|  |  |  |     if (pending > 0) { | 
					
						
							|  |  |  |         memmove(f->buf, f->buf + f->buf_index, pending); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     f->buf_index = 0; | 
					
						
							|  |  |  |     f->buf_size = pending; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-18 05:11:31 +01:00
										 |  |  |     if (f->shutdown) { | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |     len = f->ops->get_buffer(f->opaque, f->buf + pending, f->pos, | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  |                              IO_BUF_SIZE - pending, &local_error); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |     if (len > 0) { | 
					
						
							|  |  |  |         f->buf_size += len; | 
					
						
							|  |  |  |         f->pos += len; | 
					
						
							|  |  |  |     } else if (len == 0) { | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  |         qemu_file_set_error_obj(f, -EIO, local_error); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |     } else if (len != -EAGAIN) { | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  |         qemu_file_set_error_obj(f, len, local_error); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         error_free(local_error); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-04-08 15:29:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return len; | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void qemu_update_position(QEMUFile *f, size_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     f->pos += size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** Closes the file
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Returns negative error value if any error happened on previous operations or | 
					
						
							|  |  |  |  * while closing the file. Returns 0 or positive number on success. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The meaning of return value on success depends on the specific backend | 
					
						
							|  |  |  |  * being used. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int qemu_fclose(QEMUFile *f) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int ret; | 
					
						
							|  |  |  |     qemu_fflush(f); | 
					
						
							|  |  |  |     ret = qemu_file_get_error(f); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (f->ops->close) { | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  |         int ret2 = f->ops->close(f->opaque, NULL); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |         if (ret >= 0) { | 
					
						
							|  |  |  |             ret = ret2; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* If any error was spotted before closing, we should report it
 | 
					
						
							|  |  |  |      * instead of the close() return value. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (f->last_error) { | 
					
						
							|  |  |  |         ret = f->last_error; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  |     error_free(f->last_error_obj); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |     g_free(f); | 
					
						
							| 
									
										
										
										
											2014-03-11 10:42:29 +11:00
										 |  |  |     trace_qemu_file_fclose(); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-11 13:28:39 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Add buf to iovec. Do flush if iovec is full. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Return values: | 
					
						
							|  |  |  |  * 1 iovec is full and flushed | 
					
						
							|  |  |  |  * 0 iovec is not flushed | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int add_to_iovec(QEMUFile *f, const uint8_t *buf, size_t size, | 
					
						
							|  |  |  |                         bool may_free) | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | { | 
					
						
							|  |  |  |     /* check for adjacent buffer and coalesce them */ | 
					
						
							|  |  |  |     if (f->iovcnt > 0 && buf == f->iov[f->iovcnt - 1].iov_base + | 
					
						
							| 
									
										
										
										
											2017-02-03 18:23:20 +03:00
										 |  |  |         f->iov[f->iovcnt - 1].iov_len && | 
					
						
							|  |  |  |         may_free == test_bit(f->iovcnt - 1, f->may_free)) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |         f->iov[f->iovcnt - 1].iov_len += size; | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2017-02-03 18:23:20 +03:00
										 |  |  |         if (may_free) { | 
					
						
							|  |  |  |             set_bit(f->iovcnt, f->may_free); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |         f->iov[f->iovcnt].iov_base = (uint8_t *)buf; | 
					
						
							|  |  |  |         f->iov[f->iovcnt++].iov_len = size; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (f->iovcnt >= MAX_IOV_SIZE) { | 
					
						
							|  |  |  |         qemu_fflush(f); | 
					
						
							| 
									
										
										
										
											2019-09-11 13:28:39 +00:00
										 |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void add_buf_to_iovec(QEMUFile *f, size_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!add_to_iovec(f, f->buf + f->buf_index, len, false)) { | 
					
						
							|  |  |  |         f->buf_index += len; | 
					
						
							|  |  |  |         if (f->buf_index == IO_BUF_SIZE) { | 
					
						
							|  |  |  |             qemu_fflush(f); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-03 18:23:20 +03:00
										 |  |  | void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, size_t size, | 
					
						
							|  |  |  |                            bool may_free) | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (f->last_error) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     f->bytes_xfer += size; | 
					
						
							| 
									
										
										
										
											2017-02-03 18:23:20 +03:00
										 |  |  |     add_to_iovec(f, buf, size, may_free); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-13 11:51:34 +01:00
										 |  |  | void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, size_t size) | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-08-13 11:51:34 +01:00
										 |  |  |     size_t l; | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (f->last_error) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (size > 0) { | 
					
						
							|  |  |  |         l = IO_BUF_SIZE - f->buf_index; | 
					
						
							|  |  |  |         if (l > size) { | 
					
						
							|  |  |  |             l = size; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         memcpy(f->buf + f->buf_index, buf, l); | 
					
						
							|  |  |  |         f->bytes_xfer += l; | 
					
						
							| 
									
										
										
										
											2019-09-11 13:28:39 +00:00
										 |  |  |         add_buf_to_iovec(f, l); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |         if (qemu_file_get_error(f)) { | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         buf += l; | 
					
						
							|  |  |  |         size -= l; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void qemu_put_byte(QEMUFile *f, int v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (f->last_error) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     f->buf[f->buf_index] = v; | 
					
						
							|  |  |  |     f->bytes_xfer++; | 
					
						
							| 
									
										
										
										
											2019-09-11 13:28:39 +00:00
										 |  |  |     add_buf_to_iovec(f, 1); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void qemu_file_skip(QEMUFile *f, int size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (f->buf_index + size <= f->buf_size) { | 
					
						
							|  |  |  |         f->buf_index += size; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-08 15:29:37 +01:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2015-05-21 13:24:15 +01:00
										 |  |  |  * Read 'size' bytes from file (at 'offset') without moving the | 
					
						
							|  |  |  |  * pointer and set 'buf' to point to that data. | 
					
						
							| 
									
										
										
										
											2014-04-08 15:29:37 +01:00
										 |  |  |  * | 
					
						
							|  |  |  |  * It will return size bytes unless there was an error, in which case it will | 
					
						
							|  |  |  |  * return as many as it managed to read (assuming blocking fd's which | 
					
						
							|  |  |  |  * all current QEMUFile are) | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-08-13 11:51:34 +01:00
										 |  |  | size_t qemu_peek_buffer(QEMUFile *f, uint8_t **buf, size_t size, size_t offset) | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-08-13 11:51:34 +01:00
										 |  |  |     ssize_t pending; | 
					
						
							|  |  |  |     size_t index; | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     assert(!qemu_file_is_writable(f)); | 
					
						
							| 
									
										
										
										
											2014-04-08 15:29:37 +01:00
										 |  |  |     assert(offset < IO_BUF_SIZE); | 
					
						
							|  |  |  |     assert(size <= IO_BUF_SIZE - offset); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-08 15:29:37 +01:00
										 |  |  |     /* The 1st byte to read from */ | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |     index = f->buf_index + offset; | 
					
						
							| 
									
										
										
										
											2014-04-08 15:29:37 +01:00
										 |  |  |     /* The number of available bytes starting at index */ | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |     pending = f->buf_size - index; | 
					
						
							| 
									
										
										
										
											2014-04-08 15:29:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * qemu_fill_buffer might return just a few bytes, even when there isn't | 
					
						
							|  |  |  |      * an error, so loop collecting them until we get enough. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     while (pending < size) { | 
					
						
							|  |  |  |         int received = qemu_fill_buffer(f); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (received <= 0) { | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |         index = f->buf_index + offset; | 
					
						
							|  |  |  |         pending = f->buf_size - index; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (pending <= 0) { | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (size > pending) { | 
					
						
							|  |  |  |         size = pending; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-21 13:24:15 +01:00
										 |  |  |     *buf = f->buf + index; | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |     return size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-08 15:29:37 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Read 'size' bytes of data from the file into buf. | 
					
						
							|  |  |  |  * 'size' can be larger than the internal buffer. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * It will return size bytes unless there was an error, in which case it will | 
					
						
							|  |  |  |  * return as many as it managed to read (assuming blocking fd's which | 
					
						
							|  |  |  |  * all current QEMUFile are) | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-08-13 11:51:34 +01:00
										 |  |  | size_t qemu_get_buffer(QEMUFile *f, uint8_t *buf, size_t size) | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-08-13 11:51:34 +01:00
										 |  |  |     size_t pending = size; | 
					
						
							|  |  |  |     size_t done = 0; | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     while (pending > 0) { | 
					
						
							| 
									
										
										
										
											2015-08-13 11:51:34 +01:00
										 |  |  |         size_t res; | 
					
						
							| 
									
										
										
										
											2015-05-21 13:24:15 +01:00
										 |  |  |         uint8_t *src; | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-21 13:24:15 +01:00
										 |  |  |         res = qemu_peek_buffer(f, &src, MIN(pending, IO_BUF_SIZE), 0); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |         if (res == 0) { | 
					
						
							|  |  |  |             return done; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-05-21 13:24:15 +01:00
										 |  |  |         memcpy(buf, src, res); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |         qemu_file_skip(f, res); | 
					
						
							|  |  |  |         buf += res; | 
					
						
							|  |  |  |         pending -= res; | 
					
						
							|  |  |  |         done += res; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return done; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-05 18:10:35 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Read 'size' bytes of data from the file. | 
					
						
							|  |  |  |  * 'size' can be larger than the internal buffer. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The data: | 
					
						
							|  |  |  |  *   may be held on an internal buffer (in which case *buf is updated | 
					
						
							|  |  |  |  *     to point to it) that is valid until the next qemu_file operation. | 
					
						
							|  |  |  |  * OR | 
					
						
							|  |  |  |  *   will be copied to the *buf that was passed in. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The code tries to avoid the copy if possible. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * It will return size bytes unless there was an error, in which case it will | 
					
						
							|  |  |  |  * return as many as it managed to read (assuming blocking fd's which | 
					
						
							|  |  |  |  * all current QEMUFile are) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Note: Since **buf may get changed, the caller should take care to | 
					
						
							|  |  |  |  *       keep a pointer to the original buffer if it needs to deallocate it. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | size_t qemu_get_buffer_in_place(QEMUFile *f, uint8_t **buf, size_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (size < IO_BUF_SIZE) { | 
					
						
							|  |  |  |         size_t res; | 
					
						
							|  |  |  |         uint8_t *src; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         res = qemu_peek_buffer(f, &src, size, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (res == size) { | 
					
						
							|  |  |  |             qemu_file_skip(f, res); | 
					
						
							|  |  |  |             *buf = src; | 
					
						
							|  |  |  |             return res; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return qemu_get_buffer(f, *buf, size); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-08 15:29:37 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Peeks a single byte from the buffer; this isn't guaranteed to work if | 
					
						
							|  |  |  |  * offset leaves a gap after the previous read/peeked data. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | int qemu_peek_byte(QEMUFile *f, int offset) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int index = f->buf_index + offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(!qemu_file_is_writable(f)); | 
					
						
							| 
									
										
										
										
											2014-04-08 15:29:37 +01:00
										 |  |  |     assert(offset < IO_BUF_SIZE); | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (index >= f->buf_size) { | 
					
						
							|  |  |  |         qemu_fill_buffer(f); | 
					
						
							|  |  |  |         index = f->buf_index + offset; | 
					
						
							|  |  |  |         if (index >= f->buf_size) { | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return f->buf[index]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int qemu_get_byte(QEMUFile *f) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = qemu_peek_byte(f, 0); | 
					
						
							|  |  |  |     qemu_file_skip(f, 1); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 15:01:38 +01:00
										 |  |  | int64_t qemu_ftell_fast(QEMUFile *f) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int64_t ret = f->pos; | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-27 11:05:17 +01:00
										 |  |  |     for (i = 0; i < f->iovcnt; i++) { | 
					
						
							|  |  |  |         ret += f->iov[i].iov_len; | 
					
						
							| 
									
										
										
										
											2015-01-22 15:01:38 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | int64_t qemu_ftell(QEMUFile *f) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qemu_fflush(f); | 
					
						
							|  |  |  |     return f->pos; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int qemu_file_rate_limit(QEMUFile *f) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-12-18 05:11:31 +01:00
										 |  |  |     if (f->shutdown) { | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |     if (qemu_file_get_error(f)) { | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (f->xfer_limit > 0 && f->bytes_xfer > f->xfer_limit) { | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int64_t qemu_file_get_rate_limit(QEMUFile *f) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return f->xfer_limit; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void qemu_file_set_rate_limit(QEMUFile *f, int64_t limit) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     f->xfer_limit = limit; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void qemu_file_reset_rate_limit(QEMUFile *f) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     f->bytes_xfer = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-30 13:33:34 +08:00
										 |  |  | void qemu_file_update_transfer(QEMUFile *f, int64_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     f->bytes_xfer += len; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  | void qemu_put_be16(QEMUFile *f, unsigned int v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qemu_put_byte(f, v >> 8); | 
					
						
							|  |  |  |     qemu_put_byte(f, v); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void qemu_put_be32(QEMUFile *f, unsigned int v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qemu_put_byte(f, v >> 24); | 
					
						
							|  |  |  |     qemu_put_byte(f, v >> 16); | 
					
						
							|  |  |  |     qemu_put_byte(f, v >> 8); | 
					
						
							|  |  |  |     qemu_put_byte(f, v); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void qemu_put_be64(QEMUFile *f, uint64_t v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qemu_put_be32(f, v >> 32); | 
					
						
							|  |  |  |     qemu_put_be32(f, v); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | unsigned int qemu_get_be16(QEMUFile *f) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     unsigned int v; | 
					
						
							|  |  |  |     v = qemu_get_byte(f) << 8; | 
					
						
							|  |  |  |     v |= qemu_get_byte(f); | 
					
						
							|  |  |  |     return v; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | unsigned int qemu_get_be32(QEMUFile *f) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     unsigned int v; | 
					
						
							| 
									
										
										
										
											2014-12-23 22:26:55 +00:00
										 |  |  |     v = (unsigned int)qemu_get_byte(f) << 24; | 
					
						
							| 
									
										
										
										
											2013-11-28 12:01:16 -02:00
										 |  |  |     v |= qemu_get_byte(f) << 16; | 
					
						
							|  |  |  |     v |= qemu_get_byte(f) << 8; | 
					
						
							|  |  |  |     v |= qemu_get_byte(f); | 
					
						
							|  |  |  |     return v; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uint64_t qemu_get_be64(QEMUFile *f) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint64_t v; | 
					
						
							|  |  |  |     v = (uint64_t)qemu_get_be32(f) << 32; | 
					
						
							|  |  |  |     v |= qemu_get_be32(f); | 
					
						
							|  |  |  |     return v; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-03-23 16:32:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-30 15:51:20 +08:00
										 |  |  | /* return the size after compression, or negative value on error */ | 
					
						
							|  |  |  | static int qemu_compress_data(z_stream *stream, uint8_t *dest, size_t dest_len, | 
					
						
							|  |  |  |                               const uint8_t *source, size_t source_len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     err = deflateReset(stream); | 
					
						
							|  |  |  |     if (err != Z_OK) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stream->avail_in = source_len; | 
					
						
							|  |  |  |     stream->next_in = (uint8_t *)source; | 
					
						
							|  |  |  |     stream->avail_out = dest_len; | 
					
						
							|  |  |  |     stream->next_out = dest; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     err = deflate(stream, Z_FINISH); | 
					
						
							|  |  |  |     if (err != Z_STREAM_END) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return stream->next_out - dest; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Compress size bytes of data start at p and store the compressed
 | 
					
						
							|  |  |  |  * data to the buffer of f. | 
					
						
							| 
									
										
										
										
											2016-05-05 15:32:54 +08:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-10-12 10:39:31 +08:00
										 |  |  |  * Since the file is dummy file with empty_ops, return -1 if f has no space to | 
					
						
							|  |  |  |  * save the compressed data. | 
					
						
							| 
									
										
										
										
											2015-03-23 16:32:19 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-03-30 15:51:20 +08:00
										 |  |  | ssize_t qemu_put_compression_data(QEMUFile *f, z_stream *stream, | 
					
						
							|  |  |  |                                   const uint8_t *p, size_t size) | 
					
						
							| 
									
										
										
										
											2015-03-23 16:32:19 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     ssize_t blen = IO_BUF_SIZE - f->buf_index - sizeof(int32_t); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (blen < compressBound(size)) { | 
					
						
							| 
									
										
										
										
											2019-10-12 10:39:31 +08:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2015-03-23 16:32:19 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-30 15:51:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     blen = qemu_compress_data(stream, f->buf + f->buf_index + sizeof(int32_t), | 
					
						
							|  |  |  |                               blen, p, size); | 
					
						
							|  |  |  |     if (blen < 0) { | 
					
						
							| 
									
										
										
										
											2018-03-30 15:51:22 +08:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2015-03-23 16:32:19 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-30 15:51:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 16:32:19 +08:00
										 |  |  |     qemu_put_be32(f, blen); | 
					
						
							| 
									
										
										
										
											2019-09-11 13:28:39 +00:00
										 |  |  |     add_buf_to_iovec(f, blen); | 
					
						
							| 
									
										
										
										
											2015-03-23 16:32:19 +08:00
										 |  |  |     return blen + sizeof(int32_t); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Put the data in the buffer of f_src to the buffer of f_des, and
 | 
					
						
							|  |  |  |  * then reset the buf_index of f_src to 0. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int qemu_put_qemu_file(QEMUFile *f_des, QEMUFile *f_src) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int len = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (f_src->buf_index > 0) { | 
					
						
							|  |  |  |         len = f_src->buf_index; | 
					
						
							|  |  |  |         qemu_put_buffer(f_des, f_src->buf, f_src->buf_index); | 
					
						
							|  |  |  |         f_src->buf_index = 0; | 
					
						
							| 
									
										
										
										
											2016-08-09 08:22:26 +08:00
										 |  |  |         f_src->iovcnt = 0; | 
					
						
							| 
									
										
										
										
											2015-03-23 16:32:19 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     return len; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-05-21 13:24:11 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Get a string whose length is determined by a single preceding byte | 
					
						
							|  |  |  |  * A preallocated 256 byte buffer must be passed in. | 
					
						
							|  |  |  |  * Returns: len on success and a 0 terminated string in the buffer | 
					
						
							|  |  |  |  *          else 0 | 
					
						
							|  |  |  |  *          (Note a 0 length string will return 0 either way) | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | size_t qemu_get_counted_string(QEMUFile *f, char buf[256]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     size_t len = qemu_get_byte(f); | 
					
						
							|  |  |  |     size_t res = qemu_get_buffer(f, (uint8_t *)buf, len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     buf[res] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return res == len ? res : 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-11-05 18:10:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-13 15:34:00 -04:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Put a string with one preceding byte containing its length. The length of | 
					
						
							|  |  |  |  * the string should be less than 256. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void qemu_put_counted_string(QEMUFile *f, const char *str) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     size_t len = strlen(str); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(len < 256); | 
					
						
							|  |  |  |     qemu_put_byte(f, len); | 
					
						
							|  |  |  |     qemu_put_buffer(f, (const uint8_t *)str, len); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-05 18:10:36 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Set the blocking state of the QEMUFile. | 
					
						
							|  |  |  |  * Note: On some transports the OS only keeps a single blocking state for | 
					
						
							|  |  |  |  *       both directions, and thus changing the blocking on the main | 
					
						
							|  |  |  |  *       QEMUFile can also affect the return path. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void qemu_file_set_blocking(QEMUFile *f, bool block) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-04-27 11:04:56 +01:00
										 |  |  |     if (f->ops->set_blocking) { | 
					
						
							| 
									
										
										
										
											2019-04-22 13:34:20 +03:00
										 |  |  |         f->ops->set_blocking(f->opaque, block, NULL); | 
					
						
							| 
									
										
										
										
											2015-11-05 18:10:36 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } |