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

📄 block-vvfat.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    for(i=0;i<number_of_entries;i++) {	entry=array_get_next(&(s->directory));	entry->attributes=0xf;	entry->reserved[0]=0;	entry->begin=0;	entry->name[0]=(number_of_entries-i)|(i==0?0x40:0);    }    for(i=0;i<length;i++) {	int offset=(i%26);	if(offset<10) offset=1+offset;	else if(offset<22) offset=14+offset-10;	else offset=28+offset-22;	entry=array_get(&(s->directory),s->directory.next-1-(i/26));	entry->name[offset]=buffer[i];    }    return array_get(&(s->directory),s->directory.next-number_of_entries);}static char is_free(const direntry_t* direntry){    /* return direntry->name[0]==0 ; */    return direntry->attributes == 0 || direntry->name[0]==0xe5;}static char is_volume_label(const direntry_t* direntry){    return direntry->attributes == 0x28;}static char is_long_name(const direntry_t* direntry){    return direntry->attributes == 0xf;}static char is_short_name(const direntry_t* direntry){    return !is_volume_label(direntry) && !is_long_name(direntry)	&& !is_free(direntry);}static char is_directory(const direntry_t* direntry){    return direntry->attributes & 0x10 && direntry->name[0] != 0xe5;}static inline char is_dot(const direntry_t* direntry){    return is_short_name(direntry) && direntry->name[0] == '.';}static char is_file(const direntry_t* direntry){    return is_short_name(direntry) && !is_directory(direntry);}static inline uint32_t begin_of_direntry(const direntry_t* direntry){    return le16_to_cpu(direntry->begin)|(le16_to_cpu(direntry->begin_hi)<<16);}static inline uint32_t filesize_of_direntry(const direntry_t* direntry){    return le32_to_cpu(direntry->size);}static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin){    direntry->begin = cpu_to_le16(begin & 0xffff);    direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff);}/* fat functions */static inline uint8_t fat_chksum(const direntry_t* entry){    uint8_t chksum=0;    int i;    for(i=0;i<11;i++)	chksum=(((chksum&0xfe)>>1)|((chksum&0x01)?0x80:0))	    +(unsigned char)entry->name[i];        return chksum;}/* if return_time==0, this returns the fat_date, else the fat_time */static uint16_t fat_datetime(time_t time,int return_time) {    struct tm* t;#ifdef _WIN32    t=localtime(&time); /* this is not thread safe */#else    struct tm t1;    t=&t1;    localtime_r(&time,t);#endif    if(return_time)	return cpu_to_le16((t->tm_sec/2)|(t->tm_min<<5)|(t->tm_hour<<11));    return cpu_to_le16((t->tm_mday)|((t->tm_mon+1)<<5)|((t->tm_year-80)<<9));}static inline void fat_set(BDRVVVFATState* s,unsigned int cluster,uint32_t value){    if(s->fat_type==32) {	uint32_t* entry=array_get(&(s->fat),cluster);	*entry=cpu_to_le32(value);    } else if(s->fat_type==16) {	uint16_t* entry=array_get(&(s->fat),cluster);	*entry=cpu_to_le16(value&0xffff);    } else {	int offset = (cluster*3/2);	unsigned char* p = array_get(&(s->fat), offset);        switch (cluster&1) {	case 0:		p[0] = value&0xff;		p[1] = (p[1]&0xf0) | ((value>>8)&0xf);		break;	case 1:		p[0] = (p[0]&0xf) | ((value&0xf)<<4);		p[1] = (value>>4);		break;	}    }}static inline uint32_t fat_get(BDRVVVFATState* s,unsigned int cluster){    if(s->fat_type==32) {	uint32_t* entry=array_get(&(s->fat),cluster);	return le32_to_cpu(*entry);    } else if(s->fat_type==16) {	uint16_t* entry=array_get(&(s->fat),cluster);	return le16_to_cpu(*entry);    } else {	const uint8_t* x=s->fat.pointer+cluster*3/2;	return ((x[0]|(x[1]<<8))>>(cluster&1?4:0))&0x0fff;    }}static inline int fat_eof(BDRVVVFATState* s,uint32_t fat_entry){    if(fat_entry>s->max_fat_value-8)	return -1;    return 0;}static inline void init_fat(BDRVVVFATState* s){    if (s->fat_type == 12) {	array_init(&(s->fat),1);	array_ensure_allocated(&(s->fat),		s->sectors_per_fat * 0x200 * 3 / 2 - 1);    } else {	array_init(&(s->fat),(s->fat_type==32?4:2));	array_ensure_allocated(&(s->fat),		s->sectors_per_fat * 0x200 / s->fat.item_size - 1);    }    memset(s->fat.pointer,0,s->fat.size);        switch(s->fat_type) {	case 12: s->max_fat_value=0xfff; break;	case 16: s->max_fat_value=0xffff; break;	case 32: s->max_fat_value=0x0fffffff; break;	default: s->max_fat_value=0; /* error... */    }}/* TODO: in create_short_filename, 0xe5->0x05 is not yet handled! *//* TODO: in parse_short_filename, 0x05->0xe5 is not yet handled! */static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,	unsigned int directory_start, const char* filename, int is_dot){    int i,j,long_index=s->directory.next;    direntry_t* entry=0;    direntry_t* entry_long=0;    if(is_dot) {	entry=array_get_next(&(s->directory));	memset(entry->name,0x20,11);	memcpy(entry->name,filename,strlen(filename));	return entry;    }        entry_long=create_long_filename(s,filename);      i = strlen(filename);     for(j = i - 1; j>0  && filename[j]!='.';j--);    if (j > 0)	i = (j > 8 ? 8 : j);    else if (i > 8)	i = 8;    entry=array_get_next(&(s->directory));    memset(entry->name,0x20,11);    strncpy(entry->name,filename,i);        if(j > 0)	for (i = 0; i < 3 && filename[j+1+i]; i++)	    entry->extension[i] = filename[j+1+i];    /* upcase & remove unwanted characters */    for(i=10;i>=0;i--) {	if(i==10 || i==7) for(;i>0 && entry->name[i]==' ';i--);	if(entry->name[i]<=' ' || entry->name[i]>0x7f		|| strchr(".*?<>|\":/\\[];,+='",entry->name[i]))	    entry->name[i]='_';        else if(entry->name[i]>='a' && entry->name[i]<='z')            entry->name[i]+='A'-'a';    }    /* mangle duplicates */    while(1) {	direntry_t* entry1=array_get(&(s->directory),directory_start);	int j;	for(;entry1<entry;entry1++)	    if(!is_long_name(entry1) && !memcmp(entry1->name,entry->name,11))		break; /* found dupe */	if(entry1==entry) /* no dupe found */	    break;	/* use all 8 characters of name */		if(entry->name[7]==' ') {	    int j;	    for(j=6;j>0 && entry->name[j]==' ';j--)		entry->name[j]='~';	}	/* increment number */	for(j=7;j>0 && entry->name[j]=='9';j--)	    entry->name[j]='0';	if(j>0) {	    if(entry->name[j]<'0' || entry->name[j]>'9')	        entry->name[j]='0';	    else	        entry->name[j]++;	}    }    /* calculate checksum; propagate to long name */    if(entry_long) {        uint8_t chksum=fat_chksum(entry);	/* calculate anew, because realloc could have taken place */	entry_long=array_get(&(s->directory),long_index);	while(entry_long<entry && is_long_name(entry_long)) {	    entry_long->reserved[1]=chksum;	    entry_long++;	}    }    return entry;}/* * Read a directory. (the index of the corresponding mapping must be passed). */static int read_directory(BDRVVVFATState* s, int mapping_index){    mapping_t* mapping = array_get(&(s->mapping), mapping_index);    direntry_t* direntry;    const char* dirname = mapping->path;    int first_cluster = mapping->begin;    int parent_index = mapping->info.dir.parent_mapping_index;    mapping_t* parent_mapping = (mapping_t*)	(parent_index >= 0 ? array_get(&(s->mapping), parent_index) : 0);    int first_cluster_of_parent = parent_mapping ? parent_mapping->begin : -1;    DIR* dir=opendir(dirname);    struct dirent* entry;    int i;    assert(mapping->mode & MODE_DIRECTORY);    if(!dir) {	mapping->end = mapping->begin;	return -1;    }       i = mapping->info.dir.first_dir_index =	    first_cluster == 0 ? 0 : s->directory.next;    /* actually read the directory, and allocate the mappings */     while((entry=readdir(dir))) {	unsigned int length=strlen(dirname)+2+strlen(entry->d_name);        char* buffer;	direntry_t* direntry;        struct stat st;	int is_dot=!strcmp(entry->d_name,".");	int is_dotdot=!strcmp(entry->d_name,"..");	if(first_cluster == 0 && (is_dotdot || is_dot))	    continue;		buffer=(char*)malloc(length);	assert(buffer);	snprintf(buffer,length,"%s/%s",dirname,entry->d_name);	if(stat(buffer,&st)<0) {	    free(buffer);            continue;	}	/* create directory entry for this file */	direntry=create_short_and_long_name(s, i, entry->d_name,		is_dot || is_dotdot);	direntry->attributes=(S_ISDIR(st.st_mode)?0x10:0x20);	direntry->reserved[0]=direntry->reserved[1]=0;	direntry->ctime=fat_datetime(st.st_ctime,1);	direntry->cdate=fat_datetime(st.st_ctime,0);	direntry->adate=fat_datetime(st.st_atime,0);	direntry->begin_hi=0;	direntry->mtime=fat_datetime(st.st_mtime,1);	direntry->mdate=fat_datetime(st.st_mtime,0);	if(is_dotdot)	    set_begin_of_direntry(direntry, first_cluster_of_parent);	else if(is_dot)	    set_begin_of_direntry(direntry, first_cluster);	else	    direntry->begin=0; /* do that later */        if (st.st_size > 0x7fffffff) {	    fprintf(stderr, "File %s is larger than 2GB\n", buffer);	    free(buffer);	    return -2;        }	direntry->size=cpu_to_le32(S_ISDIR(st.st_mode)?0:st.st_size);	/* create mapping for this file */	if(!is_dot && !is_dotdot && (S_ISDIR(st.st_mode) || st.st_size)) {	    s->current_mapping=(mapping_t*)array_get_next(&(s->mapping));	    s->current_mapping->begin=0;	    s->current_mapping->end=st.st_size;	    /*	     * we get the direntry of the most recent direntry, which	     * contains the short name and all the relevant information.	     */	    s->current_mapping->dir_index=s->directory.next-1;	    s->current_mapping->first_mapping_index = -1;	    if (S_ISDIR(st.st_mode)) {		s->current_mapping->mode = MODE_DIRECTORY;		s->current_mapping->info.dir.parent_mapping_index =		    mapping_index;	    } else {		s->current_mapping->mode = MODE_UNDEFINED;		s->current_mapping->info.file.offset = 0;	    }	    s->current_mapping->path=buffer;	    s->current_mapping->read_only =		(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0;	}    }    closedir(dir);    /* fill with zeroes up to the end of the cluster */    while(s->directory.next%(0x10*s->sectors_per_cluster)) {	direntry_t* direntry=array_get_next(&(s->directory));	memset(direntry,0,sizeof(direntry_t));    }/* TODO: if there are more entries, bootsector has to be adjusted! */#define ROOT_ENTRIES (0x02 * 0x10 * s->sectors_per_cluster)    if (mapping_index == 0 && s->directory.next < ROOT_ENTRIES) {	/* root directory */	int cur = s->directory.next;	array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1);	memset(array_get(&(s->directory), cur), 0,		(ROOT_ENTRIES - cur) * sizeof(direntry_t));    }	     /* reget the mapping, since s->mapping was possibly realloc()ed */    mapping = (mapping_t*)array_get(&(s->mapping), mapping_index);    first_cluster += (s->directory.next - mapping->info.dir.first_dir_index)	* 0x20 / s->cluster_size;    mapping->end = first_cluster;    direntry = (direntry_t*)array_get(&(s->directory), mapping->dir_index);    set_begin_of_direntry(direntry, mapping->begin);       return 0;}static inline uint32_t sector2cluster(BDRVVVFATState* s,off_t sector_num){    return (sector_num-s->faked_sectors)/s->sectors_per_cluster;}static inline off_t cluster2sector(BDRVVVFATState* s, uint32_t cluster_num){    return s->faked_sectors + s->sectors_per_cluster * cluster_num;}static inline uint32_t sector_offset_in_cluster(BDRVVVFATState* s,off_t sector_num){    return (sector_num-s->first_sectors_number-2*s->sectors_per_fat)%s->sectors_per_cluster;}#ifdef DBGstatic direntry_t* get_direntry_for_mapping(BDRVVVFATState* s,mapping_t* mapping){    if(mapping->mode==MODE_UNDEFINED)	return 0;    return (direntry_t*)(s->directory.pointer+sizeof(direntry_t)*mapping->dir_index);}#endifstatic int init_directories(BDRVVVFATState* s,

⌨️ 快捷键说明

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