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

📄 fatlite.c

📁 M-System DOC(Disk on a Chip) Flash芯片映像读写工具, 可以进行二片Flash芯片的内容互相拷贝, 提高烧录程序的效率.
💻 C
📖 第 1 页 / 共 5 页
字号:
#ifndef FL_READ_ONLY
/*----------------------------------------------------------------------*/
/*                       s e t F A T e n t r y                          */
/*                                                                      */
/* Writes a new value to a given FAT cluster entry.                     */
/*                                                                      */
/* Parameters:                                                          */
/*       vol              : Pointer identifying drive                   */
/*       cluster              : Cluster no. of enrty.                   */
/*       entry              : New value of FAT entry.                   */
/*                                                                      */
/* Returns:                                                             */
/*       FLStatus       : 0 on success, otherwise failed                */
/*----------------------------------------------------------------------*/

static FLStatus setFATentry(Volume vol, unsigned cluster, unsigned entry)
{
  LEushort *fat16Sector;

  unsigned fatSectorNo = vol.firstFATSectorNo;

#ifdef FAT_12BIT
  if (vol.flags & VOLUME_12BIT_FAT)
    fatSectorNo += (cluster * 3) >> (FL_SECTOR_SIZE_BITS + 1);
  else
#endif
    fatSectorNo += cluster >> (FL_SECTOR_SIZE_BITS - 1);

  checkStatus(updateSector(&vol,fatSectorNo,TRUE));
  fat16Sector = (LEushort *) vol.volBuffer.flData;

#ifdef FAT_12BIT
  if (vol.flags & VOLUME_12BIT_FAT) {
    FLByte *fat12Sector = (FLByte *) vol.volBuffer.flData;
    unsigned halfByteOffset = (cluster * 3) & (FL_SECTOR_SIZE * 2 - 1);
    if (halfByteOffset & 1) {
      fat12Sector[halfByteOffset / 2] &= 0xf;
      fat12Sector[halfByteOffset / 2] |= (entry & 0xf) << 4;
    }
    else
      fat12Sector[halfByteOffset / 2] = entry;
    halfByteOffset += 2;
    if (halfByteOffset >= FL_SECTOR_SIZE * 2) {
      /* Entry continues on the next sector. What a mess */
      halfByteOffset -= FL_SECTOR_SIZE * 2;
      fatSectorNo++;
      checkStatus(updateSector(&vol,fatSectorNo,TRUE));
    }
    if (halfByteOffset & 1)
      fat12Sector[halfByteOffset / 2] = entry >> 4;
    else {
      fat12Sector[halfByteOffset / 2] &= 0xf0;
      fat12Sector[halfByteOffset / 2] |= (entry & 0x0f00) >> 8;
    }
  }
  else
#endif
    toLE2(fat16Sector[cluster & (FL_SECTOR_SIZE / 2 - 1)],entry);

  return flOK;
}


/*----------------------------------------------------------------------*/
/*                      a l l o c a t e C l u s t e r                   */
/*                                                                      */
/* Allocates a new cluster for a file and adds it to a FAT chain or     */
/* marks it in a directory entry.                                       */
/*                                                                      */
/* Parameters:                                                          */
/*       vol            : Pointer identifying drive                     */
/*       file           : File to extend. It should be positioned at    */
/*                       end-of-file.                                   */
/*                                                                      */
/* Returns:                                                             */
/*       FLStatus       : 0 on success, otherwise failed                */
/*----------------------------------------------------------------------*/

static FLStatus allocateCluster(File *file)
{
  Volume vol = file->fileVol;
  unsigned originalRover;
  unsigned fatEntry;
  DirectoryEntry *dirEntry;

  if (file->flags & FL_FILE_READ_ONLY)
    return flNoWriteAccess;

  /* Look for a free cluster. Start at the allocation rover */
  originalRover = vol.allocationRover;

  do {
    vol.allocationRover++;
    if (vol.allocationRover >= FL_LAST_VALID_CLUSTER )		
      vol.allocationRover = FL_FIRST_VALID_CLUSTER;       /* wraparound to start of volume */
    if (vol.allocationRover == originalRover)
	{
		if( originalRover != FL_FIRST_VALID_CLUSTER )
			return flNoSpaceInVolume;
		else
		{
			fatEntry = vol.allocationRover;
			checkStatus(getFATentry(&vol,&fatEntry));
			if( fatEntry != FAT_FREE )
				return flNoSpaceInVolume;
			else
				break;
		}
	}

    fatEntry = vol.allocationRover;
    checkStatus(getFATentry(&vol,&fatEntry));
  } while ( fatEntry!= FAT_FREE);


  /* Mark previous cluster or directory to point to it */
  if (file->currentCluster == 0) {
      checkStatus(getDirEntryForUpdate(file,&dirEntry));
    toLE2(dirEntry->startingCluster,vol.allocationRover);
    setCurrentDateTime(dirEntry);
  }

#ifndef FL_NO_SURE_FS_SUPPORT
    if (file->flags & FL_FILE_IS_DIRECTORY) {
      checkStatus(getDirEntryForUpdate(file,&dirEntry));
        checkStatus( setAttentionFlag( &vol, dirEntry, ATTR_SUREFS_GEN_ATTENTION_FLAG));
    }
  else {
    /* For extending file set attantion flag only once        */
    FLByte                            flag;
    const DirectoryEntry FAR0 *entry;
    
    entry = getDirEntry(file);
    if(entry==NULL)
      return flSectorNotFound;
    if(entry==(const DirectoryEntry FAR0 *)dataErrorToken)
      return flDataError;
    
    getAttentionFlag( entry, &flag);
    if (flag == 0) {
      checkStatus(getDirEntryForUpdate(file, &dirEntry));
      checkStatus( setAttentionFlag( &vol, dirEntry, ATTR_SUREFS_GEN_ATTENTION_FLAG));
    }
  }
#endif /* FL_NO_SURE_FS_SUPPORT */

    if (file->currentCluster)
        checkStatus(setFATentry(&vol,file->currentCluster,vol.allocationRover));

  /* Mark found free cluster as an end of chain */
  checkStatus(setFATentry(&vol,vol.allocationRover,FAT_LAST_CLUSTER));

  /* Set our new current cluster */
  file->currentCluster = vol.allocationRover;

  return flOK;
}

#endif /* FL_READ_ONLY  */
/*----------------------------------------------------------------------*/
/*                   g e t S e c t o r A n d O f f s e t                */
/*                                                                      */
/* Based on the current position of a file, gets a sector number and    */
/* offset in the sector that marks the file's current position.         */
/* If the position is at the end-of-file, and the file is opened for    */
/* write, this routine will extend the file by allocating a new cluster.*/
/*                                                                      */
/* Parameters:                                                          */
/*       vol              : Pointer identifying drive                   */
/*                                                                      */
/* Returns:                                                             */
/*       FLStatus       : 0 on success, otherwise failed                */
/*----------------------------------------------------------------------*/

static FLStatus getSectorAndOffset(File *file,
                             SectorNo *sectorNo,
                             unsigned *offsetInSector)
{
  Volume vol = file->fileVol;
  unsigned offsetInCluster =
             (unsigned) file->currentPosition & (vol.bytesPerCluster - 1);

  if (file->flags & FL_FILE_IS_ROOT_DIR) 
  {
    if (file->currentPosition >= file->fileSize)
      return flRootDirectoryFull;
  }

  if (offsetInCluster == 0) {       /* This cluster is finished. Get next */
    if (!(file->flags & FL_FILE_IS_ROOT_DIR)) {
      if (((file->currentPosition >= file->fileSize) && (file->currentPosition>0))||((file->fileSize==0)&&!(file->flags & FL_FILE_IS_DIRECTORY))) {
#ifndef FL_READ_ONLY
        checkStatus(allocateCluster(file));
#else
        return flSectorNotFound;
#endif
      }
      else {
        unsigned nextCluster;
        if (file->currentCluster == 0) {
          const DirectoryEntry FAR0 *dirEntry;
          dirEntry = getDirEntry(file);
          if(dirEntry==NULL)
            return flSectorNotFound;
          if(dirEntry==(const DirectoryEntry FAR0 *)dataErrorToken)
            return flDataError;
          nextCluster = LE2(dirEntry->startingCluster);
        }
       else {
          nextCluster = file->currentCluster;
          checkStatus(getFATentry(&vol,&nextCluster));
        }
       if( IsValidCluster(nextCluster) == FALSE )
          /* We have a bad file size, or the FAT is bad */
          return flInvalidFATchain;
        file->currentCluster = nextCluster;
      }
    }
  }

  *offsetInSector = offsetInCluster & (FL_SECTOR_SIZE - 1);
  if (file->flags & FL_FILE_IS_ROOT_DIR)
    *sectorNo = vol.rootDirectorySectorNo +
                  (SectorNo) (file->currentPosition >> FL_SECTOR_SIZE_BITS);
  else
    *sectorNo = firstSectorOfCluster(&vol,file->currentCluster) +
                  (SectorNo) (offsetInCluster >> FL_SECTOR_SIZE_BITS);

  return flOK;
}




/*----------------------------------------------------------------------*/
/*                      c l o s e F i l e                               */
/*                                                                      */
/* Closes an open file, records file size and dates in directory and    */
/* releases file handle.                                                */
/*                                                                      */
/* Parameters:                                                          */
/*       vol              : Pointer identifying drive                   */
/*       file             : File to close.                              */
/*                                                                      */
/* Returns:                                                             */
/*       FLStatus       : 0 on success, otherwise failed                */
/*----------------------------------------------------------------------*/

FLStatus closeFile(File *file)
{
#ifndef FL_READ_ONLY
    DirectoryEntry *dirEntry;

  if ((file->flags & FL_FILE_MODIFIED) && !(file->flags & FL_FILE_IS_ROOT_DIR)) {
      checkStatus(getDirEntryForUpdate(file,&dirEntry));
    dirEntry->attributes |= FL_ATTR_ARCHIVE;
    if (!(file->flags & FL_FILE_IS_DIRECTORY))
      toLE4(dirEntry->fileSize,file->fileSize);
    setCurrentDateTime(dirEntry);
#ifndef FL_NO_SURE_FS_SUPPORT
        checkStatus( setAttentionFlag( file->fileVol, dirEntry, 0));    /* reset attention flag */
#endif /* FL_NO_SURE_FS_SUPPORT */
  }
#endif /* FL_READ_ONLY */

  if(!(file->flags & FL_FILE_IS_ROOT_DIR))
     file->flags = 0;              /* no longer open */
  else
     file->flags = FL_FILE_IS_ROOT_DIR;

  return flOK;
}

/*----------------------------------------------------------------------*/
/*                      f l u s h F i l e                                                                */
/*                                                                                                                                            */
/* Records file size and dates in directory but does not release                */
/* file handle.                                                                                                                    */
/*                                                                      */
/* Parameters:                                                          */
/*       vol              : Pointer identifying drive                   */
/*       file              : File to close.                             */
/*                                                                      */
/* Returns:                                                             */
/*       FLStatus       : 0 on success, otherwise failed                */
/*----------------------------------------------------------------------*/

FLStatus flushFile(File *file)
{
#ifndef FL_READ_ONLY
    Volume vol = file->fileVol;

  if ((file->flags & FILE_MODIFIED) && !(file->flags & FL_FILE_IS_ROOT_DIR)) {
    DirectoryEntry *dirEntry;
    checkStatus(getDirEntryForUpdate(file,&dirEntry));

    dirEntry->attributes |= FL_ATTR_ARCHIVE;
    if (!(file->flags & FL_FILE_IS_DIRECTORY))
      toLE4(dirEntry->fileSize,file->fileSize);
    setCurrentDateTime(dirEntry);

#ifndef FL_NO_SURE_FS_SUPPORT
    checkStatus( setAttentionFlag( file->fileVol, dirEntry, 0));    /* reset attention flag */
#endif /* FL_NO_SURE_FS_SUPPORT */
      vol.volBuffer.dirty = TRUE;
    checkStatus(flushBuffer(&vol));
    file->flags &= ~FILE_MODIFIED;

⌨️ 快捷键说明

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