/* Reads a snapshot record from a qcow2-formatted file. * * The function assumes the file position of 'fd' points to the beginning of a * QcowSnapshotHeader record. When the call returns, the file position of fd is * at the place where the next QcowSnapshotHeader should start, if there is one. * * C.f. QCowSnapshotHeader in block/qcow2-snapshot.c for the complete layout of * the header. */ static void snapshot_info_read( int fd, SnapshotInfo* info ) { uint64_t start_offset = seek_or_die(fd, 0, SEEK_CUR); uint32_t extra_data_size; uint16_t id_str_size, name_size; /* read fixed-length fields */ seek_or_die(fd, 12, SEEK_CUR); /* skip l1 info */ read_or_die(fd, &id_str_size, sizeof(id_str_size)); read_or_die(fd, &name_size, sizeof(name_size)); read_or_die(fd, &info->date_sec, sizeof(info->date_sec)); read_or_die(fd, &info->date_nsec, sizeof(info->date_nsec)); read_or_die(fd, &info->vm_clock_nsec, sizeof(info->vm_clock_nsec)); read_or_die(fd, &info->vm_state_size, sizeof(info->vm_state_size)); read_or_die(fd, &extra_data_size, sizeof(extra_data_size)); /* convert to host endianness */ be16_to_cpus(&id_str_size); be16_to_cpus(&name_size); be32_to_cpus(&info->date_sec); be32_to_cpus(&info->date_nsec); be64_to_cpus(&info->vm_clock_nsec); be32_to_cpus(&info->vm_state_size); be32_to_cpus(&extra_data_size); be32_to_cpus(&extra_data_size); /* read variable-length buffers*/ info->id_str = android_alloc(id_str_size + 1); // +1: manual null-termination info->name = android_alloc(name_size + 1); seek_or_die(fd, extra_data_size, SEEK_CUR); /* skip extra data */ read_or_die(fd, info->id_str, id_str_size); read_or_die(fd, info->name, name_size); info->id_str[id_str_size] = '\0'; info->name[name_size] = '\0'; /* headers are 8 byte aligned, ceil to nearest multiple of 8 */ uint64_t end_offset = seek_or_die(fd, 0, SEEK_CUR); uint32_t total_size = end_offset - start_offset; uint32_t aligned_size = ((total_size - 1) / 8 + 1) * 8; /* skip to start of next record */ seek_or_die(fd, start_offset + aligned_size, SEEK_SET); }
static char* substring_dup( const char* start, const char* end ) { int len = end - start; char* result = android_alloc(len+1); memcpy(result, start, len); result[len] = 0; return result; }
/* Loads a single boot property from a snapshot file */ static int boot_property_load_property( QEMUFile *f ) { int ret; /* load key */ uint32_t key_buf_len = qemu_get_be32(f); char* key = android_alloc(key_buf_len); if ((ret = qemu_get_buffer(f, (uint8_t*)key, key_buf_len) != (int)key_buf_len)) { D("%s: key load failed: expected %d bytes, got %d\n", __FUNCTION__, key_buf_len, ret); goto fail_key; } /* load value */ uint32_t value_buf_len = qemu_get_be32(f); char* value = android_alloc(value_buf_len); if ((ret = qemu_get_buffer(f, (uint8_t*)value, value_buf_len) != (int)value_buf_len)) { D("%s: value load failed: expected %d bytes, got %d\n", __FUNCTION__, value_buf_len, ret); goto fail_value; } /* add the property */ ret = boot_property_add2(key, key_buf_len - 1, value, value_buf_len - 1); if (ret < 0) { D("%s: load failed: cannot add boot property (details follow)\n", __FUNCTION__); boot_property_raise_warning(ret, key, key_buf_len - 1, value, value_buf_len - 1); goto fail_value; } return 0; /* in case of errors, clean up before return */ fail_value: AFREE(value); fail_key: AFREE(key); return -EIO; }
void* _android_array_alloc( size_t itemSize, size_t count ) { #if ACONFIG_USE_ASSERT size_t maxSize; if (itemSize == 0) AASSERT_FAIL("item size is 0\n"); maxSize = (~(size_t)0) / itemSize; if (count > maxSize) AASSERT_FAIL("allocation too large (%d > %d)\n", count, maxSize); #endif return android_alloc(itemSize * count); }
static BootProperty* boot_property_alloc( const char* name, int namelen, const char* value, int valuelen ) { int length = namelen + 1 + valuelen; BootProperty* prop = android_alloc( sizeof(*prop) + length + 1 ); char* p; prop->next = NULL; prop->property = p = (char*)(prop + 1); prop->length = length; memcpy( p, name, namelen ); p += namelen; *p++ = '='; memcpy( p, value, valuelen ); p += valuelen; *p = '\0'; return prop; }
static SnapshotInfo* snapshot_info_alloc() { return android_alloc(sizeof(SnapshotInfo)); }