static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, void *opaque) { trace_vmstate_subsection_load(vmsd->name); while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) { char idstr[256], *idstr_ret; int ret; uint8_t version_id, len, size; const VMStateDescription *sub_vmsd; len = qemu_peek_byte(f, 1); if (len < strlen(vmsd->name) + 1) { /* subsection name has be be "section_name/a" */ trace_vmstate_subsection_load_bad(vmsd->name, "(short)", ""); return 0; } size = qemu_peek_buffer(f, (uint8_t **)&idstr_ret, len, 2); if (size != len) { trace_vmstate_subsection_load_bad(vmsd->name, "(peek fail)", ""); return 0; } memcpy(idstr, idstr_ret, size); idstr[size] = 0; if (strncmp(vmsd->name, idstr, strlen(vmsd->name)) != 0) { trace_vmstate_subsection_load_bad(vmsd->name, idstr, "(prefix)"); /* it doesn't have a valid subsection name */ return 0; } sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr); if (sub_vmsd == NULL) { trace_vmstate_subsection_load_bad(vmsd->name, idstr, "(lookup)"); return -ENOENT; } qemu_file_skip(f, 1); /* subsection */ qemu_file_skip(f, 1); /* len */ qemu_file_skip(f, len); /* idstr */ version_id = qemu_get_be32(f); ret = vmstate_load_state(f, sub_vmsd, opaque, version_id); if (ret) { trace_vmstate_subsection_load_bad(vmsd->name, idstr, "(child)"); return ret; } } trace_vmstate_subsection_load_good(vmsd->name); return 0; }
/* * 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); }
/* * 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) */ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size) { int pending = size; int done = 0; while (pending > 0) { int res; res = qemu_peek_buffer(f, buf, MIN(pending, IO_BUF_SIZE), 0); if (res == 0) { return done; } qemu_file_skip(f, res); buf += res; pending -= res; done += res; } return done; }
/* * 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) */ size_t qemu_get_buffer(QEMUFile *f, uint8_t *buf, size_t size) { size_t pending = size; size_t done = 0; while (pending > 0) { size_t res; uint8_t *src; res = qemu_peek_buffer(f, &src, MIN(pending, IO_BUF_SIZE), 0); if (res == 0) { return done; } memcpy(buf, src, res); qemu_file_skip(f, res); buf += res; pending -= res; done += res; } return done; }
static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, void *opaque) { while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) { char idstr[256]; int ret; uint8_t version_id, len, size; const VMStateDescription *sub_vmsd; len = qemu_peek_byte(f, 1); if (len < strlen(vmsd->name) + 1) { /* subsection name has be be "section_name/a" */ return 0; } size = qemu_peek_buffer(f, (uint8_t *)idstr, len, 2); if (size != len) { return 0; } idstr[size] = 0; if (strncmp(vmsd->name, idstr, strlen(vmsd->name)) != 0) { /* it don't have a valid subsection name */ return 0; } sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr); if (sub_vmsd == NULL) { return -ENOENT; } qemu_file_skip(f, 1); /* subsection */ qemu_file_skip(f, 1); /* len */ qemu_file_skip(f, len); /* idstr */ version_id = qemu_get_be32(f); ret = vmstate_load_state(f, sub_vmsd, opaque, version_id); if (ret) { return ret; } } return 0; }