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

📄 dir.c

📁 MMC interface and FAT File system
💻 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 + -