⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 block-qcow.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 2 页
字号:
                if (s->crypt_method &&                     (n_end - n_start) < s->cluster_sectors) {                    uint64_t start_sect;                    start_sect = (offset & ~(s->cluster_size - 1)) >> 9;                    memset(s->cluster_data + 512, 0xaa, 512);                    for(i = 0; i < s->cluster_sectors; i++) {                        if (i < n_start || i >= n_end) {                            encrypt_sectors(s, start_sect + i,                                             s->cluster_data,                                             s->cluster_data + 512, 1, 1,                                            &s->aes_encrypt_key);                            lseek(s->fd, cluster_offset + i * 512, SEEK_SET);                            if (write(s->fd, s->cluster_data, 512) != 512)                                return -1;                        }                    }                }            } else {                cluster_offset |= QCOW_OFLAG_COMPRESSED |                     (uint64_t)compressed_size << (63 - s->cluster_bits);            }        }        /* update L2 table */        tmp = cpu_to_be64(cluster_offset);        l2_table[l2_index] = tmp;        lseek(s->fd, l2_offset + l2_index * sizeof(tmp), SEEK_SET);        if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))            return 0;    }    return cluster_offset;}static int qcow_is_allocated(BlockDriverState *bs, int64_t sector_num,                              int nb_sectors, int *pnum){    BDRVQcowState *s = bs->opaque;    int index_in_cluster, n;    uint64_t cluster_offset;    cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);    index_in_cluster = sector_num & (s->cluster_sectors - 1);    n = s->cluster_sectors - index_in_cluster;    if (n > nb_sectors)        n = nb_sectors;    *pnum = n;    return (cluster_offset != 0);}static int decompress_buffer(uint8_t *out_buf, int out_buf_size,                             const uint8_t *buf, int buf_size){    z_stream strm1, *strm = &strm1;    int ret, out_len;    memset(strm, 0, sizeof(*strm));    strm->next_in = (uint8_t *)buf;    strm->avail_in = buf_size;    strm->next_out = out_buf;    strm->avail_out = out_buf_size;    ret = inflateInit2(strm, -12);    if (ret != Z_OK)        return -1;    ret = inflate(strm, Z_FINISH);    out_len = strm->next_out - out_buf;    if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) ||        out_len != out_buf_size) {        inflateEnd(strm);        return -1;    }    inflateEnd(strm);    return 0;}                              static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset){    int ret, csize;    uint64_t coffset;    coffset = cluster_offset & s->cluster_offset_mask;    if (s->cluster_cache_offset != coffset) {        csize = cluster_offset >> (63 - s->cluster_bits);        csize &= (s->cluster_size - 1);        lseek(s->fd, coffset, SEEK_SET);        ret = read(s->fd, s->cluster_data, csize);        if (ret != csize)             return -1;        if (decompress_buffer(s->cluster_cache, s->cluster_size,                              s->cluster_data, csize) < 0) {            return -1;        }        s->cluster_cache_offset = coffset;    }    return 0;}static int qcow_read(BlockDriverState *bs, int64_t sector_num,                      uint8_t *buf, int nb_sectors){    BDRVQcowState *s = bs->opaque;    int ret, index_in_cluster, n;    uint64_t cluster_offset;        while (nb_sectors > 0) {        cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);        index_in_cluster = sector_num & (s->cluster_sectors - 1);        n = s->cluster_sectors - index_in_cluster;        if (n > nb_sectors)            n = nb_sectors;        if (!cluster_offset) {            memset(buf, 0, 512 * n);        } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {            if (decompress_cluster(s, cluster_offset) < 0)                return -1;            memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);        } else {            lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);            ret = read(s->fd, buf, n * 512);            if (ret != n * 512)                 return -1;            if (s->crypt_method) {                encrypt_sectors(s, sector_num, buf, buf, n, 0,                                 &s->aes_decrypt_key);            }        }        nb_sectors -= n;        sector_num += n;        buf += n * 512;    }    return 0;}static int qcow_write(BlockDriverState *bs, int64_t sector_num,                      const uint8_t *buf, int nb_sectors){    BDRVQcowState *s = bs->opaque;    int ret, index_in_cluster, n;    uint64_t cluster_offset;        while (nb_sectors > 0) {        index_in_cluster = sector_num & (s->cluster_sectors - 1);        n = s->cluster_sectors - index_in_cluster;        if (n > nb_sectors)            n = nb_sectors;        cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0,                                             index_in_cluster,                                             index_in_cluster + n);        if (!cluster_offset)            return -1;        lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);        if (s->crypt_method) {            encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1,                            &s->aes_encrypt_key);            ret = write(s->fd, s->cluster_data, n * 512);        } else {            ret = write(s->fd, buf, n * 512);        }        if (ret != n * 512)             return -1;        nb_sectors -= n;        sector_num += n;        buf += n * 512;    }    s->cluster_cache_offset = -1; /* disable compressed cache */    return 0;}static void qcow_close(BlockDriverState *bs){    BDRVQcowState *s = bs->opaque;    qemu_free(s->l1_table);    qemu_free(s->l2_cache);    qemu_free(s->cluster_cache);    qemu_free(s->cluster_data);    close(s->fd);}static int qcow_create(const char *filename, int64_t total_size,                      const char *backing_file, int flags){    int fd, header_size, backing_filename_len, l1_size, i, shift;    QCowHeader header;    char backing_filename[1024];    uint64_t tmp;    struct stat st;    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,               0644);    if (fd < 0)        return -1;    memset(&header, 0, sizeof(header));    header.magic = cpu_to_be32(QCOW_MAGIC);    header.version = cpu_to_be32(QCOW_VERSION);    header.size = cpu_to_be64(total_size * 512);    header_size = sizeof(header);    backing_filename_len = 0;    if (backing_file) {	if (strcmp(backing_file, "fat:")) {	    const char *p;	    /* XXX: this is a hack: we do not attempt to check for URL	       like syntax */	    p = strchr(backing_file, ':');	    if (p && (p - backing_file) >= 2) {		/* URL like but exclude "c:" like filenames */		pstrcpy(backing_filename, sizeof(backing_filename),			backing_file);	    } else {		realpath(backing_file, backing_filename);		if (stat(backing_filename, &st) != 0) {		    return -1;		}	    }	    header.backing_file_offset = cpu_to_be64(header_size);	    backing_filename_len = strlen(backing_filename);	    header.backing_file_size = cpu_to_be32(backing_filename_len);	    header_size += backing_filename_len;	} else	    backing_file = NULL;        header.mtime = cpu_to_be32(st.st_mtime);        header.cluster_bits = 9; /* 512 byte cluster to avoid copying                                    unmodifyed sectors */        header.l2_bits = 12; /* 32 KB L2 tables */    } else {        header.cluster_bits = 12; /* 4 KB clusters */        header.l2_bits = 9; /* 4 KB L2 tables */    }    header_size = (header_size + 7) & ~7;    shift = header.cluster_bits + header.l2_bits;    l1_size = ((total_size * 512) + (1LL << shift) - 1) >> shift;    header.l1_table_offset = cpu_to_be64(header_size);    if (flags) {        header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);    } else {        header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);    }        /* write all the data */    write(fd, &header, sizeof(header));    if (backing_file) {        write(fd, backing_filename, backing_filename_len);    }    lseek(fd, header_size, SEEK_SET);    tmp = 0;    for(i = 0;i < l1_size; i++) {        write(fd, &tmp, sizeof(tmp));    }    close(fd);    return 0;}int qcow_make_empty(BlockDriverState *bs){    BDRVQcowState *s = bs->opaque;    uint32_t l1_length = s->l1_size * sizeof(uint64_t);    memset(s->l1_table, 0, l1_length);    lseek(s->fd, s->l1_table_offset, SEEK_SET);    if (write(s->fd, s->l1_table, l1_length) < 0)	return -1;    ftruncate(s->fd, s->l1_table_offset + l1_length);    memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));    memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t));    memset(s->l2_cache_counts, 0, L2_CACHE_SIZE * sizeof(uint32_t));    return 0;}int qcow_get_cluster_size(BlockDriverState *bs){    BDRVQcowState *s = bs->opaque;    if (bs->drv != &bdrv_qcow)        return -1;    return s->cluster_size;}/* XXX: put compressed sectors first, then all the cluster aligned   tables to avoid losing bytes in alignment */int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,                           const uint8_t *buf){    BDRVQcowState *s = bs->opaque;    z_stream strm;    int ret, out_len;    uint8_t *out_buf;    uint64_t cluster_offset;    if (bs->drv != &bdrv_qcow)        return -1;    out_buf = qemu_malloc(s->cluster_size + (s->cluster_size / 1000) + 128);    if (!out_buf)        return -1;    /* best compression, small window, no zlib header */    memset(&strm, 0, sizeof(strm));    ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION,                       Z_DEFLATED, -12,                        9, Z_DEFAULT_STRATEGY);    if (ret != 0) {        qemu_free(out_buf);        return -1;    }    strm.avail_in = s->cluster_size;    strm.next_in = (uint8_t *)buf;    strm.avail_out = s->cluster_size;    strm.next_out = out_buf;    ret = deflate(&strm, Z_FINISH);    if (ret != Z_STREAM_END && ret != Z_OK) {        qemu_free(out_buf);        deflateEnd(&strm);        return -1;    }    out_len = strm.next_out - out_buf;    deflateEnd(&strm);    if (ret != Z_STREAM_END || out_len >= s->cluster_size) {        /* could not compress: write normal cluster */        qcow_write(bs, sector_num, buf, s->cluster_sectors);    } else {        cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,                                             out_len, 0, 0);        cluster_offset &= s->cluster_offset_mask;        lseek(s->fd, cluster_offset, SEEK_SET);        if (write(s->fd, out_buf, out_len) != out_len) {            qemu_free(out_buf);            return -1;        }    }        qemu_free(out_buf);    return 0;}BlockDriver bdrv_qcow = {    "qcow",    sizeof(BDRVQcowState),    qcow_probe,    qcow_open,    qcow_read,    qcow_write,    qcow_close,    qcow_create,    qcow_is_allocated,    qcow_set_key,    qcow_make_empty};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -