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

📄 block-vvfat.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* vim:set shiftwidth=4 ts=8: *//* * QEMU Block driver for virtual VFAT (shadows a local directory) *  * Copyright (c) 2004,2005 Johannes E. Schindelin *  * 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 <sys/stat.h>#include <dirent.h>#include <assert.h>#include "vl.h"#include "block_int.h"#ifndef S_IWGRP#define S_IWGRP 0#endif#ifndef S_IWOTH#define S_IWOTH 0#endif/* TODO: add ":bootsector=blabla.img:" *//* LATER TODO: add automatic boot sector generation from    BOOTEASY.ASM and Ranish Partition Manager    Note that DOS assumes the system files to be the first files in the     file system (test if the boot sector still relies on that fact)! *//* MAYBE TODO: write block-visofs.c *//* TODO: call try_commit() only after a timeout *//* #define DEBUG */#ifdef DEBUG#define DLOG(a) a#undef stderr#define stderr STDERRFILE* stderr = NULL;static void checkpoint();#ifdef __MINGW32__void nonono(const char* file, int line, const char* msg) {    fprintf(stderr, "Nonono! %s:%d %s\n", file, line, msg);    exit(-5);}#undef assert#define assert(a) if (!(a)) nonono(__FILE__, __LINE__, #a)#endif#else#define DLOG(a)#endif/* dynamic array functions */typedef struct array_t {    char* pointer;    unsigned int size,next,item_size;} array_t;static inline void array_init(array_t* array,unsigned int item_size){    array->pointer=0;    array->size=0;    array->next=0;    array->item_size=item_size;}static inline void array_free(array_t* array){    if(array->pointer)        free(array->pointer);    array->size=array->next=0;}/* does not automatically grow */static inline void* array_get(array_t* array,unsigned int index) {    assert(index >= 0);    assert(index < array->next);    return array->pointer + index * array->item_size;}static inline int array_ensure_allocated(array_t* array, int index){    if((index + 1) * array->item_size > array->size) {	int new_size = (index + 32) * array->item_size;	array->pointer = realloc(array->pointer, new_size);	if (!array->pointer)	    return -1;	array->size = new_size;	array->next = index + 1;    }    return 0;}static inline void* array_get_next(array_t* array) {    unsigned int next = array->next;    void* result;    if (array_ensure_allocated(array, next) < 0)	return NULL;    array->next = next + 1;    result = array_get(array, next);    return result;}static inline void* array_insert(array_t* array,unsigned int index,unsigned int count) {    if((array->next+count)*array->item_size>array->size) {	int increment=count*array->item_size;	array->pointer=realloc(array->pointer,array->size+increment);	if(!array->pointer)	    return 0;	array->size+=increment;    }    memmove(array->pointer+(index+count)*array->item_size,		array->pointer+index*array->item_size,		(array->next-index)*array->item_size);    array->next+=count;    return array->pointer+index*array->item_size;}/* this performs a "roll", so that the element which was at index_from becomes * index_to, but the order of all other elements is preserved. */static inline int array_roll(array_t* array,int index_to,int index_from,int count){    char* buf;    char* from;    char* to;    int is;    if(!array ||	    index_to<0 || index_to>=array->next ||	    index_from<0 || index_from>=array->next)	return -1;        if(index_to==index_from)	return 0;    is=array->item_size;    from=array->pointer+index_from*is;    to=array->pointer+index_to*is;    buf=malloc(is*count);    memcpy(buf,from,is*count);    if(index_to<index_from)	memmove(to+is*count,to,from-to);    else	memmove(from,from+is*count,to-from);        memcpy(to,buf,is*count);    free(buf);    return 0;}inline int array_remove_slice(array_t* array,int index, int count){    assert(index >=0);    assert(count > 0);    assert(index + count <= array->next);    if(array_roll(array,array->next-1,index,count))	return -1;    array->next -= count;    return 0;}int array_remove(array_t* array,int index){    return array_remove_slice(array, index, 1);}/* return the index for a given member */int array_index(array_t* array, void* pointer){    size_t offset = (char*)pointer - array->pointer;    assert(offset >= 0);    assert((offset % array->item_size) == 0);    assert(offset/array->item_size < array->next);    return offset/array->item_size;}/* These structures are used to fake a disk and the VFAT filesystem. * For this reason we need to use __attribute__((packed)). */typedef struct bootsector_t {    uint8_t jump[3];    uint8_t name[8];    uint16_t sector_size;    uint8_t sectors_per_cluster;    uint16_t reserved_sectors;    uint8_t number_of_fats;    uint16_t root_entries;    uint16_t total_sectors16;    uint8_t media_type;    uint16_t sectors_per_fat;    uint16_t sectors_per_track;    uint16_t number_of_heads;    uint32_t hidden_sectors;    uint32_t total_sectors;    union {        struct {	    uint8_t drive_number;	    uint8_t current_head;	    uint8_t signature;	    uint32_t id;	    uint8_t volume_label[11];	} __attribute__((packed)) fat16;	struct {	    uint32_t sectors_per_fat;	    uint16_t flags;	    uint8_t major,minor;	    uint32_t first_cluster_of_root_directory;	    uint16_t info_sector;	    uint16_t backup_boot_sector;	    uint16_t ignored;	} __attribute__((packed)) fat32;    } u;    uint8_t fat_type[8];    uint8_t ignored[0x1c0];    uint8_t magic[2];} __attribute__((packed)) bootsector_t;typedef struct partition_t {    uint8_t attributes; /* 0x80 = bootable */    uint8_t start_head;    uint8_t start_sector;    uint8_t start_cylinder;    uint8_t fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xb = FAT32 */    uint8_t end_head;    uint8_t end_sector;    uint8_t end_cylinder;    uint32_t start_sector_long;    uint32_t end_sector_long;} __attribute__((packed)) partition_t;typedef struct mbr_t {    uint8_t ignored[0x1be];    partition_t partition[4];    uint8_t magic[2];} __attribute__((packed)) mbr_t;typedef struct direntry_t {    uint8_t name[8];    uint8_t extension[3];    uint8_t attributes;    uint8_t reserved[2];    uint16_t ctime;    uint16_t cdate;    uint16_t adate;    uint16_t begin_hi;    uint16_t mtime;    uint16_t mdate;    uint16_t begin;    uint32_t size;} __attribute__((packed)) direntry_t;/* this structure are used to transparently access the files */typedef struct mapping_t {    /* begin is the first cluster, end is the last+1 */    uint32_t begin,end;    /* as s->directory is growable, no pointer may be used here */    unsigned int dir_index;    /* the clusters of a file may be in any order; this points to the first */    int first_mapping_index;    union {	/* offset is	 * - the offset in the file (in clusters) for a file, or	 * - the next cluster of the directory for a directory, and	 * - the address of the buffer for a faked entry	 */	struct {	    uint32_t offset;	} file;	struct {	    int parent_mapping_index;	    int first_dir_index;	} dir;    } info;    /* path contains the full path, i.e. it always starts with s->path */    char* path;    enum { MODE_UNDEFINED = 0, MODE_NORMAL = 1, MODE_MODIFIED = 2,	MODE_DIRECTORY = 4, MODE_FAKED = 8,	MODE_DELETED = 16, MODE_RENAMED = 32 } mode;    int read_only;} mapping_t;#ifdef DEBUGstatic void print_direntry(const struct direntry_t*);static void print_mapping(const struct mapping_t* mapping);#endif/* here begins the real VVFAT driver */typedef struct BDRVVVFATState {    BlockDriverState* bs; /* pointer to parent */    unsigned int first_sectors_number; /* 1 for a single partition, 0x40 for a disk with partition table */    unsigned char first_sectors[0x40*0x200];        int fat_type; /* 16 or 32 */    array_t fat,directory,mapping;       unsigned int cluster_size;    unsigned int sectors_per_cluster;    unsigned int sectors_per_fat;    unsigned int sectors_of_root_directory;    uint32_t last_cluster_of_root_directory;    unsigned int faked_sectors; /* how many sectors are faked before file data */    uint32_t sector_count; /* total number of sectors of the partition */    uint32_t cluster_count; /* total number of clusters of this partition */    uint32_t max_fat_value;       int current_fd;    mapping_t* current_mapping;    unsigned char* cluster; /* points to current cluster */    unsigned char* cluster_buffer; /* points to a buffer to hold temp data */    unsigned int current_cluster;    /* write support */    BlockDriverState* write_target;    char* qcow_filename;    BlockDriverState* qcow;    void* fat2;    char* used_clusters;    array_t commits;    const char* path;    int downcase_short_names;} BDRVVVFATState;static int vvfat_probe(const uint8_t *buf, int buf_size, const char *filename){    if (strstart(filename, "fat:", NULL))	return 100;    return 0;}static void init_mbr(BDRVVVFATState* s){    /* TODO: if the files mbr.img and bootsect.img exist, use them */    mbr_t* real_mbr=(mbr_t*)s->first_sectors;    partition_t* partition=&(real_mbr->partition[0]);    memset(s->first_sectors,0,512);       partition->attributes=0x80; /* bootable */    partition->start_head=1;    partition->start_sector=1;    partition->start_cylinder=0;    /* FAT12/FAT16/FAT32 */    partition->fs_type=(s->fat_type==12?0x1:s->fat_type==16?0x6:0xb);    partition->end_head=s->bs->heads-1;    partition->end_sector=0xff; /* end sector & upper 2 bits of cylinder */;    partition->end_cylinder=0xff; /* lower 8 bits of end cylinder */;    partition->start_sector_long=cpu_to_le32(s->bs->secs);    partition->end_sector_long=cpu_to_le32(s->sector_count);    real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;}/* direntry functions *//* dest is assumed to hold 258 bytes, and pads with 0xffff up to next multiple of 26 */static inline int short2long_name(unsigned char* dest,const char* src){    int i;    for(i=0;i<129 && src[i];i++) {        dest[2*i]=src[i];	dest[2*i+1]=0;    }    dest[2*i]=dest[2*i+1]=0;    for(i=2*i+2;(i%26);i++)	dest[i]=0xff;    return i;}static inline direntry_t* create_long_filename(BDRVVVFATState* s,const char* filename){    char buffer[258];    int length=short2long_name(buffer,filename),        number_of_entries=(length+25)/26,i;    direntry_t* entry;

⌨️ 快捷键说明

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