|
/************************************************************************ * File : filesystem.c * Processor : ADSP-BF533 * IDDE : VisualDSP++3.5 * Description : Define operating functions of FAT32, includes: * * Wait_Ready(); * Wait_ReadyBusy(); * CheckforError(); * IdeStandby(); * IdeIdle(); * *************************************************************************/ #include "fat/filesystem.h" #include "fat/fat32.h" #include "IDE/ide_access.h" #include "IDE/ide_base.h" #include "type.h"
partition_table_t *partition_table[23]; FS_t fs;
extern BYTE fnUpdateFILE(FILE_t *fp); extern currentcluster_t fnFAT32_WriteSector(currentcluster_t,DWORD);
extern unsigned int cycles[100];
/****************************************************************** * Function : fnDetect_Partition * Description : get HD DPT information * Input : none * Return : none *******************************************************************/ void fnDetect_Partition(void) { BYTE partition_num=0; BYTE temp; BYTE master_table_buffer[64]; BYTE *table_buffer; BYTE i; DWORD LBABEGIN; DWORD EXT_next_partition; // Load MBR (LBA 0) into the 512 byte buffer fnIDE_BufferSector(&(buffers.currentsector),0,1); // Make Sure 0x55 and 0xAA are at end of sector if (fnIDE_SectorWord(SIGN_POSITION)!=SIGN_VALUE) { printf("\r\nInvalid MBR, Please Format Drive\r\n"); while(1); } //read main DPT (4 partitions) fnIDE_SectorData(PARTITION_TABLE_1,master_table_buffer,sizeof(master_table_buffer)); // table_buffer=(BYTE*)malloc(sizeof(BYTE)*PARTITION_TABLE_SIZE); for (i=0;i<4;i++) { temp=master_table_buffer[i*PARTITION_TABLE_SIZE+SYSTEM_ID]; //Processing Extended Aartition if((temp==EXT_TYPECODE1)||(temp==EXT_TYPECODE2)) { memcpy(table_buffer,master_table_buffer+i*PARTITION_TABLE_SIZE,PARTITION_TABLE_SIZE); while(temp!=NO_PARTITION) { EXT_next_partition =table_buffer[OFFSET_SECTOR]; EXT_next_partition+=((DWORD)table_buffer[OFFSET_SECTOR+1])<<8; EXT_next_partition+=((DWORD)table_buffer[OFFSET_SECTOR+2])<<16; EXT_next_partition+=((DWORD)table_buffer[OFFSET_SECTOR+3])<<24; fnIDE_BufferSector(&(buffers.currentsector),EXT_next_partition,1); fnIDE_SectorData(PARTITION_TABLE_1,table_buffer,sizeof(table_buffer)); fnPartition_init(table_buffer,partition_num); partition_num++; fnIDE_SectorData(PARTITION_TABLE_2,table_buffer,sizeof(table_buffer)); temp=table_buffer[SYSTEM_ID]; } continue; } else if(temp==NO_PARTITION) { break; } memcpy(table_buffer,master_table_buffer+i*PARTITION_TABLE_SIZE,PARTITION_TABLE_SIZE); fnPartition_init(table_buffer,partition_num); partition_num++; } for(i=partition_num;i<23;i++) { partition_table[i]=NULL; } free(table_buffer); if(partition_num==0) { printf("The Disk isn't partitioned\r\n"); return; } } /****************************************************************** * Function : fnPartition_init * Description : Initialize DPT, get DPT inforamtion * Input : * BYTE *buffer-informatioin of DPT * BYTE num-partition number * Return : none *******************************************************************/ void fnPartition_init(BYTE *buffer,BYTE num) { BYTE temp; temp=buffer[SYSTEM_ID]; if ((temp==FAT32_TYPECODE1)||(temp==FAT32_TYPECODE2)||(temp==FAT32_TYPECODE3)) { partition_table[num]=(partition_table_t *)malloc(sizeof(partition_table_t)); partition_table[num]->flag=1; partition_table[num]->fs=(FS_t *)malloc(sizeof(FS_t)); partition_table[num]->fnFS_init = fnFAT32_init; } else if ((temp==FAT16_TYPECODE1)||(temp==FAT16_TYPECODE2)||(temp==FAT16_TYPECODE3)) { /*partition_table[num]=(partition_table_t *)malloc(sizeof(partition_table_t)); partition_table[num]->flag=1; partition_table[num]->fs=(FS_t *)malloc(sizeof(FS_t)); partition_table[num]->fnFS_init = fnFAT16_init;*/ } else { partition_table[num]=(partition_table_t *)malloc(sizeof(partition_table_t)); partition_table[num]->flag=0; return; }
partition_table[num]->offset_sector = buffer[OFFSET_SECTOR]; partition_table[num]->total_sector = buffer[TOTAL_SECTOR]; partition_table[num]->fnFS_init(partition_table[num]->fs,partition_table[num]->offset_sector); }
/****************************************************************** * Function : fnFATMisc_If_LFN_TextOnly * Description : Check long file name * Input : * BYTE recordoffset-offset of long file name entry in buffers * Return : yes-1/no-0 *******************************************************************/ int fnFATMisc_If_LFN_TextOnly(DWORD recordoffset) { if ((fnIDE_SectorByte(recordoffset+11)&0x0F)==FILE_ATTR_LFN_TEXT) return 1; else return 0; }
/****************************************************************** * Function : fnFATMisc_If_LFN_Invalid * Description : Check the entry wheter ignorable, ignore the entry if the entry is null or deleted * Input : * BYTE recordoffset-offset of long file name entry in buffers * Return : yes-1/no-0 *******************************************************************/ int fnFATMisc_If_LFN_Invalid(DWORD recordoffset) { if ((fnIDE_SectorByte(recordoffset)==FILE_HEADER_BLANK)||(fnIDE_SectorByte(recordoffset)==FILE_HEADER_DELETED))//||(fnIDE_SectorByte(recordoffset+11)==FILE_ATTR_VOLUME_ID)||(fnIDE_SectorByte(recordoffset+11)&FILE_ATTR_SYSHID)) return 1; else return 0; } /****************************************************************** * Function : fnFATMisc_If_LFN_Exists * Description : Check whether a long file name. * Input : * BYTE recordoffset-offset of long file name entryin buffers * Return : yes-1/no-0 *******************************************************************/ int fnFATMisc_If_LFN_Exists(DWORD recordoffset, BYTE LFNstrings) { if ((fnIDE_SectorByte(recordoffset+11)!=FILE_ATTR_LFN_TEXT) && (fnIDE_SectorByte(recordoffset)!=FILE_HEADER_BLANK) && (fnIDE_SectorByte(recordoffset)!=FILE_HEADER_DELETED) /*&& (fnIDE_SectorByte(recordoffset+11)!=FILE_ATTR_VOLUME_ID) && (!(fnIDE_SectorByte(recordoffset+11)&FILE_ATTR_SYSHID))*/ && (LFNstrings)) return 1; else return 0; } /****************************************************************** * Function : fnFATMisc_If_noLFN_SFN_Only * Description : Check whether not long file name only * Input : * BYTE recordoffset-offset of long file name entry in buffers * Return : yes-1/no-0 *******************************************************************/ int fnFATMisc_If_noLFN_SFN_Only(DWORD recordoffset) { if ((fnIDE_SectorByte(recordoffset+11)!=FILE_ATTR_LFN_TEXT) && (fnIDE_SectorByte(recordoffset)!=FILE_HEADER_BLANK) && (fnIDE_SectorByte(recordoffset)!=FILE_HEADER_DELETED) /*&& (fnIDE_SectorByte(recordoffset+11)!=FILE_ATTR_VOLUME_ID) && (!(fnIDE_SectorByte(recordoffset+11)&FILE_ATTR_SYSHID))*/) return 1; else return 0; } /****************************************************************** * Function : fnFATMisc_If_dir_entry * Description : Check whether directory entry * Input : * BYTE recordoffset-offset of long file name entry in buffers * Return : yes-1/no-0 *******************************************************************/ int fnFATMisc_If_dir_entry(DWORD recordoffset) { if ((fnIDE_SectorByte(recordoffset+11))&FILE_ATTR_DIRECTORY) return 1; else return 0; } /****************************************************************** * Function : fnFATMisc_cacheLFN * Description : fetch long file name entry - ASCII charaters * Input : * BYTE recordoffset-offset of long file name entry in buffers * BYTE LFNIndex-long file name entry number * BYTE *String-destinated address of store long file name * Return : BYTE numbers of ASCII charaters *******************************************************************/ BYTE fnFATMisc_cacheLFN(WORD recordoffset,BYTE LFNIndex,BYTE *String) { BYTE i; BYTE String_offset; //charater location in long file name entry BYTE char_locate[13]={1,3,5,7,9,0x0E,0x10,0x12,0x14,0x16,0x18,0x1C,0x1E}; BYTE sub_size; String_offset = 0; for(i=1;i<LFNIndex;i++) { String_offset += 13; } sub_size=13; for(i=0;i<13;i++) {
//Charaters in long file name are encoded in unicode format. String[String_offset+i] = fnIDE_SectorByte(recordoffset+char_locate[i]); if(String[String_offset+i]==0) { sub_size=i; break; } } for (i=0; i<13; i++) if (String[String_offset+i]==0xFF) String[String_offset+i] = 0x0; // Replace with space //exclude '/0' return sub_size; } /****************************************************************** * Function : fnGetChksum * Description : get check code from 11 bytes in short file name * Input : * BYTE *shortname-address of short file name * Return : BYTE check code *******************************************************************/ BYTE fnGetChksum(BYTE *shortname) { BYTE i,j=0; BYTE chksum=0; for (i=11; i>0; i--) chksum = ((chksum & 1) ? 0x80 : 0) + (chksum >> 1) + shortname[j++]; return chksum; }
/****************************************************************** * Function : fnFindFile_LongName * Description : get long file name pointer * Input : * DWORD sector_num-sector number that contain file entry * WORD item-entry number of file entry in current sector * DWORD up_folder-starting sector of up directory * BYTE *String_buffer- size of file name * FILE_t *file-file pointer * Return : none *******************************************************************/ void fnFindFile_LongName(DWORD sector_num,WORD item,DWORD up_folder,BYTE *String_buffer,WORD name_size,FILE_t *file) { WORD recordoffset=item*32; file->flag |= MODE_OPEN; file->startcluster = (DWORD)fnIDE_SectorWord(recordoffset+0x1A); file->startcluster += ((DWORD)fnIDE_SectorWord(recordoffset+0x14))<<16; file->currentcluster.value =file->startcluster; file->currentcluster.offset = 0;
file->curp = 0; file->type = fnIDE_SectorByte(recordoffset+0x0B); file->filesize = fnIDE_SectorDWORD(recordoffset+0x1C); memcpy(file->filename,String_buffer,name_size); file->filename[name_size]=0; file->listp=sector_num*16+item; file->up_folder=up_folder; }
/****************************************************************** * Function : fnFindFile_ShortName * Description : get short file name pointer * Input : * DWORD sector_num-sector number that contain file entry * WORD item-entry number of file entry in current sector * DWORD up_folder-starting sector of up directory * BYTE *String_buffer- size of file name * FILE_t *file-file pointer * Return : none *******************************************************************/ void fnFindFile_ShortName(DWORD sector_num,BYTE item,DWORD up_folder,FILE_t *file) { BYTE i,j=0; BYTE temp; WORD recordoffset=item*32; file->flag |= MODE_OPEN; file->startcluster = (DWORD)fnIDE_SectorWord(recordoffset+0x1A); file->startcluster += ((DWORD)fnIDE_SectorWord(recordoffset+0x14))<<16; file->currentcluster.value =file->startcluster; file->currentcluster.offset = 0; file->curp = 0; file->type = fnIDE_SectorByte(recordoffset+0x0B); file->filesize = fnIDE_SectorDWORD(recordoffset+0x1C); for(i=0;i<8;i++) { temp = fnIDE_SectorByte(recordoffset+i); if(temp!=0x20) { file->filename[i] = __tolower(temp); } else { break; } } if(fnIDE_SectorByte(recordoffset+8)!=0x20) { file->filename[i]='.'; i++; for(j=0;j<3;j++) { temp = fnIDE_SectorByte(recordoffset+8+j); if(temp!=0x20) { file->filename[i+j] = __tolower(temp); } else { file->filename[i+j] = '\0'; break; } } } else { file->filename[i]='\0'; } file->filename[i+j] = '\0'; file->listp=sector_num*16+item; file->up_folder=up_folder; return; } /****************************************************************** * Function : fnDetectDirectory * Description : get numbers of files and directores in current directory * Input : * DWORD startcluster-starting sector of curret directory * Return :DWORD amount of files and directories *******************************************************************/ DWORD fnDetectDirectory(DWORD startcluster) { BYTE item; WORD recordoffset; DWORD x=0; BYTE stringnum=0; DWORD filenum=0; currentcluster_t current_cluster; current_cluster.value=startcluster; current_cluster.offset=0; while (current_cluster.value!= 0xFFFFFFFF) // Do while not end of cluster chain { // Read Sector current_cluster = fnFAT32_SectorReader(current_cluster, x++);
if (current_cluster.value!=0xFFFFFFFF) { for (item=0; item<=15;item++) { recordoffset = (32*item); if ( fnFATMisc_If_LFN_Exists(recordoffset,stringnum) ) { filenum++; //File / Dir Count } else if ( fnFATMisc_If_noLFN_SFN_Only(recordoffset) ) { filenum++; //File / Dir Count } }// end of for } } return filenum; }
/****************************************************************** * Function : fnListDirectory * Description : open a directory, get all file pointers of all files in the directory and store them in FILELIST_t. * Input : * DWORD startcluster-starting sector of curret directory * Return :FILELIST_t file list pointer *******************************************************************/ FILELIST_t* fnListDirectory(DWORD startcluster) { BYTE i,item,index; WORD recordoffset; BYTE LFNIndex=0; DWORD x=0; currentcluster_t current_cluster; BYTE stringnum=0,next_num=0; BYTE chksum; DWORD filenumber=0; BYTE String_buffer[20*13]; BYTE short_name[11]; WORD name_size=0; current_cluster.value=startcluster; current_cluster.offset=0; FILELIST_t *filelist=NULL; //get numbers of files in current directory filenumber = fnDetectDirectory(startcluster); filelist=(FILELIST_t *)malloc(sizeof(FILELIST_t)); filelist->list=(FILE_t **)malloc(sizeof(FILE_t *)*(filenumber)); filelist->num=filenumber; if(filenumber==0) { return NULL; } filenumber=0; while (current_cluster.value!= 0xFFFFFFFF) // Do while not end of cluster chain { // Read Sector current_cluster = fnFAT32_SectorReader(current_cluster, x++);
if (current_cluster.value!=0xFFFFFFFF) { LFNIndex=0; for (item=0; item<=15;item++) { recordoffset = (32*item); //check entry type if ( fnFATMisc_If_LFN_Invalid(recordoffset) ) { //invalid entry stringnum = 0; name_size = 0; next_num =0 ; continue; } // Long File Name Text Found else if ( fnFATMisc_If_LFN_TextOnly(recordoffset) ) { // if file name entry if(stringnum==0) { //check last entry by checking bit-7, first byte in file name entry if((fnIDE_SectorByte(recordoffset)&0x40)!=0) { LFNIndex =fnIDE_SectorByte(recordoffset)&0x1F; stringnum = LFNIndex; next_num = stringnum; chksum = fnIDE_SectorByte(recordoffset+0x0D); } else { // do nothing if bit-7 is not '1'. continue; } } else { // check file name serial number and check code, correct-get file name charaters, error-reset with 0 if(((fnIDE_SectorByte(recordoffset)&0x1F)==next_num)&&(fnIDE_SectorByte(recordoffset+0x0D)==chksum)) { LFNIndex =(fnIDE_SectorByte(recordoffset)&0x1F); } else { stringnum = 0; name_size = 0; next_num =0 ; continue; } } name_size += fnFATMisc_cacheLFN(recordoffset,LFNIndex,String_buffer); next_num--; } // Normal Entry and Long text exists else if ( fnFATMisc_If_LFN_Exists(recordoffset,stringnum) ) { filelist->list[filenumber]=(FILE_t*)malloc(sizeof(FILE_t)); fnIDE_SectorData(recordoffset,short_name,11); // check file name serial number and check code, correct-get long file name charaters, error-get short file name if((next_num!=0)||(chksum!=fnGetChksum(short_name))) fnFindFile_ShortName(x-1,item,startcluster,filelist->list[filenumber]); else fnFindFile_LongName(x-1,item,startcluster,String_buffer,name_size,filelist->list[filenumber]); filenumber++; stringnum = 0; name_size = 0; next_num =0 ; } // Normal Entry, only 8.3 Text else if ( fnFATMisc_If_noLFN_SFN_Only(recordoffset) ) { filelist->list[filenumber]=(FILE_t*)malloc(sizeof(FILE_t)); fnFindFile_ShortName(x-1,item,startcluster,filelist->list[filenumber]); filenumber++; stringnum = 0; name_size = 0; next_num =0 ; } }// end of for } } return filelist; }
/****************************************************************** * Function : fnFindFile * Description : search a file or directory. * Input : * DWORD startcluster-starting sector of curret directory * BYTE* filename-target file name * BYTE mode -file type: file or directory * Return :FILE_t - file pointer if found, or none *******************************************************************/ FILE_t *fnFindFile(DWORD startcluster,BYTE *filename,BYTE mode) { BYTE i,item,index; WORD recordoffset; BYTE LFNIndex=0; DWORD x=0; currentcluster_t current_cluster; BYTE stringnum=0,next_num=0; BYTE chksum; DWORD filenumber=0; BYTE String_buffer[20*13]; BYTE short_name[11]; WORD name_size=0; FILE_t *fp; current_cluster.value = startcluster; current_cluster.offset = 0; fp = (FILE_t*)malloc(sizeof(FILE_t)); fp->flag=0; // while (current_cluster.value!= 0xFFFFFFFF) // Do while not end of cluster chain { // Read Sector current_cluster = fnFAT32_SectorReader(current_cluster, x++);
if (current_cluster.value!=0xFFFFFFFF) { LFNIndex=0; for (item=0; item<=15;item++) { recordoffset = (32*item); //check entry type if ( fnFATMisc_If_LFN_Invalid(recordoffset) ) { // check file name, reset with 0 if invalid stringnum = 0; name_size = 0; next_num =0 ; continue; } // Long File Name Text Found else if ( fnFATMisc_If_LFN_TextOnly(recordoffset) ) { //if long file name entry if(stringnum==0) { //check last entry by checking bit-7, first byte in file name entry if((fnIDE_SectorByte(recordoffset)&0x40)!=0) { LFNIndex =fnIDE_SectorByte(recordoffset)&0x1F; stringnum = LFNIndex; next_num = stringnum; chksum = fnIDE_SectorByte(recordoffset+0x0D); } else { continue; } } else { if(((fnIDE_SectorByte(recordoffset)&0x1F)==next_num)&&(fnIDE_SectorByte(recordoffset+0x0D)==chksum)) { LFNIndex =(fnIDE_SectorByte(recordoffset)&0x1F); } else { stringnum = 0; name_size = 0; next_num =0 ; continue; } } name_size += fnFATMisc_cacheLFN(recordoffset,LFNIndex,String_buffer); next_num--; } // Normal Entry and Long text exists else if ( fnFATMisc_If_LFN_Exists(recordoffset,stringnum) ) { //check search mode and entry type matched or not. if(((fnIDE_SectorByte(recordoffset+0x0B)&FILE_ATTR_DIRECTORY)==0&&mode==FIND_FILE_MODE)|| ((fnIDE_SectorByte(recordoffset+0x0B)&FILE_ATTR_DIRECTORY)!=0&&mode==FIND_DIR_MODE)|| (mode==FIND_ALL_MODE)) { fnIDE_SectorData(recordoffset,short_name,11); if((next_num!=0)||(chksum!=fnGetChksum(short_name))) fnFindFile_ShortName(x-1,item,startcluster,fp); else fnFindFile_LongName(x-1,item,startcluster,String_buffer,name_size,fp); filenumber++; stringnum = 0; name_size = 0; next_num =0 ; i=0; while(1) { if(__tolower(filename[i])!=__tolower(fp->filename[i])) { break; } if(filename[i]=='\0') { return fp; } i++; } } } // Normal Entry, only 8.3 Text else if ( fnFATMisc_If_noLFN_SFN_Only(recordoffset) ) { if(((fnIDE_SectorByte(recordoffset+0x0B)&FILE_ATTR_DIRECTORY)==0&&mode==FIND_FILE_MODE)|| ((fnIDE_SectorByte(recordoffset+0x0B)&FILE_ATTR_DIRECTORY)!=0&&mode==FIND_DIR_MODE)|| (mode==FIND_ALL_MODE)) { fnFindFile_ShortName(x-1,item,startcluster,fp); filenumber++; i=0; while(1) { if(__tolower(filename[i])!=__tolower(fp->filename[i])) { break; } if(filename[i]=='\0') { return fp; } i++; } stringnum = 0; name_size = 0; next_num =0 ; } } }// end of for } } free(fp); return fp; }
/****************************************************************** * Function : fnReadFile * Description : read a file into data buffer * Input : * BYTE *buffer-data buffer addess * BYTE size-size of data entry * DWORD count -number of data entry * FILE_t *fp-file pointer * Return :DWORD count of reading data *******************************************************************/ DWORD fnReadFile(BYTE *buffer, BYTE size, DWORD count, FILE_t *fp) {
DWORD read_num; DWORD offset,sp1,sp2,length; DWORD bytepercluster = current_fs->byte_per_cluster; DWORD bytepersector = current_fs->bpb.byte_per_sector; BYTE *rbuffer; DWORD remain; rbuffer=buffers.currentsector.u8data; //which sector *fp locates offset=fp->curp/bytepersector;
//sp1 is starting address of target sector sp1=fp->curp-offset*bytepersector; read_num=size*count; //counting reading data, cut data if overflow if((read_num+fp->curp)>fp->filesize) { read_num=fp->filesize-fp->curp; } //length: numbers of Byte will be read next operation //if length more than one sector, cut length or do next reading operation? if(read_num>bytepersector-sp1) { length=bytepersector-sp1; } else { length=read_num; } //start reading data, follow 3 cases //case1-start sector-target data start is not the start of the sector //case2-reading data-target data is a whole data sector //case3-end sector-target data is not the ead of the sector //case1-read the first sector fp->currentcluster = fnFAT32_SectorReader(fp->currentcluster,offset); memcpy(buffer,rbuffer+sp1,length); fp->curp=fp->curp+length; remain=read_num-length; sp2 = length; offset = offset +1; if(remain==0) return read_num; //case2 while(remain>bytepersector) { fp->currentcluster = fnFAT32_SectorReader(fp->currentcluster,offset); memcpy(buffer+sp2,rbuffer,bytepersector); fp->curp = fp->curp+bytepersector; //sp1=(fp->curp%bytepercluster)%bytepersector; sp2 += bytepersector; remain =remain-bytepersector; offset = offset+1; } //case3 fp->currentcluster = fnFAT32_SectorReader(fp->currentcluster,offset); memcpy(buffer+sp2,rbuffer,remain); fp->curp=fp->curp+remain; return read_num; } /****************************************************************** * Function : fnFreeFile * Description : Free a file(free the chain) when the target file is O_TRUNC and O_WRONLY * Input : * DWORD startcluster -start sector of the file * Return :none *******************************************************************/ void fnFreeFile(DWORD startcluster) { DWORD cluster_chain; DWORD cluster_temp; if(startcluster==0) return; cluster_chain=startcluster; while (cluster_chain!=0xFFFFFFFF) { cluster_temp=fnFAT32_FindNextCluster(cluster_chain); fnFAT32_EditFat(cluster_chain,0x00000000); cluster_chain=cluster_temp; } }
/****************************************************************** * Function : fnOpenFile * Description : after get file pointer via finFindFile, open a file * Input : * FILE_t *fp-file pointer * BYTE mode-open mode * Return :FILE_t *p *******************************************************************/ FILE_t * fnOpenFile(FILE_t* fp,BYTE mode) { DWORD cluster_chain=0; DWORD cluster_temp=0; DWORD i; // check file properties if((fp->type&FILE_ATTR_HIDDEN)||(fp->type&FILE_ATTR_SYSTEM)||(fp->type&FILE_ATTR_SYSHID) ||(fp->type&FILE_ATTR_VOLUME_ID )) { return 0; } //can not open read-only file by open mode-writable else if(fp->type&FILE_ATTR_READ_ONLY) { if((mode&O_WRONLY)||(mode&O_RDWR)) { return 0; } } else { //initial operation on open mode if((mode&O_TRUNC)&&(mode&O_WRONLY)) { fnFreeFile(fp->startcluster); fp->startcluster=0; fp->currentcluster.value=0; fp->currentcluster.offset=0; fp->curp=0; fp->filesize = 0; } if(mode&O_APPEND) { if(fp->filesize!=0) { fp->curp = fp->filesize; cluster_temp=fp->startcluster; i=0; while (cluster_temp!=0xFFFFFFFF) { cluster_chain=cluster_temp; cluster_temp=fnFAT32_FindNextCluster(cluster_chain); i++; } fp->currentcluster.value = cluster_chain; fp->currentcluster.offset = i-1; } } } return fp; }
/****************************************************************** * Function : fnWriteFile * Description : write a data section from data buffer to target file * Input : * BYTE *buffer-data buffer address * BYTE size-data unit size * DWORD count-number of data unit-data section size * FILE_t *fp-file pointer * Return :DWORD wrote data section size *******************************************************************/ DWORD fnWriteFile(BYTE *buffer, BYTE size, DWORD count, FILE_t *fp) { DWORD write_num=size*count; DWORD offset,offset1,sp1,sp2,length; DWORD bytepercluster = current_fs->bpb.byte_per_sector*current_fs->bpb.sector_per_cluster; WORD bytepersector = current_fs->bpb.byte_per_sector; BYTE *wbuffer; DWORD remain_write,remain_place; DWORD cluster_temp; DWORD old_filesize=fp->filesize; wbuffer=buffers.currentsector.u8data; //get sector number that contain the current file offset=fp->curp/bytepersector; //get offest of current sector in current clustor offset1= offset%current_fs->bpb.sector_per_cluster;
//modify file size if it overflows if(fp->curp+write_num>fp->filesize) { fp->filesize=fp->curp+write_num; } //get starting address of writing sp1=fp->curp-offset*bytepersector;//(fp->curp%bytepercluster)%bytepersector;
//get starting address of buffer sp2=0;
//remain_write: left mumber of bytes which not be writtin in buffer remain_write=write_num;
//remain_place: left space in current cluster remain_place=bytepercluster-fp->curp%bytepercluster; while(1) { //read in source sector if(fp->curp<old_filesize) { fp->currentcluster = fnFAT32_SectorReader(fp->currentcluster,offset); } //length: mumber of bytes in one copy operation length=remain_write; if(length>bytepersector-sp1) { length=bytepersector-sp1; } //create a new cluster if length > main_place or current custer is invalid if((length>remain_place)&&(fp->currentcluster.value==0xFFFFFFFF)) { fp->currentcluster.value = fnFAT32_NextEmptyCluster(cluster_temp);
//modify the size of file if fail in creating a new cluster, return if(fp->currentcluster.value==0xFFFFFFFF) { if(fp->filesize>old_filesize) { fp->filesize=fp->curp; } return sp2; } //在FAT_buffer中修改簇链 fnFAT32_EditFatChain(cluster_temp,fp->currentcluster.value); fnFAT32_EditFatChain(fp->currentcluster.value,0x0FFFFFFF); remain_place +=bytepercluster; } memcpy(wbuffer+sp1,buffer+sp2,length); //stop_cycle(); fp->currentcluster=fnFAT32_WriteSector(fp->currentcluster,offset); //enable_cycle(); offset++; offset1++; fp->curp = fp->curp+length; sp1=0;//(fp->curp%bytepercluster)%bytepersector; sp2 += length; if(sp2>=write_num) break; remain_write -=length; remain_place -=length; if(offset1 == current_fs->bpb.sector_per_cluster) { offset1 = 0; cluster_temp=fp->currentcluster.value; fp->currentcluster.value=fnFAT32_FindNextCluster(fp->currentcluster.value); fp->currentcluster.offset++; } } //refresh FAT fnFAT32_UpdateFAT(fp->currentcluster.value); //refresh file directory fnUpdateFILE(fp); return write_num; //} }
/****************************************************************** * Function : fnDeleteFileLabel * Description : remove dedicated file units in previous sector * Input : * FILE_t *fp-file pointer * Return :BYTE number of removed file units *******************************************************************/
BYTE fnDeleteFileLabel(FILE_t *fp) { int label=fp->listp%16; DWORD offset=fp->listp/16; BYTE label_num1=0; currentcluster_t current_cluster={fp->up_folder,0};
fnFAT32_SectorReader(current_cluster,offset); //insert remove flag fnIDE_WriteSectorByte(label*32,0xE5); while(1) { // return label_num1 if go to the end of current directory if(label==0&&offset==0) { return label_num1; } label--; //do following stuffs when label reach to previous sector //write current sector and read previous sector, keep searching
if(label<0) { fnFAT32_WriteSector(current_cluster,offset); offset--; label=15; fnFAT32_SectorReader(current_cluster,offset); } //delete previous label if it is valid file name unit. if((fnIDE_SectorByte(label*32)!=0xE5)&&(fnIDE_SectorByte(label*32+0x0B)==0x0F)) { label_num1++; fnIDE_WriteSectorByte(label*32,0xE5); } else { break; } } //write back last modified sector fnFAT32_WriteSector(current_cluster,offset); return label_num1; }
/****************************************************************** * Function : fnFindEmptyLabel * Description : search empty file units to store record of a new created file in up folder * Input : * DWORD startcluster -start sector of file * BYTE n - number of units in long file name * Return :WORD label offset *******************************************************************/
WORD fnFindEmptyLabel(DWORD startcluster,BYTE n) { DWORD labe_per_cluster=current_fs->bpb.sector_per_cluster*16; WORD label_offset=0; WORD sector_offset=0; BYTE idle_label=0; DWORD next_cluster; currentcluster_t current_cluster={startcluster,0}; while(1) { if(label_offset%16==0) { //get next secotr current_cluster=fnFAT32_SectorReader(current_cluster,sector_offset); //create a new cluster for up folder if get no next sector if(current_cluster.value==0xFFFFFFFF) { next_cluster=fnFAT32_NextEmptyCluster(current_cluster.value); if(next_cluster==0xFFFFFFFF) { return 0xFFFF; } fnFAT32_EditFatChain(current_cluster.value,next_cluster); fnFAT32_EditFatChain(next_cluster,0x0FFFFFFF); current_cluster.value=next_cluster; } sector_offset++; }
if((fnIDE_SectorByte(label_offset%16*32)==0xE5)||(fnIDE_SectorByte(label_offset%16*32)==0x00)) { idle_label++; } else { idle_label=0; } if(idle_label>n) { break; } label_offset++; }
fnFAT32_UpdateFAT(current_cluster.value); return label_offset; }
/****************************************************************** * Function : fnWriteFileLabel * Description : write file infor. to up folder * Input : * FILE_t *fp - file pointer * file_lable_t - address of file infor. unit buffer * int label - address of file infor. unit * int label_num - number of long file name infor. unit * Return :BYTE 1 or 0-error *******************************************************************/
BYTE fnWriteFileLabel(FILE_t *fp,file_label_t *buffer,int label,int label_num) { WORD i,j,label_count=0,sector_offset=label/16; int label_offset=label%16; lfn_label_t *lfn_buffer; BYTE chksum; BYTE data_buffer[32]; BYTE name_len=strlen(fp->filename); currentcluster_t current_cluster={fp->up_folder,0}; lfn_buffer=(lfn_label_t *)malloc(sizeof(lfn_label_t)); fnFAT32_SectorReader(current_cluster,sector_offset);
fnIDE_WriteSectorData(label_offset*32,(BYTE *)buffer,32); if(label_num==0) { fnFAT32_WriteSector(current_cluster,sector_offset); free(lfn_buffer); return 1; } chksum=fnGetChksum(buffer->short_name);
while(1) { label_offset--; if(label_offset<0) { sector_offset--; label_offset=15; fnFAT32_WriteSector(current_cluster,sector_offset+1); fnFAT32_SectorReader(current_cluster,sector_offset); } i=13*label_count; for(j=0;j<5;j++) { if(i==name_len) { lfn_buffer->name1[j]=0x0000; i++; } else if(i>name_len) { lfn_buffer->name1[j]=0xFFFF; } else { lfn_buffer->name1[j]=(WORD)fp->filename[i++]; } } for(j=0;j<6;j++) { if(i==name_len) { lfn_buffer->name2[j]=0x0000; i++; } else if(i>name_len) { lfn_buffer->name2[j]=0xFFFF; } else { lfn_buffer->name2[j]=(WORD)fp->filename[i++]; } } for(j=0;j<2;j++) { if(i==name_len) { lfn_buffer->name3[j]=0x0000; i++; } else if(i>name_len) { lfn_buffer->name3[j]=0xFFFF; } else { lfn_buffer->name3[j]=(WORD)fp->filename[i++]; } } if(label_count==label_num-1) { lfn_buffer->num=(label_count+1)|0x40; } else { lfn_buffer->num=(label_count+1); } lfn_buffer->flag=0x0F; lfn_buffer->reserve=0; lfn_buffer->chksum=chksum; lfn_buffer->startcluster=0; data_buffer[0]=lfn_buffer->num; memcpy(data_buffer+1,lfn_buffer->name1,13); memcpy(data_buffer+14,lfn_buffer->name2,18); fnIDE_WriteSectorData(label_offset*32,data_buffer,32); if(label_count==label_num-1) { break; } label_count++; } fnFAT32_WriteSector(current_cluster,sector_offset); free(lfn_buffer); return 1; }
/****************************************************************** * Function : fnGetShortNum * Description : number files which have same short file names * Input : * FILE_t *fp - file pointer * BYTE *short_name - short file name * Return :BYTE serial number *******************************************************************/
BYTE fnGetShortNum(FILE_t *fp,BYTE *short_name) { BYTE item; WORD recordoffset=0; DWORD x=0; BYTE name[11]; BYTE num=1,temp;; BYTE refind=0; currentcluster_t current_cluster={fp->up_folder,0}; while (current_cluster.value!= 0xFFFFFFFF) // Do while not end of cluster chain { // Read Sector current_cluster = fnFAT32_SectorReader(current_cluster, x++);
if (current_cluster.value!=0xFFFFFFFF) { for (item=0; item<=15;item++) { recordoffset = (32*item); if(((x*16+item)!=fp->listp)&&(fnIDE_SectorByte(recordoffset)!=0xE5)) { fnIDE_SectorData(recordoffset,name,11); if(strncmp(short_name+8,name+8,3)!=0) continue; if((strncmp(short_name,name,4)==0)&&(name[4]=='~')) { temp=num%100; if((name[5]==(num/100+'0'))&&(name[6]==(temp/10+'0'))&&(name[7]==(temp%10+'0'))) { num++; refind=1; break; } } } } } if(refind==1) { refind=0; current_cluster.value=fp->up_folder; current_cluster.offset=0; x=0; } } return num; }
/****************************************************************** * Function : fnUpdateFILE * Description : update file infor. including file name, file size, etc * Input : * FILE_t *fp - file pointer * Return :BYTE 1 *******************************************************************/
BYTE fnUpdateFILE(FILE_t *fp) { int i,j; file_label_t *buffer; BYTE short_name[11]=" "; BYTE ext[256]=" "; BYTE name[256]; int label_num1,label_num2,label,temp; DWORD offset; BYTE type=0; //type = 0 - normal short //type =1 - normal long //type=2 - short, caps //type=3 - short, blank currentcluster_t currentcluster={fp->up_folder,0}; buffer=(file_label_t *)malloc(sizeof(file_label_t)); fnFAT32_SectorReader(currentcluster,fp->listp/16); fnIDE_SectorData((fp->listp%16)*32,(BYTE *)buffer,32);
//remove original file directory label_num1=fnDeleteFileLabel(fp);
//get file name and extended file name for(i=strlen(fp->filename);i>0;i--) { if(fp->filename[i]=='.') { memcpy(ext,fp->filename+i+1,strlen(fp->filename)-i); memcpy(name,fp->filename,i); name[i]='\0'; break; } } if(i==0) { memcpy(name,fp->filename,strlen(fp->filename)+1); }
//get file type if((strlen(name)<=8)&&(strlen(ext)<=3)) { type=0; label_num2=0; for(i=0;name[i]!='\0';i++) { if((name[i]<='Z'&&name[i]>='A')) { type=2; label_num2=1; break; } if(name[i]==' '||name[i]=='.') { type=3; label_num2=1; break; } } for(i=0;ext[i]!='\0';i++) { if((ext[i]<='Z'&&ext[i]>='A')) { type=2; label_num2=1; break; } } } else { label_num2=(strlen(fp->filename)-1)/13+1; type=1; } //get file starting if(label_num2>label_num1) { label=fnFindEmptyLabel(fp->up_folder,label_num2); fp->listp=label; } else { label=fp->listp; } //get short file name with 'type' switch(type) { case 0: case 2: { memcpy(short_name,name,strlen(name)); memcpy(short_name+8,ext,strlen(ext)); for(i=0;i<11;i++) { if(short_name[i]!=' ') { if(short_name[i]<='z'&&short_name[i]>='a') short_name[i]=short_name[i]-0x20; } } break; } case 1: case 3: { if(strlen(ext)<=3) { memcpy(short_name+8,ext,strlen(ext)); } else { memcpy(short_name+8,ext,3); } for(i=0,j=0;i<strlen(name);i++) { if(name[i]==' '||name[i]=='.') continue; short_name[j]=__toupper(name[i]); j++; if(j==4) break; } for(i=0,j=8;i<strlen(ext);i++) { if(ext[i]==' '||ext[i]=='.') continue; short_name[j]=__toupper(ext[i]); j++; if(j==11) break; } temp=fnGetShortNum(fp,short_name); short_name[4]='~';
short_name[5]=temp/100+'0'; temp=temp%100; short_name[6]=temp/10+'0'; short_name[7]=temp%10+'0'; for(i=0;i<11;i++) { if(short_name[i]!=' ') { if(short_name[i]<='z'&&short_name[i]>='a') short_name[i]=short_name[i]-0x20; } } break; } }
//handle '.' &'..' directories if(strcmp(fp->filename,".")==0||strcmp(fp->filename,"..")==0) { for(i=0;i<11;i++) short_name[i]=0x20; memcpy(short_name,fp->filename,strlen(fp->filename)+1); label_num2=0; label=label-1; } memcpy(buffer->short_name,short_name,11); buffer->type = fp->type; buffer->filesize=fp->filesize; buffer->cluster_high=(WORD)fp->startcluster>>16; buffer->cluster_low=(WORD)fp->startcluster; buffer->create_time_10ms = 0; buffer->create_time = 0; buffer->create_date = 0; buffer->last_visit_date = 0; buffer->last_edit_time = 0; buffer->last_edit_date = 0;
//write back undated file label to HD driver fnWriteFileLabel(fp,buffer,label,label_num2); free(buffer); return 1; }
/****************************************************************** 创建一个文件 用途: 创建一个文件,赋文件指针 输入: DWORD startcluster 上一级目录起始扇区 BYTE *name 文件名 输出: FILE_t * 文件指针 *********************************************************************/ FILE_t *fnCreateFile(DWORD startcluster,BYTE *name) { FILE_t *fp; fp=(FILE_t *)malloc(sizeof(FILE_t)); fp->listp=fnFindEmptyLabel(startcluster,0); if(fp->listp==0xFFFF) { return NULL; } fp->flag=MODE_OPEN; fp->startcluster=0;//=fnFAT32_NextEmptyCluster(2); //fnFAT32_EditFat(fp->startcluster,0x0FFFFFFF); fp->curp =0; memcpy(fp->filename,name,strlen(name)+1); fp->type = 0x20; fp->filesize =0; fp->up_folder = startcluster; fnUpdateFILE(fp);
return fp; }
/****************************************************************** 创建一个目录 用途: 创建一个目录 输入: DWORD startcluster 上一级目录起始扇区 BYTE *name 文件名 输出: void ******************************************************************/ BYTE fnCreateDir(DWORD startcluster,BYTE *name) { FILE_t *fp; DWORD current_cluster; fp=(FILE_t *)malloc(sizeof(FILE_t)); fp->listp=fnFindEmptyLabel(startcluster,0); if(fp->listp==0xFFFF) { return 0; } fp->flag=0; fp->startcluster=fnFAT32_NextEmptyCluster(2); fnFAT32_EditFat(fp->startcluster,0x0FFFFFFF); current_cluster= fp->startcluster; fp->curp =0; memcpy(fp->filename,name,strlen(name)+1); fp->type = FILE_ATTR_DIRECTORY; fp->filesize =0; fp->up_folder = startcluster; fnUpdateFILE(fp); fp->listp=fnFindEmptyLabel(current_cluster,0); if(fp->listp==0xFFFF) { return 0; } fp->flag=0; fp->startcluster=current_cluster; fp->curp =0; memcpy(fp->filename,".",2); fp->type = FILE_ATTR_DIRECTORY; fp->filesize =0; fp->up_folder = current_cluster; fnUpdateFILE(fp); fp->listp=fnFindEmptyLabel(current_cluster,0); if(fp->listp==0xFFFF) { return 0; } fp->flag=0; fp->startcluster=startcluster; fp->curp =0; memcpy(fp->filename,"..",3); fp->type = FILE_ATTR_DIRECTORY; fp->filesize =0; fp->up_folder = current_cluster; fnUpdateFILE(fp);
free(fp); return 1; }
/****************************************************************** * Function : fnSearchFile * Description : search files in dedicated directories (recursive function) * Input : * DWORD startcluster - starting sector of dedicated directory * BYTE *name - file name * BYTE level - directories depth * BYTE *num - number of searched files * FILELIST_t *fl - searched files in file list * Return :void *******************************************************************/
void fnSearchFile(DWORD startcluster,BYTE * name,BYTE level,BYTE *num,FILELIST_t *fl) { DWORD i=0,j=0; FILE_t *fp; FILELIST_t *filelist; fp=(FILE_t *)malloc(sizeof(FILE_t)); if(level>5) { //do five level search here return; }
//get files and directory infor. in current direcotry filelist=fnListDirectory(startcluster); while(i<filelist->num) { //do nothing with '.' & '..' direcotries if((strcmp(filelist->list[i]->filename,".")==0)||(strcmp(filelist->list[i]->filename,"..")==0)) { i++; continue; } //do recursion to directory here if(filelist->list[i]->type&FILE_ATTR_DIRECTORY) { fnSearchFile(filelist->list[i]->startcluster,name,level,num,fl); } else { j=0; while(1) { //compare every character of file name, break is error or reach to end of file name if(__tolower(filelist->list[i]->filename[j])!=__tolower(name[j])) { break; } if(filelist->list[i]->filename[j]=='\0') { break; } j++; } //list file names if matched if((filelist->list[i]->filename[j]=='\0')&&(name[j]=='\0')) { if(*num>=255) { break; } memcpy(fp,filelist->list[i],sizeof(FILE_t)); fl->list[*num]=fp; *num=(*num)+1; } else { i++; continue; }
} i++; } for(i=0;i<filelist->num;i++) { free(filelist->list[i]); } free(filelist->list); free(filelist); __fclose(fp); return; }
/****************************************************************** * Function : fnGetCurrentCluster * Description : get current cluster * Input : * DWORD curp - file operating pointer * DWORD startcluster - starting cluster * Return :currentcluster_t - current cluster *******************************************************************/ currentcluster_t fnGetCurrentCluster(DWORD curp,DWORD startcluster) { DWORD i; DWORD cluster_chain=startcluster; DWORD offset=curp/(current_fs->bpb.byte_per_sector*current_fs->bpb.sector_per_cluster); currentcluster_t cluster; for(i=0;i<offset;i++) { cluster_chain=fnFAT32_FindNextCluster(cluster_chain); if(cluster_chain==0xFFFFFFFF) break; } cluster.value = cluster_chain; cluster.offset = i; return cluster; }
|