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

📄 block-vmdk.c.svn-base

📁 我们自己开发的一个OSEK操作系统!不知道可不可以?
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
/* * Block driver for the VMDK format * * Copyright (c) 2004 Fabrice Bellard * Copyright (c) 2005 Filip Navara * * 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. */#include "qemu-common.h"#include "block_int.h"#define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')#define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')typedef struct {    uint32_t version;    uint32_t flags;    uint32_t disk_sectors;    uint32_t granularity;    uint32_t l1dir_offset;    uint32_t l1dir_size;    uint32_t file_sectors;    uint32_t cylinders;    uint32_t heads;    uint32_t sectors_per_track;} VMDK3Header;typedef struct {    uint32_t version;    uint32_t flags;    int64_t capacity;    int64_t granularity;    int64_t desc_offset;    int64_t desc_size;    int32_t num_gtes_per_gte;    int64_t rgd_offset;    int64_t gd_offset;    int64_t grain_offset;    char filler[1];    char check_bytes[4];} __attribute__((packed)) VMDK4Header;#define L2_CACHE_SIZE 16typedef struct BDRVVmdkState {    BlockDriverState *hd;    int64_t l1_table_offset;    int64_t l1_backup_table_offset;    uint32_t *l1_table;    uint32_t *l1_backup_table;    unsigned int l1_size;    uint32_t l1_entry_sectors;    unsigned int l2_size;    uint32_t *l2_cache;    uint32_t l2_cache_offsets[L2_CACHE_SIZE];    uint32_t l2_cache_counts[L2_CACHE_SIZE];    unsigned int cluster_sectors;    uint32_t parent_cid;    int is_parent;} BDRVVmdkState;typedef struct VmdkMetaData {    uint32_t offset;    unsigned int l1_index;    unsigned int l2_index;    unsigned int l2_offset;    int valid;} VmdkMetaData;typedef struct ActiveBDRVState{    BlockDriverState *hd;            // active image handler    uint64_t cluster_offset;         // current write offset}ActiveBDRVState;static ActiveBDRVState activeBDRV;static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename){    uint32_t magic;    if (buf_size < 4)        return 0;    magic = be32_to_cpu(*(uint32_t *)buf);    if (magic == VMDK3_MAGIC ||        magic == VMDK4_MAGIC)        return 100;    else        return 0;}#define CHECK_CID 1#define SECTOR_SIZE 512#define DESC_SIZE 20*SECTOR_SIZE	// 20 sectors of 512 bytes each#define HEADER_SIZE 512   			// first sector of 512 bytesstatic uint32_t vmdk_read_cid(BlockDriverState *bs, int parent){    BDRVVmdkState *s = bs->opaque;    char desc[DESC_SIZE];    uint32_t cid;    char *p_name, *cid_str;    size_t cid_str_size;    /* the descriptor offset = 0x200 */    if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)        return 0;    if (parent) {        cid_str = "parentCID";        cid_str_size = sizeof("parentCID");    } else {        cid_str = "CID";        cid_str_size = sizeof("CID");    }    if ((p_name = strstr(desc,cid_str)) != 0) {        p_name += cid_str_size;        sscanf(p_name,"%x",&cid);    }    return cid;}static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid){    BDRVVmdkState *s = bs->opaque;    char desc[DESC_SIZE], tmp_desc[DESC_SIZE];    char *p_name, *tmp_str;    /* the descriptor offset = 0x200 */    if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)        return -1;    tmp_str = strstr(desc,"parentCID");    strcpy(tmp_desc, tmp_str);    if ((p_name = strstr(desc,"CID")) != 0) {        p_name += sizeof("CID");        sprintf(p_name,"%x\n",cid);        strcat(desc,tmp_desc);    }    if (bdrv_pwrite(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)        return -1;    return 0;}static int vmdk_is_cid_valid(BlockDriverState *bs){#ifdef CHECK_CID    BDRVVmdkState *s = bs->opaque;    BlockDriverState *p_bs = s->hd->backing_hd;    uint32_t cur_pcid;    if (p_bs) {        cur_pcid = vmdk_read_cid(p_bs,0);        if (s->parent_cid != cur_pcid)            // CID not valid            return 0;    }#endif    // CID valid    return 1;}static int vmdk_snapshot_create(const char *filename, const char *backing_file){    int snp_fd, p_fd;    uint32_t p_cid;    char *p_name, *gd_buf, *rgd_buf;    const char *real_filename, *temp_str;    VMDK4Header header;    uint32_t gde_entries, gd_size;    int64_t gd_offset, rgd_offset, capacity, gt_size;    char p_desc[DESC_SIZE], s_desc[DESC_SIZE], hdr[HEADER_SIZE];    char *desc_template =    "# Disk DescriptorFile\n"    "version=1\n"    "CID=%x\n"    "parentCID=%x\n"    "createType=\"monolithicSparse\"\n"    "parentFileNameHint=\"%s\"\n"    "\n"    "# Extent description\n"    "RW %lu SPARSE \"%s\"\n"    "\n"    "# The Disk Data Base \n"    "#DDB\n"    "\n";    snp_fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 0644);    if (snp_fd < 0)        return -1;    p_fd = open(backing_file, O_RDONLY | O_BINARY | O_LARGEFILE);    if (p_fd < 0) {        close(snp_fd);        return -1;    }    /* read the header */    if (lseek(p_fd, 0x0, SEEK_SET) == -1)        goto fail;    if (read(p_fd, hdr, HEADER_SIZE) != HEADER_SIZE)        goto fail;    /* write the header */    if (lseek(snp_fd, 0x0, SEEK_SET) == -1)        goto fail;    if (write(snp_fd, hdr, HEADER_SIZE) == -1)        goto fail;    memset(&header, 0, sizeof(header));    memcpy(&header,&hdr[4], sizeof(header)); // skip the VMDK4_MAGIC    ftruncate(snp_fd, header.grain_offset << 9);    /* the descriptor offset = 0x200 */    if (lseek(p_fd, 0x200, SEEK_SET) == -1)        goto fail;    if (read(p_fd, p_desc, DESC_SIZE) != DESC_SIZE)        goto fail;    if ((p_name = strstr(p_desc,"CID")) != 0) {        p_name += sizeof("CID");        sscanf(p_name,"%x",&p_cid);    }    real_filename = filename;    if ((temp_str = strrchr(real_filename, '\\')) != NULL)        real_filename = temp_str + 1;    if ((temp_str = strrchr(real_filename, '/')) != NULL)        real_filename = temp_str + 1;    if ((temp_str = strrchr(real_filename, ':')) != NULL)        real_filename = temp_str + 1;    sprintf(s_desc, desc_template, p_cid, p_cid, backing_file            , (uint32_t)header.capacity, real_filename);    /* write the descriptor */    if (lseek(snp_fd, 0x200, SEEK_SET) == -1)        goto fail;    if (write(snp_fd, s_desc, strlen(s_desc)) == -1)        goto fail;    gd_offset = header.gd_offset * SECTOR_SIZE;     // offset of GD table    rgd_offset = header.rgd_offset * SECTOR_SIZE;   // offset of RGD table    capacity = header.capacity * SECTOR_SIZE;       // Extent size    /*     * Each GDE span 32M disk, means:     * 512 GTE per GT, each GTE points to grain     */    gt_size = (int64_t)header.num_gtes_per_gte * header.granularity * SECTOR_SIZE;    if (!gt_size)        goto fail;    gde_entries = (uint32_t)(capacity / gt_size);  // number of gde/rgde    gd_size = gde_entries * sizeof(uint32_t);    /* write RGD */    rgd_buf = qemu_malloc(gd_size);    if (!rgd_buf)        goto fail;    if (lseek(p_fd, rgd_offset, SEEK_SET) == -1)        goto fail_rgd;    if (read(p_fd, rgd_buf, gd_size) != gd_size)        goto fail_rgd;    if (lseek(snp_fd, rgd_offset, SEEK_SET) == -1)        goto fail_rgd;    if (write(snp_fd, rgd_buf, gd_size) == -1)        goto fail_rgd;    qemu_free(rgd_buf);    /* write GD */    gd_buf = qemu_malloc(gd_size);    if (!gd_buf)        goto fail_rgd;    if (lseek(p_fd, gd_offset, SEEK_SET) == -1)        goto fail_gd;    if (read(p_fd, gd_buf, gd_size) != gd_size)        goto fail_gd;    if (lseek(snp_fd, gd_offset, SEEK_SET) == -1)        goto fail_gd;    if (write(snp_fd, gd_buf, gd_size) == -1)        goto fail_gd;    qemu_free(gd_buf);    close(p_fd);    close(snp_fd);    return 0;    fail_gd:    qemu_free(gd_buf);    fail_rgd:    qemu_free(rgd_buf);    fail:    close(p_fd);    close(snp_fd);    return -1;}static void vmdk_parent_close(BlockDriverState *bs){    if (bs->backing_hd)        bdrv_close(bs->backing_hd);}int parent_open = 0;static int vmdk_parent_open(BlockDriverState *bs, const char * filename){    BDRVVmdkState *s = bs->opaque;    char *p_name;    char desc[DESC_SIZE];    char parent_img_name[1024];    /* the descriptor offset = 0x200 */    if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)        return -1;    if ((p_name = strstr(desc,"parentFileNameHint")) != 0) {        char *end_name;        struct stat file_buf;        p_name += sizeof("parentFileNameHint") + 1;        if ((end_name = strchr(p_name,'\"')) == 0)            return -1;        strncpy(s->hd->backing_file, p_name, end_name - p_name);        if (stat(s->hd->backing_file, &file_buf) != 0) {            path_combine(parent_img_name, sizeof(parent_img_name),                         filename, s->hd->backing_file);        } else {            strcpy(parent_img_name, s->hd->backing_file);        }        s->hd->backing_hd = bdrv_new("");        if (!s->hd->backing_hd) {            failure:            bdrv_close(s->hd);            return -1;        }        parent_open = 1;        if (bdrv_open(s->hd->backing_hd, parent_img_name, BDRV_O_RDONLY) < 0)            goto failure;        parent_open = 0;    }    return 0;}static int vmdk_open(BlockDriverState *bs, const char *filename, int flags){    BDRVVmdkState *s = bs->opaque;    uint32_t magic;    int l1_size, i, ret;    if (parent_open)        // Parent must be opened as RO.        flags = BDRV_O_RDONLY;    fprintf(stderr, "(VMDK) image open: flags=0x%x filename=%s\n", flags, bs->filename);    ret = bdrv_file_open(&s->hd, filename, flags);    if (ret < 0)        return ret;    if (bdrv_pread(s->hd, 0, &magic, sizeof(magic)) != sizeof(magic))        goto fail;    magic = be32_to_cpu(magic);    if (magic == VMDK3_MAGIC) {        VMDK3Header header;        if (bdrv_pread(s->hd, sizeof(magic), &header, sizeof(header)) != sizeof(header))            goto fail;        s->cluster_sectors = le32_to_cpu(header.granularity);        s->l2_size = 1 << 9;        s->l1_size = 1 << 6;        bs->total_sectors = le32_to_cpu(header.disk_sectors);        s->l1_table_offset = le32_to_cpu(header.l1dir_offset) << 9;        s->l1_backup_table_offset = 0;        s->l1_entry_sectors = s->l2_size * s->cluster_sectors;    } else if (magic == VMDK4_MAGIC) {        VMDK4Header header;        if (bdrv_pread(s->hd, sizeof(magic), &header, sizeof(header)) != sizeof(header))            goto fail;        bs->total_sectors = le64_to_cpu(header.capacity);        s->cluster_sectors = le64_to_cpu(header.granularity);        s->l2_size = le32_to_cpu(header.num_gtes_per_gte);        s->l1_entry_sectors = s->l2_size * s->cluster_sectors;        if (s->l1_entry_sectors <= 0)            goto fail;        s->l1_size = (bs->total_sectors + s->l1_entry_sectors - 1)            / s->l1_entry_sectors;        s->l1_table_offset = le64_to_cpu(header.rgd_offset) << 9;        s->l1_backup_table_offset = le64_to_cpu(header.gd_offset) << 9;        if (parent_open)            s->is_parent = 1;        else

⌨️ 快捷键说明

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