📄 dir.c
字号:
//###########################################################
// File: dir.c
//
// For FAT12, FAT16 and FAT32
// FAT32 not tested yet
// Only for first Partition
// Only for drives with 512 bytes per sector (the most)
//
//#########################################################################
// Last change: 09.11.2003
//#########################################################################
// holger.klabunde@t-online.de
// http://home.t-online.de/home/holger.klabunde/homepage.htm
//#########################################################################
// Compiler: AVR-GCC 3.2
//#########################################################################
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "protos.h"
#include "dos.h"
#include "mydefs.h"
#include "serial.h"
/*
unsigned char MakeDir(char *name)
{
//MakeFilename
//Test if directoryname exists in currentdir
//if directory exist return success
//MakeNewDirentry
//AllocCluster for new dir
//Cluster allocated ? if not return no_success
//clean all sectors of cluster (fill with 0x00)
//insert "." my new dir entry
//insert ".." upper dir entry
//return success
}
*/
//###########################################################
unsigned char ChangeDir(char *name)
//###########################################################
{
if(FindName(name)==FULL_MATCH) return F_OK;
else return F_ERROR;
}
//###########################################################
unsigned char MakeNewFileEntry(void)
//###########################################################
{
unsigned long tmpsector,tmpcluster,lastdircluster;
unsigned int i;
unsigned char result;
if(CurrentDirCluster<2) result=SearchRootDir();
else result=SearchSubDir(CurrentDirCluster);
if(result==0)
{
//if dir is rootdir (FAT12/16 only) you have a problem ;)
if(CurrentDirCluster<2 && (FATtype==FAT12 || FATtype==FAT16) )
{
#ifdef F_DEBUG
puts("Rootdir is full !\n");
#endif
return F_ERROR;
}
//search the last cluster of directory
lastdircluster=CurrentDirCluster;
do
{
tmpcluster=GetNextClusterNumber(lastdircluster);
if(tmpcluster < endofclusterchain) lastdircluster=tmpcluster;
}while(tmpcluster < endofclusterchain);
tmpcluster=AllocCluster(lastdircluster); //if currentdir is full alloc new cluster for dir
if(tmpcluster==DISK_FULL) //no free clusters ?
{
#ifdef F_DEBUG
puts("No free cluster for directory !\n");
#endif
return F_ERROR;
}
//fill all cluster sectors with zero
for(i=0; i<BYTE_PER_SEC; i++) inbuff[i]=0; //Fill write buffer
tmpsector=GetFirstSectorOfCluster(tmpcluster);
for(i=0; i<secPerCluster; i++)
{
CFWriteSector(tmpsector,inbuff);
tmpsector++;
}
FileDirOffset=0; //set offset for new direntry in dirsector
FileDirSector=GetFirstSectorOfCluster(tmpcluster);
}
tmpcluster=AllocCluster(0); //alloc first cluster for file
if(tmpcluster==DISK_FULL) //no free clusters ?
{
#ifdef F_DEBUG
puts("No free cluster for file !\n");
#endif
return F_ERROR;
}
FileFirstCluster=tmpcluster;
FileSize=0;
UpdateFileEntry(); //write new file entry
return F_OK; //all ok
}
//###########################################################
unsigned char UpdateFileEntry(void)
//###########################################################
{
struct DirEntry *di;
CFReadSector(FileDirSector,inbuff);
di=(struct DirEntry *)&inbuff[FileDirOffset*32];
strncpy(di->DIR_Name,FileName,8);
strncpy(di->DIR_Ext,FileExt,3);
di->DIR_Attr=ATTR_FILE;
di->DIR_NTres=0;
di->DIR_CrtTimeTenth=0;
//because i have no clock give file a fixed time
di->DIR_CrtTime=(unsigned int)( (19<<11) + (21<<5) ); //creation time
di->DIR_CrtDate=(unsigned int)( (23<<9) + (5<<5) + 10); //creation date
di->DIR_LastAccDate=(unsigned int)( (23<<9) + (5<<5) + 10); //last access date 10.05.2003
di->DIR_WrtTime=(unsigned int)( (19<<11) + (21<<5) ); //last write time 19:21
di->DIR_WrtDate=(unsigned int)( (23<<9) + (5<<5) + 10); //last write date 10.05.2003
di->DIR_FstClusHI=(unsigned int)(FileFirstCluster>>16); //first cluster high word
di->DIR_FstClusLO=(unsigned int)(FileFirstCluster & 0xFFFF); //first cluster low word
di->DIR_FileSize=FileSize;
CFWriteSector(FileDirSector,inbuff);
return F_OK;
}
//###########################################################
//search root dir for free dir entry
unsigned char SearchRootDir(void)
//###########################################################
{
unsigned long i;
unsigned char result;
result=0;
for(i=0; i<RootDirSectors; i++)
{
result=SearchDirSector(FirstRootSector+i);
if(result!=0) break; //break sector loop
}
return result;
}
//###########################################################
//search sub dir for free dir entry
unsigned char SearchSubDir(unsigned long startcluster)
//###########################################################
{
unsigned long tmpsector,tmpcluster;
unsigned char i,result;
tmpcluster=startcluster;
result=0;
while(tmpcluster < endofclusterchain)
{
tmpsector=GetFirstSectorOfCluster(tmpcluster);
for(i=0; i<secPerCluster; i++)
{
result=SearchDirSector(tmpsector+i);
if(result!=0) break; //break sector loop
}
if(result!=0) break; //break cluster loop
tmpcluster=GetNextClusterNumber(tmpcluster);
}
return result;
}
//###########################################################
//search dir sector for free dir entry
unsigned char SearchDirSector(unsigned long sector)
//###########################################################
{
unsigned int count;
CFReadSector(sector,inbuff); //read one directory sector.
count=0;
do
{
if(inbuff[count]==0 || inbuff[count]==0xE5)
{
FileDirSector=sector; //keep some values in mind
FileDirOffset=count/32;
return 1;
}
count+=32;
}while(count<BYTE_PER_SEC);
return 0;
}
//###########################################################
// List dir function (if name==NULL)
// Change to dir or find a filename (if name!=NULL)
//
// Following global variables will be set if dir or filename
// was found:
//
// For directories:
// CurrentDirCluster First cluster of directory
//
// For files:
// FileName 8 chars for filename
// FileExt 3 chars for extension
// FileDirSector Sector which keeps direntry of the file
// FileDirOffset Offset to direntry of the file
// FileFirstCluster First cluster of the dir/file in FAT
// FileSize
unsigned char ScanOneDirectorySector(unsigned long sector, char *name)
//###########################################################
{
unsigned char by,i;
unsigned int count;
unsigned long tmp;
struct DirEntry *di;
struct DirEntryBuffer *dib;
char nam[8];
char ext[3];
unsigned char match;
if(name) //find filename or directory name
{
MakeFileName(name,nam,ext);
}//if(name)
by=CFReadSector(sector,inbuff); //read one directory sector.
count=0;
do
{
match=NO_MATCH;
di=(struct DirEntry *)(&inbuff[count]);
//make a second pointer to inbuff for easier access to long filename entrys
dib=(struct DirEntryBuffer *)di;
if(di->DIR_Name[0]==0) return END_DIR; //end of directory
if(di->DIR_Name[0]!=0xE5 && di->DIR_Name[0]>0)
{
di->DIR_Attr&=0x3F; //smash upper two bits
if(di->DIR_Attr==ATTR_LONG_NAME)
{
#ifdef F_DEBUG
//show parts of long filenames. max. 13 chars per dir entry
//beginning at the *END* of filename :-(
if(lo && name==NULL)
{
puts("L "); //show flag long filename entry
for(i=1; i<=9; i+=2) { by=dib->longchars[i]; if(by<0xFF) putchar(by); }
for(i=14; i<=24; i+=2) { by=dib->longchars[i]; if(by<0xFF) putchar(by); }
for(i=28; i<=30; i+=2) { by=dib->longchars[i]; if(by<0xFF) putchar(by); }
puts("\n");
}
#endif
}
else
{
if(name==NULL) //List only
{
#ifdef F_DEBUG
if(di->DIR_Attr & ATTR_VOLUME_ID) puts("V "); //flag volume
else if(di->DIR_Attr & ATTR_DIRECTORY) puts("D "); //flag directory
else puts("F "); //flag file
for(i=0; i<8; i++) putchar(di->DIR_Name[i]); //show filename
putchar('.');
for(i=0; i<3; i++) putchar(di->DIR_Ext[i]); //show extension
putchar(' ');
if(di->DIR_Attr & ATTR_READ_ONLY) putchar('R'); else putchar('-'); //read only
if(di->DIR_Attr & ATTR_SYSTEM) putchar('S'); else putchar('-'); //system
if(di->DIR_Attr & ATTR_HIDDEN) putchar('H'); else putchar('-'); //hidden
if(di->DIR_Attr & ATTR_ARCHIVE) putchar('A'); else putchar('-'); //archived
#endif
}//if(name==NULL)
else //searching for a filename or a directory name
{
if(strncmp(nam,di->DIR_Name,8)==0) match=MATCH_NAME;
if(strncmp(ext,di->DIR_Ext,3)==0) match+=MATCH_EXT;
#ifdef F_DEBUG
if(echo) { if(match==FULL_MATCH) puts("Found\n"); }
#endif
}
if(di->DIR_Attr & ATTR_VOLUME_ID)
{
#ifdef F_DEBUG
if(name==NULL) puts(" <VOL>\n");
#endif
}
else
{
#ifdef F_DEBUG
if(name==NULL) //List only
{
by=(unsigned char)(di->DIR_WrtDate & 0x001F); //day of month
printf(" %02u.",by);
by=(unsigned char)((di->DIR_WrtDate>>5) & 0x000F); //month
printf("%02u.",by);
by=(unsigned char)(di->DIR_WrtDate>>9); //year since 1980
if(by<20) by+=80; else by-=20;
printf("%02u",by);
by=(unsigned char)(di->DIR_WrtTime>>11); //hour of day
printf(" %02u:",by);
by=(unsigned char)((di->DIR_WrtTime>>5) & 0x003F); //minute
printf("%02u",by);
}//if(name==NULL)
#endif
if(di->DIR_Attr & ATTR_DIRECTORY) //this is a directory
{
tmp=di->DIR_FstClusHI; //Highword of first cluster number
tmp<<=16;
tmp+=di->DIR_FstClusLO; //Lowword of first cluster number
if(name==NULL) //List only
{
#ifdef F_DEBUG
printf(" <DIR> Clu: % 9lu\n",tmp);
#endif
}
else //searching for a directoryname
{
if(match==FULL_MATCH)
{
CurrentDirCluster=tmp;
#ifdef F_DEBUG
if(echo) printf("%lu\n",CurrentDirCluster);
#endif
return FULL_MATCH;
}
}//if(name==NULL)
}//if(di->DIR_Attr & ATTR_DIRECTORY)
else //is not a directory. this is a file
{
tmp=di->DIR_FstClusHI; //Highword of first cluster number
tmp<<=16;
tmp+=di->DIR_FstClusLO; //Lowword of first cluster number
if(name==NULL) //List filenames only
{
#ifdef F_DEBUG
printf(" % 9lu Clu: % 9lu\n",di->DIR_FileSize,tmp);
#endif
}
else //searching for a filename
{
if(match==FULL_MATCH)
{
strncpy(FileName,nam,8);
strncpy(FileExt,ext,3);
FileDirSector=sector; //keep some values in mind
FileDirOffset=count/32;
FileFirstCluster=tmp;
FileSize=di->DIR_FileSize;
#ifdef F_DEBUG
if(echo) printf("%lu\n%lu\n%lu\n%u\n",FileFirstCluster,FileSize,FileDirSector,FileDirOffset);
#endif
return FULL_MATCH;
}
}
}//if(di->DIR_Attr & ATTR_DIRECTORY)
}
}
}//if(di->DIR_Name[0]!=0xE5 && di->DIR_Name[0]>0)
count+=32;
}while(count<BYTE_PER_SEC);
return NO_MATCH;
}
//###########################################################
unsigned char ScanSubDir(unsigned long startcluster, char *name)
//###########################################################
{
unsigned long tmpsector,tmpcluster;
unsigned char i,result;
tmpcluster=startcluster;
result=NO_MATCH;
while(tmpcluster < endofclusterchain)
{
tmpsector=GetFirstSectorOfCluster(tmpcluster);
for(i=0; i<secPerCluster; i++)
{
result=ScanOneDirectorySector(tmpsector+i, name);
if(result!=NO_MATCH) break; //break sector loop
}
if(result!=NO_MATCH) break; //break cluster loop
tmpcluster=GetNextClusterNumber(tmpcluster);
}
if(echo) ser_putc(EOT); //End of Transmission
return(result);
}
//###########################################################
//FAT12/16 only
unsigned char ScanRootDir(char *name)
//###########################################################
{
unsigned long i;
unsigned char result;
result=NO_MATCH;
for(i=0; i<RootDirSectors; i++)
{
result=ScanOneDirectorySector(FirstRootSector+i, name);
if(result!=NO_MATCH) break; //break sector loop
}
if(echo) ser_putc(EOT); //End of Transmission
return(result);
}
//###########################################################
void MakeFileName(char *inname, char *outname, char *outext)
//###########################################################
{
unsigned char by,i,j;
char *po;
po=outname;
for(i=0; i<8; i++) *po++=' '; //fill filename buffers with spaces
po=outext;
*po++=' ';
*po++=' ';
*po =' ';
po=outname;
if(inname[0]=='.' && inname[1]=='.') //change to upper dir
{
*po++='.';
*po ='.';
}
else
{
i=0; //get filename and make it uppercase
do
{
by=inname[i];
if(by!='.' && by!=0) *po++=toupper(by);
i++;
}while(i<8 && by!='.' && by!=0);
//if i < 8 there was a dot or a \0
//if i == 8 there could be a dot or a \0
if(i==8 && by!='.' && by!=0) { by=inname[i]; i++; }
if(by=='.')
{
j=0;
do
{
by=inname[i];
if(by!=0) outext[j]=toupper(by);
j++;
i++;
}while(j<3 && by!=0);
}
}
// for(i=0; i<8; i++) putchar(outname[i]);
// for(i=0; i<3; i++) putchar(outext[i]);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -