static int parallels_open(BlockDriverState *bs, int flags) { BDRVParallelsState *s = bs->opaque; int i; struct parallels_header ph; bs->read_only = 1; // no write support yet if (bdrv_pread(bs->file, 0, &ph, sizeof(ph)) != sizeof(ph)) goto fail; if (memcmp(ph.magic, HEADER_MAGIC, 16) || (le32_to_cpu(ph.version) != HEADER_VERSION)) { goto fail; } bs->total_sectors = le32_to_cpu(ph.nb_sectors); s->tracks = le32_to_cpu(ph.tracks); s->catalog_size = le32_to_cpu(ph.catalog_entries); s->catalog_bitmap = g_malloc(s->catalog_size * 4); if (bdrv_pread(bs->file, 64, s->catalog_bitmap, s->catalog_size * 4) != s->catalog_size * 4) goto fail; for (i = 0; i < s->catalog_size; i++) le32_to_cpus(&s->catalog_bitmap[i]); return 0; fail: if (s->catalog_bitmap) g_free(s->catalog_bitmap); return -1; }
static int parallels_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVParallelsState *s = bs->opaque; int i; struct parallels_header ph; int ret; bs->read_only = 1; // no write support yet ret = bdrv_pread(bs->file, 0, &ph, sizeof(ph)); if (ret < 0) { goto fail; } if (memcmp(ph.magic, HEADER_MAGIC, 16) || (le32_to_cpu(ph.version) != HEADER_VERSION)) { error_setg(errp, "Image not in Parallels format"); ret = -EINVAL; goto fail; } bs->total_sectors = le32_to_cpu(ph.nb_sectors); s->tracks = le32_to_cpu(ph.tracks); if (s->tracks == 0) { error_setg(errp, "Invalid image: Zero sectors per track"); ret = -EINVAL; goto fail; } s->catalog_size = le32_to_cpu(ph.catalog_entries); if (s->catalog_size > INT_MAX / 4) { error_setg(errp, "Catalog too large"); ret = -EFBIG; goto fail; } s->catalog_bitmap = g_try_malloc(s->catalog_size * 4); if (s->catalog_size && s->catalog_bitmap == NULL) { ret = -ENOMEM; goto fail; } ret = bdrv_pread(bs->file, 64, s->catalog_bitmap, s->catalog_size * 4); if (ret < 0) { goto fail; } for (i = 0; i < s->catalog_size; i++) le32_to_cpus(&s->catalog_bitmap[i]); qemu_co_mutex_init(&s->lock); return 0; fail: g_free(s->catalog_bitmap); return ret; }
static inline int dmg_read_chunk(BlockDriverState *bs, int sector_num) { BDRVDMGState *s = bs->opaque; if(!is_sector_in_chunk(s,s->current_chunk,sector_num)) { int ret; uint32_t chunk = search_chunk(s,sector_num); if(chunk>=s->n_chunks) return -1; s->current_chunk = s->n_chunks; switch(s->types[chunk]) { case 0x80000005: { /* zlib compressed */ int i; /* we need to buffer, because only the chunk as whole can be * inflated. */ i=0; do { ret = bdrv_pread(bs->file, s->offsets[chunk] + i, s->compressed_chunk+i, s->lengths[chunk]-i); if(ret<0 && errno==EINTR) ret=0; i+=ret; } while(ret>=0 && ret+i<s->lengths[chunk]); if (ret != s->lengths[chunk]) return -1; s->zstream.next_in = s->compressed_chunk; s->zstream.avail_in = s->lengths[chunk]; s->zstream.next_out = s->uncompressed_chunk; s->zstream.avail_out = 512*s->sectorcounts[chunk]; ret = inflateReset(&s->zstream); if(ret != Z_OK) return -1; ret = inflate(&s->zstream, Z_FINISH); if(ret != Z_STREAM_END || s->zstream.total_out != 512*s->sectorcounts[chunk]) return -1; break; } case 1: /* copy */ ret = bdrv_pread(bs->file, s->offsets[chunk], s->uncompressed_chunk, s->lengths[chunk]); if (ret != s->lengths[chunk]) return -1; break; case 2: /* zero */ memset(s->uncompressed_chunk, 0, 512*s->sectorcounts[chunk]); break; } s->current_chunk = chunk; } return 0; }
int qcow2_read_snapshots(BlockDriverState *bs) { BDRVQcowState *s = bs->opaque; QCowSnapshotHeader h; QCowSnapshot *sn; int i, id_str_size, name_size; int64_t offset; uint32_t extra_data_size; if (!s->nb_snapshots) { s->snapshots = NULL; s->snapshots_size = 0; return 0; } offset = s->snapshots_offset; s->snapshots = qemu_mallocz(s->nb_snapshots * sizeof(QCowSnapshot)); for(i = 0; i < s->nb_snapshots; i++) { offset = align_offset(offset, 8); if (bdrv_pread(s->hd, offset, &h, sizeof(h)) != sizeof(h)) goto fail; offset += sizeof(h); sn = s->snapshots + i; sn->l1_table_offset = be64_to_cpu(h.l1_table_offset); sn->l1_size = be32_to_cpu(h.l1_size); sn->vm_state_size = be32_to_cpu(h.vm_state_size); sn->date_sec = be32_to_cpu(h.date_sec); sn->date_nsec = be32_to_cpu(h.date_nsec); sn->vm_clock_nsec = be64_to_cpu(h.vm_clock_nsec); extra_data_size = be32_to_cpu(h.extra_data_size); id_str_size = be16_to_cpu(h.id_str_size); name_size = be16_to_cpu(h.name_size); offset += extra_data_size; sn->id_str = qemu_malloc(id_str_size + 1); if (bdrv_pread(s->hd, offset, sn->id_str, id_str_size) != id_str_size) goto fail; offset += id_str_size; sn->id_str[id_str_size] = '\0'; sn->name = qemu_malloc(name_size + 1); if (bdrv_pread(s->hd, offset, sn->name, name_size) != name_size) goto fail; offset += name_size; sn->name[name_size] = '\0'; } s->snapshots_size = offset - s->snapshots_offset; return 0; fail: qcow2_free_snapshots(bs); return -1; }
static void test_sync_op_pread(BdrvChild *c) { uint8_t buf[512]; int ret; /* Success */ ret = bdrv_pread(c, 0, buf, sizeof(buf)); g_assert_cmpint(ret, ==, 512); /* Early error: Negative offset */ ret = bdrv_pread(c, -2, buf, sizeof(buf)); g_assert_cmpint(ret, ==, -EIO); }
static int cloop_open(BlockDriverState *bs, int flags) { BDRVCloopState *s = bs->opaque; uint32_t offsets_size, max_compressed_block_size = 1, i; bs->read_only = 1; /* read header */ if (bdrv_pread(bs->file, 128, &s->block_size, 4) < 4) { goto cloop_close; } s->block_size = be32_to_cpu(s->block_size); if (bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4) < 4) { goto cloop_close; } s->n_blocks = be32_to_cpu(s->n_blocks); /* read offsets */ offsets_size = s->n_blocks * sizeof(uint64_t); s->offsets = g_malloc(offsets_size); if (bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size) < offsets_size) { goto cloop_close; } for(i=0;i<s->n_blocks;i++) { s->offsets[i] = be64_to_cpu(s->offsets[i]); if (i > 0) { uint32_t size = s->offsets[i] - s->offsets[i - 1]; if (size > max_compressed_block_size) { max_compressed_block_size = size; } } } /* initialize zlib engine */ s->compressed_block = g_malloc(max_compressed_block_size + 1); s->uncompressed_block = g_malloc(s->block_size); if (inflateInit(&s->zstream) != Z_OK) { goto cloop_close; } s->current_block = s->n_blocks; s->sectors_per_block = s->block_size/512; bs->total_sectors = s->n_blocks * s->sectors_per_block; qemu_co_mutex_init(&s->lock); return 0; cloop_close: return -1; }
static int vmdk_open_desc_file(BlockDriverState *bs, int flags, int64_t desc_offset) { int ret; char buf[2048]; char ct[128]; BDRVVmdkState *s = bs->opaque; ret = bdrv_pread(bs->file, desc_offset, buf, sizeof(buf)); if (ret < 0) { return ret; } buf[2047] = '\0'; if (vmdk_parse_description(buf, "createType", ct, sizeof(ct))) { return -EINVAL; } if (strcmp(ct, "monolithicFlat") && strcmp(ct, "twoGbMaxExtentSparse") && strcmp(ct, "twoGbMaxExtentFlat")) { fprintf(stderr, "VMDK: Not supported image type \"%s\""".\n", ct); return -ENOTSUP; } s->desc_offset = 0; return vmdk_parse_extents(buf, bs, bs->file->filename); }
static int vmdk_open_vmdk3(BlockDriverState *bs, BlockDriverState *file, int flags) { int ret; uint32_t magic; VMDK3Header header; VmdkExtent *extent; ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header)); if (ret < 0) { return ret; } extent = vmdk_add_extent(bs, bs->file, false, le32_to_cpu(header.disk_sectors), le32_to_cpu(header.l1dir_offset) << 9, 0, 1 << 6, 1 << 9, le32_to_cpu(header.granularity)); ret = vmdk_init_tables(bs, extent); if (ret) { /* free extent allocated by vmdk_add_extent */ vmdk_free_last_extent(bs); } return ret; }
static int vmdk_parent_open(BlockDriverState *bs) { char *p_name; char desc[DESC_SIZE + 1]; BDRVVmdkState *s = bs->opaque; int ret; desc[DESC_SIZE] = '\0'; ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE); if (ret < 0) { return ret; } p_name = strstr(desc, "parentFileNameHint"); if (p_name != NULL) { char *end_name; p_name += sizeof("parentFileNameHint") + 1; end_name = strchr(p_name, '\"'); if (end_name == NULL) { return -EINVAL; } if ((end_name - p_name) > sizeof(bs->backing_file) - 1) { return -EINVAL; } pstrcpy(bs->backing_file, end_name - p_name + 1, p_name); } return 0; }
static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid) { char desc[DESC_SIZE], tmp_desc[DESC_SIZE]; char *p_name, *tmp_str; BDRVVmdkState *s = bs->opaque; int ret; ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE); if (ret < 0) { return ret; } desc[DESC_SIZE - 1] = '\0'; tmp_str = strstr(desc, "parentCID"); if (tmp_str == NULL) { return -EINVAL; } pstrcpy(tmp_desc, sizeof(tmp_desc), tmp_str); p_name = strstr(desc, "CID"); if (p_name != NULL) { p_name += sizeof("CID"); snprintf(p_name, sizeof(desc) - (p_name - desc), "%x\n", cid); pstrcat(desc, sizeof(desc), tmp_desc); } ret = bdrv_pwrite_sync(bs->file, s->desc_offset, desc, DESC_SIZE); if (ret < 0) { return ret; } return 0; }
static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent) { char desc[DESC_SIZE]; uint32_t cid = 0xffffffff; const char *p_name, *cid_str; size_t cid_str_size; BDRVVmdkState *s = bs->opaque; int ret; ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE); if (ret < 0) { return 0; } if (parent) { cid_str = "parentCID"; cid_str_size = sizeof("parentCID"); } else { cid_str = "CID"; cid_str_size = sizeof("CID"); } desc[DESC_SIZE - 1] = '\0'; p_name = strstr(desc, cid_str); if (p_name != NULL) { p_name += cid_str_size; sscanf(p_name, "%x", &cid); } return cid; }
static off_t read_off(BlockDriverState *bs, int64_t offset) { uint64_t buffer; if (bdrv_pread(bs->file, offset, &buffer, 8) < 8) return 0; return be64_to_cpu(buffer); }
static inline int cloop_read_block(BlockDriverState *bs, int block_num) { BDRVCloopState *s = bs->opaque; if (s->current_block != block_num) { int ret; uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num]; ret = bdrv_pread(bs->file->bs, s->offsets[block_num], s->compressed_block, bytes); if (ret != bytes) { return -1; } s->zstream.next_in = s->compressed_block; s->zstream.avail_in = bytes; s->zstream.next_out = s->uncompressed_block; s->zstream.avail_out = s->block_size; ret = inflateReset(&s->zstream); if (ret != Z_OK) { return -1; } ret = inflate(&s->zstream, Z_FINISH); if (ret != Z_STREAM_END || s->zstream.total_out != s->block_size) { return -1; } s->current_block = block_num; } return 0; }
static int do_pread(char *buf, int64_t offset, int count, int *total) { *total = bdrv_pread(bs, offset, (uint8_t *)buf, count); if (*total < 0) return *total; return 1; }
/* Reads num_sectors from the log (all log sectors are 4096 bytes), * into buffer 'buffer'. Upon return, *sectors_read will contain * the number of sectors successfully read. * * It is assumed that 'buffer' is already allocated, and of sufficient * size (i.e. >= 4096*num_sectors). * * If 'peek' is true, then the tail (read) pointer for the circular buffer is * not modified. * * 0 is returned on success, -errno otherwise. */ static int vhdx_log_read_sectors(BlockDriverState *bs, VHDXLogEntries *log, uint32_t *sectors_read, void *buffer, uint32_t num_sectors, bool peek) { int ret = 0; uint64_t offset; uint32_t read; read = log->read; *sectors_read = 0; while (num_sectors) { if (read == log->write) { /* empty */ break; } offset = log->offset + read; ret = bdrv_pread(bs->file, offset, buffer, VHDX_LOG_SECTOR_SIZE); if (ret < 0) { goto exit; } read = vhdx_log_inc_idx(read, log->length); *sectors_read = *sectors_read + 1; num_sectors--; } exit: if (!peek) { log->read = read; } return ret; }
static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset, void **table, bool read_from_disk) { BDRVQcowState *s = bs->opaque; int i; int ret; trace_qcow2_cache_get(qemu_coroutine_self(), c == s->l2_table_cache, offset, read_from_disk); /* Check if the table is already cached */ for (i = 0; i < c->size; i++) { if (c->entries[i].offset == offset) { goto found; } } /* If not, write a table back and replace it */ i = qcow2_cache_find_entry_to_replace(c); trace_qcow2_cache_get_replace_entry(qemu_coroutine_self(), c == s->l2_table_cache, i); if (i < 0) { return i; } ret = qcow2_cache_entry_flush(bs, c, i); if (ret < 0) { return ret; } trace_qcow2_cache_get_read(qemu_coroutine_self(), c == s->l2_table_cache, i); c->entries[i].offset = 0; if (read_from_disk) { if (c == s->l2_table_cache) { BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD); } ret = bdrv_pread(bs->file, offset, c->entries[i].table, s->cluster_size); if (ret < 0) { return ret; } } /* Give the table some hits for the start so that it won't be replaced * immediately. The number 32 is completely arbitrary. */ c->entries[i].cache_hits = 32; c->entries[i].offset = offset; /* And return the right table */ found: c->entries[i].cache_hits++; c->entries[i].ref++; *table = c->entries[i].table; trace_qcow2_cache_get_done(qemu_coroutine_self(), c == s->l2_table_cache, i); return 0; }
static off_t read_uint32(BlockDriverState *bs, int64_t offset) { uint32_t buffer; if (bdrv_pread(bs->file, offset, &buffer, 4) < 4) return 0; return be32_to_cpu(buffer); }
int qcow2_snapshot_load_tmp(BlockDriverState *bs, const char *snapshot_name) { int i, snapshot_index, l1_size2; BDRVQcowState *s = bs->opaque; QCowSnapshot *sn; snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_name); if (snapshot_index < 0) { return -ENOENT; } sn = &s->snapshots[snapshot_index]; s->l1_size = sn->l1_size; l1_size2 = s->l1_size * sizeof(uint64_t); if (s->l1_table != NULL) { g_free(s->l1_table); } s->l1_table_offset = sn->l1_table_offset; s->l1_table = g_malloc0(align_offset(l1_size2, 512)); if (bdrv_pread(bs->file, sn->l1_table_offset, s->l1_table, l1_size2) != l1_size2) { return -1; } for(i = 0; i < s->l1_size; i++) { be64_to_cpus(&s->l1_table[i]); } return 0; }
/* This is where we get a request from a caller to read something */ static BlockDriverAIOCB *tar_aio_readv(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { BDRVTarState *s = bs->opaque; SparseCache *sparse; int64_t sec_file = sector_num + s->file_sec; int64_t start = sector_num * SECTOR_SIZE; int64_t end = start + (nb_sectors * SECTOR_SIZE); int i; TarAIOCB *acb; for (i = 0; i < s->sparse_num; i++) { sparse = &s->sparse[i]; if (sparse->start > end) { /* We expect the cache to be start increasing */ break; } else if ((sparse->start < start) && (sparse->end <= start)) { /* sparse before our offset */ sec_file -= (sparse->end - sparse->start) / SECTOR_SIZE; } else if ((sparse->start <= start) && (sparse->end >= end)) { /* all our sectors are sparse */ char *buf = g_malloc0(nb_sectors * SECTOR_SIZE); acb = qemu_aio_get(&tar_aiocb_info, bs, cb, opaque); qemu_iovec_from_buf(qiov, 0, buf, nb_sectors * SECTOR_SIZE); g_free(buf); acb->bh = qemu_bh_new(tar_sparse_cb, acb); qemu_bh_schedule(acb->bh); return &acb->common; } else if (((sparse->start >= start) && (sparse->start < end)) || ((sparse->end >= start) && (sparse->end < end))) { /* we're semi-sparse (worst case) */ /* let's go synchronous and read all sectors individually */ char *buf = g_malloc(nb_sectors * SECTOR_SIZE); uint64_t offs; for (offs = 0; offs < (nb_sectors * SECTOR_SIZE); offs += SECTOR_SIZE) { bdrv_pread(bs, (sector_num * SECTOR_SIZE) + offs, buf + offs, SECTOR_SIZE); } qemu_iovec_from_buf(qiov, 0, buf, nb_sectors * SECTOR_SIZE); acb = qemu_aio_get(&tar_aiocb_info, bs, cb, opaque); acb->bh = qemu_bh_new(tar_sparse_cb, acb); qemu_bh_schedule(acb->bh); return &acb->common; } } return bdrv_aio_readv(s->hd, sec_file, qiov, nb_sectors, cb, opaque); }
int qcow2_snapshot_load_tmp(BlockDriverState *bs, const char *snapshot_id, const char *name, Error **errp) { int i, snapshot_index; BDRVQcow2State *s = bs->opaque; QCowSnapshot *sn; uint64_t *new_l1_table; int new_l1_bytes; int ret; assert(bs->read_only); /* Search the snapshot */ snapshot_index = find_snapshot_by_id_and_name(bs, snapshot_id, name); if (snapshot_index < 0) { error_setg(errp, "Can't find snapshot"); return -ENOENT; } sn = &s->snapshots[snapshot_index]; /* Allocate and read in the snapshot's L1 table */ if (sn->l1_size > QCOW_MAX_L1_SIZE / sizeof(uint64_t)) { error_setg(errp, "Snapshot L1 table too large"); return -EFBIG; } new_l1_bytes = sn->l1_size * sizeof(uint64_t); new_l1_table = qemu_try_blockalign(bs->file->bs, align_offset(new_l1_bytes, 512)); if (new_l1_table == NULL) { return -ENOMEM; } ret = bdrv_pread(bs->file->bs, sn->l1_table_offset, new_l1_table, new_l1_bytes); if (ret < 0) { error_setg(errp, "Failed to read l1 table for snapshot"); qemu_vfree(new_l1_table); return ret; } /* Switch the L1 table */ qemu_vfree(s->l1_table); s->l1_size = sn->l1_size; s->l1_table_offset = sn->l1_table_offset; s->l1_table = new_l1_table; for(i = 0;i < s->l1_size; i++) { be64_to_cpus(&s->l1_table[i]); } return 0; }
static int parallels_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVParallelsState *s = bs->opaque; int i; struct parallels_header ph; int ret; bs->read_only = 1; // no write support yet ret = bdrv_pread(bs->file, 0, &ph, sizeof(ph)); if (ret < 0) { goto fail; } if (memcmp(ph.magic, HEADER_MAGIC, 16) || (le32_to_cpu(ph.version) != HEADER_VERSION)) { ret = -EMEDIUMTYPE; goto fail; } bs->total_sectors = le32_to_cpu(ph.nb_sectors); s->tracks = le32_to_cpu(ph.tracks); s->catalog_size = le32_to_cpu(ph.catalog_entries); s->catalog_bitmap = g_malloc(s->catalog_size * 4); ret = bdrv_pread(bs->file, 64, s->catalog_bitmap, s->catalog_size * 4); if (ret < 0) { goto fail; } for (i = 0; i < s->catalog_size; i++) le32_to_cpus(&s->catalog_bitmap[i]); qemu_co_mutex_init(&s->lock); return 0; fail: g_free(s->catalog_bitmap); return ret; }
static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent) { int ret; int l1_size, i; /* read the L1 table */ l1_size = extent->l1_size * sizeof(uint32_t); extent->l1_table = g_malloc(l1_size); ret = bdrv_pread(extent->file, extent->l1_table_offset, extent->l1_table, l1_size); if (ret < 0) { goto fail_l1; } for (i = 0; i < extent->l1_size; i++) { le32_to_cpus(&extent->l1_table[i]); } if (extent->l1_backup_table_offset) { extent->l1_backup_table = g_malloc(l1_size); ret = bdrv_pread(extent->file, extent->l1_backup_table_offset, extent->l1_backup_table, l1_size); if (ret < 0) { goto fail_l1b; } for (i = 0; i < extent->l1_size; i++) { le32_to_cpus(&extent->l1_backup_table[i]); } } extent->l2_cache = g_malloc(extent->l2_size * L2_CACHE_SIZE * sizeof(uint32_t)); return 0; fail_l1b: g_free(extent->l1_backup_table); fail_l1: g_free(extent->l1_table); return ret; }
/* load_bitmap_data * @bitmap_table entries must satisfy specification constraints. * @bitmap must be cleared */ static int load_bitmap_data(BlockDriverState *bs, const uint64_t *bitmap_table, uint32_t bitmap_table_size, BdrvDirtyBitmap *bitmap) { int ret = 0; BDRVQcow2State *s = bs->opaque; uint64_t offset, limit; uint64_t bm_size = bdrv_dirty_bitmap_size(bitmap); uint8_t *buf = NULL; uint64_t i, tab_size = size_to_clusters(s, bdrv_dirty_bitmap_serialization_size(bitmap, 0, bm_size)); if (tab_size != bitmap_table_size || tab_size > BME_MAX_TABLE_SIZE) { return -EINVAL; } buf = g_malloc(s->cluster_size); limit = bytes_covered_by_bitmap_cluster(s, bitmap); for (i = 0, offset = 0; i < tab_size; ++i, offset += limit) { uint64_t count = MIN(bm_size - offset, limit); uint64_t entry = bitmap_table[i]; uint64_t data_offset = entry & BME_TABLE_ENTRY_OFFSET_MASK; assert(check_table_entry(entry, s->cluster_size) == 0); if (data_offset == 0) { if (entry & BME_TABLE_ENTRY_FLAG_ALL_ONES) { bdrv_dirty_bitmap_deserialize_ones(bitmap, offset, count, false); } else { /* No need to deserialize zeros because the dirty bitmap is * already cleared */ } } else { ret = bdrv_pread(bs->file, data_offset, buf, s->cluster_size); if (ret < 0) { goto finish; } bdrv_dirty_bitmap_deserialize_part(bitmap, buf, offset, count, false); } } ret = 0; bdrv_dirty_bitmap_deserialize_finish(bitmap); finish: g_free(buf); return ret; }
static int dmg_read_plist_xml(BlockDriverState *bs, DmgHeaderState *ds, uint64_t info_begin, uint64_t info_length) { BDRVDMGState *s = bs->opaque; int ret; uint8_t *buffer = NULL; char *data_begin, *data_end; /* Have at least some length to avoid NULL for g_malloc. Attempt to set a * safe upper cap on the data length. A test sample had a XML length of * about 1 MiB. */ if (info_length == 0 || info_length > 16 * 1024 * 1024) { ret = -EINVAL; goto fail; } buffer = g_malloc(info_length + 1); buffer[info_length] = '\0'; ret = bdrv_pread(bs->file, info_begin, buffer, info_length); if (ret != info_length) { ret = -EINVAL; goto fail; } /* look for <data>...</data>. The data is 284 (0x11c) bytes after base64 * decode. The actual data element has 431 (0x1af) bytes which includes tabs * and line feeds. */ data_end = (char *)buffer; while ((data_begin = strstr(data_end, "<data>")) != NULL) { guchar *mish; gsize out_len = 0; data_begin += 6; data_end = strstr(data_begin, "</data>"); /* malformed XML? */ if (data_end == NULL) { ret = -EINVAL; goto fail; } *data_end++ = '\0'; mish = g_base64_decode(data_begin, &out_len); ret = dmg_read_mish_block(s, ds, mish, (uint32_t)out_len); g_free(mish); if (ret < 0) { goto fail; } } ret = 0; fail: g_free(buffer); return ret; }
static int read_uint32(BlockDriverState *bs, int64_t offset, uint32_t *result) { uint32_t buffer; int ret; ret = bdrv_pread(bs->file, offset, &buffer, 4); if (ret < 0) { return ret; } *result = be32_to_cpu(buffer); return 0; }
/** * Read a string of known length from the image file * * @file: Image file * @offset: File offset to start of string, in bytes * @n: String length in bytes * @buf: Destination buffer * @buflen: Destination buffer length in bytes * @ret: 0 on success, -errno on failure * * The string is NUL-terminated. */ static int qed_read_string(BlockDriverState *file, uint64_t offset, size_t n, char *buf, size_t buflen) { int ret; if (n >= buflen) { return -EINVAL; } ret = bdrv_pread(file, offset, buf, n); if (ret < 0) { return ret; } buf[n] = '\0'; return 0; }
static void rtas_nvram_fetch(PowerPCCPU *cpu, sPAPREnvironment *spapr, uint32_t token, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { sPAPRNVRAM *nvram = spapr->nvram; hwaddr offset, buffer, len; int alen; void *membuf; if ((nargs != 3) || (nret != 2)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; } if (!nvram) { rtas_st(rets, 0, RTAS_OUT_HW_ERROR); rtas_st(rets, 1, 0); return; } offset = rtas_ld(args, 0); buffer = rtas_ld(args, 1); len = rtas_ld(args, 2); if (((offset + len) < offset) || ((offset + len) > nvram->size)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); rtas_st(rets, 1, 0); return; } membuf = cpu_physical_memory_map(buffer, &len, 1); if (nvram->drive) { alen = bdrv_pread(nvram->drive, offset, membuf, len); } else { assert(nvram->buf); memcpy(membuf, nvram->buf + offset, len); alen = len; } cpu_physical_memory_unmap(membuf, len, 1, len); rtas_st(rets, 0, (alen < len) ? RTAS_OUT_HW_ERROR : RTAS_OUT_SUCCESS); rtas_st(rets, 1, (alen < 0) ? 0 : alen); }
/* copy the snapshot 'snapshot_name' into the current disk image */ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) { BDRVQcowState *s = bs->opaque; QCowSnapshot *sn; int i, snapshot_index; int cur_l1_bytes, sn_l1_bytes; snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id); if (snapshot_index < 0) return -ENOENT; sn = &s->snapshots[snapshot_index]; if (qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, -1) < 0) goto fail; if (qcow2_grow_l1_table(bs, sn->l1_size, true) < 0) goto fail; cur_l1_bytes = s->l1_size * sizeof(uint64_t); sn_l1_bytes = sn->l1_size * sizeof(uint64_t); if (cur_l1_bytes > sn_l1_bytes) { memset(s->l1_table + sn->l1_size, 0, cur_l1_bytes - sn_l1_bytes); } /* copy the snapshot l1 table to the current l1 table */ if (bdrv_pread(bs->file, sn->l1_table_offset, s->l1_table, sn_l1_bytes) < 0) goto fail; if (bdrv_pwrite_sync(bs->file, s->l1_table_offset, s->l1_table, cur_l1_bytes) < 0) goto fail; for(i = 0; i < s->l1_size; i++) { be64_to_cpus(&s->l1_table[i]); } if (qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1) < 0) goto fail; #ifdef DEBUG_ALLOC qcow2_check_refcounts(bs); #endif return 0; fail: return -EIO; }
static int parallels_read(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, int nb_sectors) { while (nb_sectors > 0) { int64_t position = seek_to_sector(bs, sector_num); if (position >= 0) { if (bdrv_pread(bs->file, position, buf, 512) != 512) return -1; } else { memset(buf, 0, 512); } nb_sectors--; sector_num++; buf += 512; } return 0; }
static ssize_t block_crypto_read_func(QCryptoBlock *block, size_t offset, uint8_t *buf, size_t buflen, Error **errp, void *opaque) { BlockDriverState *bs = opaque; ssize_t ret; ret = bdrv_pread(bs->file, offset, buf, buflen); if (ret < 0) { error_setg_errno(errp, -ret, "Could not read encryption header"); return ret; } return ret; }