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

📄 block.c.svn-base

📁 我们自己开发的一个OSEK操作系统!不知道可不可以?
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:
/* * QEMU System Emulator block driver * * Copyright (c) 2003 Fabrice Bellard * * 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"#ifndef QEMU_IMG#include "console.h"#endif#include "block_int.h"#ifdef _BSD#include <sys/types.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <sys/queue.h>#include <sys/disk.h>#endif#define SECTOR_BITS 9#define SECTOR_SIZE (1 << SECTOR_BITS)typedef struct BlockDriverAIOCBSync {    BlockDriverAIOCB common;    QEMUBH *bh;    int ret;} BlockDriverAIOCBSync;static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,        int64_t sector_num, uint8_t *buf, int nb_sectors,        BlockDriverCompletionFunc *cb, void *opaque);static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,        int64_t sector_num, const uint8_t *buf, int nb_sectors,        BlockDriverCompletionFunc *cb, void *opaque);static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb);static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,                        uint8_t *buf, int nb_sectors);static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,                         const uint8_t *buf, int nb_sectors);BlockDriverState *bdrv_first;static BlockDriver *first_drv;int path_is_absolute(const char *path){    const char *p;#ifdef _WIN32    /* specific case for names like: "\\.\d:" */    if (*path == '/' || *path == '\\')        return 1;#endif    p = strchr(path, ':');    if (p)        p++;    else        p = path;#ifdef _WIN32    return (*p == '/' || *p == '\\');#else    return (*p == '/');#endif}/* if filename is absolute, just copy it to dest. Otherwise, build a   path to it by considering it is relative to base_path. URL are   supported. */void path_combine(char *dest, int dest_size,                  const char *base_path,                  const char *filename){    const char *p, *p1;    int len;    if (dest_size <= 0)        return;    if (path_is_absolute(filename)) {        pstrcpy(dest, dest_size, filename);    } else {        p = strchr(base_path, ':');        if (p)            p++;        else            p = base_path;        p1 = strrchr(base_path, '/');#ifdef _WIN32        {            const char *p2;            p2 = strrchr(base_path, '\\');            if (!p1 || p2 > p1)                p1 = p2;        }#endif        if (p1)            p1++;        else            p1 = base_path;        if (p1 > p)            p = p1;        len = p - base_path;        if (len > dest_size - 1)            len = dest_size - 1;        memcpy(dest, base_path, len);        dest[len] = '\0';        pstrcat(dest, dest_size, filename);    }}static void bdrv_register(BlockDriver *bdrv){    if (!bdrv->bdrv_aio_read) {        /* add AIO emulation layer */        bdrv->bdrv_aio_read = bdrv_aio_read_em;        bdrv->bdrv_aio_write = bdrv_aio_write_em;        bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em;        bdrv->aiocb_size = sizeof(BlockDriverAIOCBSync);    } else if (!bdrv->bdrv_read && !bdrv->bdrv_pread) {        /* add synchronous IO emulation layer */        bdrv->bdrv_read = bdrv_read_em;        bdrv->bdrv_write = bdrv_write_em;    }    bdrv->next = first_drv;    first_drv = bdrv;}/* create a new block device (by default it is empty) */BlockDriverState *bdrv_new(const char *device_name){    BlockDriverState **pbs, *bs;    bs = qemu_mallocz(sizeof(BlockDriverState));    if(!bs)        return NULL;    pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);    if (device_name[0] != '\0') {        /* insert at the end */        pbs = &bdrv_first;        while (*pbs != NULL)            pbs = &(*pbs)->next;        *pbs = bs;    }    return bs;}BlockDriver *bdrv_find_format(const char *format_name){    BlockDriver *drv1;    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {        if (!strcmp(drv1->format_name, format_name))            return drv1;    }    return NULL;}int bdrv_create(BlockDriver *drv,                const char *filename, int64_t size_in_sectors,                const char *backing_file, int flags){    if (!drv->bdrv_create)        return -ENOTSUP;    return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);}#ifdef _WIN32void get_tmp_filename(char *filename, int size){    char temp_dir[MAX_PATH];    GetTempPath(MAX_PATH, temp_dir);    GetTempFileName(temp_dir, "qem", 0, filename);}#elsevoid get_tmp_filename(char *filename, int size){    int fd;    /* XXX: race condition possible */    pstrcpy(filename, size, "/tmp/vl.XXXXXX");    fd = mkstemp(filename);    close(fd);}#endif#ifdef _WIN32static int is_windows_drive_prefix(const char *filename){    return (((filename[0] >= 'a' && filename[0] <= 'z') ||             (filename[0] >= 'A' && filename[0] <= 'Z')) &&            filename[1] == ':');}static int is_windows_drive(const char *filename){    if (is_windows_drive_prefix(filename) &&        filename[2] == '\0')        return 1;    if (strstart(filename, "\\\\.\\", NULL) ||        strstart(filename, "//./", NULL))        return 1;    return 0;}#endifstatic BlockDriver *find_protocol(const char *filename){    BlockDriver *drv1;    char protocol[128];    int len;    const char *p;#ifdef _WIN32    if (is_windows_drive(filename) ||        is_windows_drive_prefix(filename))        return &bdrv_raw;#endif    p = strchr(filename, ':');    if (!p)        return &bdrv_raw;    len = p - filename;    if (len > sizeof(protocol) - 1)        len = sizeof(protocol) - 1;    memcpy(protocol, filename, len);    protocol[len] = '\0';    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {        if (drv1->protocol_name &&            !strcmp(drv1->protocol_name, protocol))            return drv1;    }    return NULL;}/* XXX: force raw format if block or character device ? It would   simplify the BSD case */static BlockDriver *find_image_format(const char *filename){    int ret, score, score_max;    BlockDriver *drv1, *drv;    uint8_t buf[2048];    BlockDriverState *bs;    /* detect host devices. By convention, /dev/cdrom[N] is always       recognized as a host CDROM */    if (strstart(filename, "/dev/cdrom", NULL))        return &bdrv_host_device;#ifdef _WIN32    if (is_windows_drive(filename))        return &bdrv_host_device;#else    {        struct stat st;        if (stat(filename, &st) >= 0 &&            (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {            return &bdrv_host_device;        }    }#endif    drv = find_protocol(filename);    /* no need to test disk image formats for vvfat */    if (drv == &bdrv_vvfat)        return drv;    ret = bdrv_file_open(&bs, filename, BDRV_O_RDONLY);    if (ret < 0)        return NULL;    ret = bdrv_pread(bs, 0, buf, sizeof(buf));    bdrv_delete(bs);    if (ret < 0) {        return NULL;    }    score_max = 0;    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {        if (drv1->bdrv_probe) {            score = drv1->bdrv_probe(buf, ret, filename);            if (score > score_max) {                score_max = score;                drv = drv1;            }        }    }    return drv;}int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags){    BlockDriverState *bs;    int ret;    bs = bdrv_new("");    if (!bs)        return -ENOMEM;    ret = bdrv_open2(bs, filename, flags | BDRV_O_FILE, NULL);    if (ret < 0) {        bdrv_delete(bs);        return ret;    }    *pbs = bs;    return 0;}int bdrv_open(BlockDriverState *bs, const char *filename, int flags){    return bdrv_open2(bs, filename, flags, NULL);}int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,               BlockDriver *drv){    int ret, open_flags;    char tmp_filename[PATH_MAX];    char backing_filename[PATH_MAX];    bs->read_only = 0;    bs->is_temporary = 0;    bs->encrypted = 0;    if (flags & BDRV_O_SNAPSHOT) {        BlockDriverState *bs1;        int64_t total_size;        /* if snapshot, we create a temporary backing file and open it           instead of opening 'filename' directly */        /* if there is a backing file, use it */        bs1 = bdrv_new("");        if (!bs1) {            return -ENOMEM;        }        if (bdrv_open(bs1, filename, 0) < 0) {            bdrv_delete(bs1);            return -1;        }        total_size = bdrv_getlength(bs1) >> SECTOR_BITS;        bdrv_delete(bs1);        get_tmp_filename(tmp_filename, sizeof(tmp_filename));        realpath(filename, backing_filename);        if (bdrv_create(&bdrv_qcow2, tmp_filename,                        total_size, backing_filename, 0) < 0) {            return -1;        }        filename = tmp_filename;        bs->is_temporary = 1;    }    pstrcpy(bs->filename, sizeof(bs->filename), filename);    if (flags & BDRV_O_FILE) {        drv = find_protocol(filename);        if (!drv)            return -ENOENT;    } else {        if (!drv) {            drv = find_image_format(filename);            if (!drv)                return -1;        }    }    bs->drv = drv;    bs->opaque = qemu_mallocz(drv->instance_size);    if (bs->opaque == NULL && drv->instance_size > 0)        return -1;    /* Note: for compatibility, we open disk image files as RDWR, and       RDONLY as fallback */    if (!(flags & BDRV_O_FILE))        open_flags = BDRV_O_RDWR | (flags & BDRV_O_DIRECT);    else        open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);    ret = drv->bdrv_open(bs, filename, open_flags);    if (ret == -EACCES && !(flags & BDRV_O_FILE)) {        ret = drv->bdrv_open(bs, filename, BDRV_O_RDONLY);        bs->read_only = 1;    }    if (ret < 0) {        qemu_free(bs->opaque);        bs->opaque = NULL;        bs->drv = NULL;        return ret;    }    if (drv->bdrv_getlength) {        bs->total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;    }#ifndef _WIN32    if (bs->is_temporary) {        unlink(filename);    }#endif    if (bs->backing_file[0] != '\0') {        /* if there is a backing file, use it */        bs->backing_hd = bdrv_new("");        if (!bs->backing_hd) {        fail:            bdrv_close(bs);            return -ENOMEM;        }        path_combine(backing_filename, sizeof(backing_filename),                     filename, bs->backing_file);        if (bdrv_open(bs->backing_hd, backing_filename, 0) < 0)            goto fail;    }    /* call the change callback */    bs->media_changed = 1;    if (bs->change_cb)        bs->change_cb(bs->change_opaque);    return 0;}void bdrv_close(BlockDriverState *bs){    if (bs->drv) {        if (bs->backing_hd)            bdrv_delete(bs->backing_hd);        bs->drv->bdrv_close(bs);        qemu_free(bs->opaque);#ifdef _WIN32        if (bs->is_temporary) {            unlink(bs->filename);        }#endif        bs->opaque = NULL;        bs->drv = NULL;        /* call the change callback */        bs->media_changed = 1;        if (bs->change_cb)            bs->change_cb(bs->change_opaque);    }}void bdrv_delete(BlockDriverState *bs){    /* XXX: remove the driver list */    bdrv_close(bs);    qemu_free(bs);}/* commit COW file into the raw image */int bdrv_commit(BlockDriverState *bs){    BlockDriver *drv = bs->drv;    int64_t i, total_sectors;    int n, j;    unsigned char sector[512];    if (!drv)        return -ENOMEDIUM;    if (bs->read_only) {	return -EACCES;    }    if (!bs->backing_hd) {

⌨️ 快捷键说明

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