Beispiel #1
0
static BOOL GetNextConsecutiveChain(RDWRHandle handle, CLUSTER source, unsigned long* length)
{
    CLUSTER current = source, label;
    
    if (!GetNthCluster(handle, source, &label))
	RETURN_FTEERROR(FALSE);
    
    *length = 0;
    
    while (FAT_NORMAL(label))
    {
	if (label != current+1)
	{
	   return TRUE;        	    	    
	}	
	
	(*length)++;
	
	if (!GetNthCluster(handle, current, &label))
	    RETURN_FTEERROR(FALSE);
    }
    
    (*length)++;
    return TRUE;    
}
Beispiel #2
0
BOOL MoveDefragmentedFilesToStartOfBlock(RDWRHandle handle, 
                                         CLUSTER lowerbound, 
                                         CLUSTER upperbound)
{
    CLUSTER i, j, cluster;
    BOOL IsPartOfFF;
    
    for (i = lowerbound; i < upperbound; i++)
    {
        if (!IsPartOfFragmentedFile(handle, i, &IsPartOfFF))
           return FALSE;
        
        if (!IsPartOfFF)
           continue;
           
        /* See if we haven't already reached to free space in this
           block */
        if (!GetNthCluster(handle, i, cluster))
           return FALSE;   
    
        if (FAT_FREE(cluster))
           break;           
           
        for (j = i; j <= upperbound; j++)
        {
            /* See if we haven't already reached to free space in this
               block */
            if (!GetNthCluster(handle, j, cluster))
               return FALSE;   
    
            if (FAT_FREE(cluster))
               break;
                        
            if (!IsPartOfFragmentedFile(handle, j, &IsPartOfFF))
               return FALSE;
           
            if (!IsPartOfFF)
               break;
        }
        
        if (j > upperbound)
           break;
        
        if (FAT_FREE(cluster))
           continue;
           
        if (!SwapClusters(handle, i, j));
           return FALSE;
    }
 
    return TRUE;
}
Beispiel #3
0
BOOL RelocateKnownFile(RDWRHandle handle, 
                       struct DirectoryPosition* pos,
                       struct DirectoryEntry* entry,
                       CLUSTER destination)
{
    /* We assume destination long enough to relocate the complete file */
    unsigned long length, flength;
    CLUSTER firstcluster;
    CLUSTER source;
    
    firstcluster = GetFirstCluster(entry);
    length = CalculateFileSize(handle, firstcluster);
    if (length == FAIL) 
        RETURN_FTEERROR(FALSE);    

    /* Small optimization for when length == 1 */

    if (!RelocateFirstCluster(handle, pos, entry, destination))
        RETURN_FTEERROR(FALSE);

    if (length == 1) return TRUE;    
    length--;
    
    /* Change the structures for the relocation */
    firstcluster = GetFirstCluster(entry);  // Value is now different!
    if (!GetNthCluster(handle, firstcluster, &source))
       return FALSE;
    
    destination++;

    while (length > 0)
    {    
        if (!GetNextConsecutiveChain(handle, source, length, &flength))	    
	   RETURN_FTEERROR(FALSE);		

        if (!RelocateConsecutiveClusterSeq(handle, source, destination, flength))
	    RETURN_FTEERROR(FALSE);

        if (!GetNthCluster(handle, destination + flength-1, &source))
	    return FALSE;

	if (FAT_LAST(source))
	    return length == flength;

	destination += flength;
	length -= flength;
    }
      
    return TRUE;
}
Beispiel #4
0
static BOOL MarkClusterChain(RDWRHandle handle, CLUSTER source, CLUSTER dest, unsigned long filesize, BOOL atend)
{
    CLUSTER label;
    unsigned long i;    
    
    for (i=0; i<filesize; i++)
    {
	if (!WriteFatLabel(handle, dest+i, dest+i+1))
	    RETURN_FTEERROR(FALSE);
    }

    if (atend)
    {    		 
        if (!WriteFatLabel(handle, dest+filesize, FAT_LAST_LABEL))
	   RETURN_FTEERROR(FALSE);
    }    
    else
    {
	if (!GetNthCluster(handle, source+filesize, &label))
	    RETURN_FTEERROR(FALSE);

	if (!WriteFatLabel(handle, dest+filesize, label))
	    RETURN_FTEERROR(FALSE);
    }
     
    return TRUE;    
}
Beispiel #5
0
static BOOL RelocateConsecutiveClusterSeq(RDWRHandle handle, 
                                          CLUSTER source, 
                                          CLUSTER destination,                                           
                                          unsigned long flength)
{
    CLUSTER label;
    CLUSTER pSource = destination - 1; /* Only valid in this context */
    
    assert(flength>0);
    
    if (!Relocate1Cluster(handle, source, destination, pSource))
	RETURN_FTEERROR(FALSE);
    
    if (flength == 1) return TRUE;              /* If we have to relocate just one cluster, we're done */

    /* The first cluster is relocated to the destination, the link to break is now there */
    /* After that, just move all the data from the source to the destination,
       adding fat labels to the destination */
    if (!GetNthCluster(handle, source+flength-1, &label))
	RETURN_FTEERROR(FALSE);
    
    if (!CopyClusters(handle, source+1, destination+1, flength-1))
	RETURN_FTEERROR(FALSE);    
    
    if (!MarkClusterChain(handle, source, destination, flength-1, FAT_LAST(label)))
	RETURN_FTEERROR(FALSE);      
  
    /* In the end, remove all the fat labels from the source */
    if (!CleanFatLabels(handle, source, flength))
	RETURN_FTEERROR(FALSE);        
    
    return TRUE;
}
Beispiel #6
0
CLUSTER random_freeSpace(RDWRHandle handle, unsigned long labelsinfat)
{
    unsigned long randomnumber;
    unsigned random1, random2;
    CLUSTER label;

    random1 = rand() * (labelsinfat % 65536L);
    random2 = rand() * (labelsinfat / 65536L);

    randomnumber = random1 * 65536L + random2;

    randomnumber = (randomnumber % (labelsinfat-2))+2;

    while (TRUE)
    {
        if (!GetNthCluster(handle, randomnumber, &label))
            return FALSE;
        
        if (FAT_FREE(label))
        {
            return randomnumber;
        }

        randomnumber++;
        if (randomnumber == labelsinfat)
       randomnumber = 2;
    }
}
Beispiel #7
0
static BOOL CreateFatReferedMap(RDWRHandle handle)
{
    unsigned long LabelsInFat;
    CLUSTER current, label;

    LabelsInFat = GetLabelsInFat(handle);
    if (!LabelsInFat) return FAIL;
        
    FatReferedMap = CreateVFSBitField(handle, LabelsInFat);
    if (!FatReferedMap) return FAIL;

    for (current = 2; current < LabelsInFat; current++)
    {
	if (!GetNthCluster(handle, current, &label))
	    return FALSE;

	if (FAT_NORMAL(label))
	{
	    if (!SetVFSBitfieldBit(FatReferedMap, label))
		return FALSE;	
	}    
    }

    return TRUE;
}
Beispiel #8
0
static BOOL GetNextConsecutiveChain(RDWRHandle handle, CLUSTER source, unsigned long maxlength, unsigned long* length)
{
    CLUSTER current = source, label;
    unsigned long retLength;
    
    if (!GetNthCluster(handle, source, &label))
	RETURN_FTEERROR(FALSE);
    
    for (retLength=1; 
	 FAT_NORMAL(label) && (label == ++current) && (retLength < maxlength);
         retLength++)    
    {
	if (!GetNthCluster(handle, current, &label))
	    RETURN_FTEERROR(FALSE);
    }
    
    *length = retLength;
    return TRUE;    
}
Beispiel #9
0
static BOOL CleanFatLabelChain(RDWRHandle handle, CLUSTER source)
{
    CLUSTER label;
    
    do {
	
	if (!GetNthCluster(handle, source, &label))
	    RETURN_FTEERROR(FALSE);	
	
	if (!WriteFatLabel(handle, source, FAT_FREE_LABEL))
	    RETURN_FTEERROR(FALSE);	
	
	source = label;
	
    } while (FAT_NORMAL(label));
    
    return TRUE;
}
Beispiel #10
0
static BOOL OnlyFilledRead(RDWRHandle handle, SECTOR lsect,
                           unsigned numsectors, char* buf)
{
    unsigned i;
    SECTOR  start = lsect;
    CLUSTER cluster, label;

    for (i = 0; i < numsectors; i++)
    {
        cluster = DataSectorToCluster(handle, lsect+i);
        if (!cluster) return FALSE;

        if (!GetNthCluster(handle, cluster, &label))
        {
            return FALSE;
        }

        if (FAT_FREE(label) || FAT_BAD(label))
        {
            if (i)
            {
                if (ReadSectors(handle, i, start, buf) == -1)
                {
                    return FALSE;
                }
            }

            start = lsect+i+1;
        }
    }

    if (start < lsect+numsectors)
    {
        if (ReadSectors(handle, numsectors - (unsigned)(start - lsect),
                        start, buf) == -1)
        {
            return FALSE;
        }
    }

    return TRUE;
}
Beispiel #11
0
static BOOL CopyClusterChain(RDWRHandle handle, CLUSTER source, CLUSTER dest)
{
    unsigned long length;
    
    do {
        if (!GetNextConsecutiveChain(handle, source, &length))
	   RETURN_FTEERROR(FALSE);
    
	if (!CopyConsecutiveClusters(handle, source, dest, length))
	    RETURN_FTEERROR(FALSE);
	
	dest += length;
	
	if (!GetNthCluster(handle, source+length-1, &source))
	    RETURN_FTEERROR(FALSE);
	
    } while (FAT_NORMAL(source));
    
    
    return TRUE;
}
Beispiel #12
0
CLUSTER random_cluster(RDWRHandle handle, unsigned long labelsinfat)
{
    unsigned long randomnumber;
    unsigned random1, random2;
    CLUSTER label;

    int fatlabelsize = GetFatLabelSize(handle);
    if (!fatlabelsize) return FALSE;

    random1 = rand() * (labelsinfat % 65536L);
    random2 = rand() * (labelsinfat / 65536L);

    randomnumber = random1 * 65536L + random2;

    randomnumber = (randomnumber % (labelsinfat-2))+2;

    while (TRUE)
    {
        if (fatlabelsize == FAT32)
        {
            if (randomnumber == GetFAT32RootCluster(handle))
            {
                randomnumber++;
                continue;
            }
        }

        if (!GetNthCluster(handle, randomnumber, &label))
            return FALSE;
        
        if (FAT_NORMAL(label) || FAT_LAST(label))
        {
            return randomnumber;
        }

        randomnumber++;
        if (randomnumber == labelsinfat)
       randomnumber = 2;
    }
}
Beispiel #13
0
/*************************************************************************
**                        RecoverFileChains
**************************************************************************
** Goes through the FAT and converts every cluster chain to a valid file.
**************************************************************************/
static BOOL RecoverFileChains(RDWRHandle handle)
{
    unsigned long LabelsInFat, i;
    unsigned long filesize;
    CLUSTER label;
    
    LabelsInFat = GetLabelsInFat(handle);
    if (!LabelsInFat) return FALSE;
	
    for (i = 2; i < LabelsInFat; i++)
    {	
	if (!GetNthCluster(handle, i, &label))
	   return FALSE;
	
	if (FAT_NORMAL(label) || (label == FAT_LAST_LABEL))
	{    
	   switch (IsStartOfChain(handle, i))
	   {
	      case TRUE:    
	           if (!RecoverFileChain(handle, i, &filesize))
		      return FALSE;
		   if (filesize)
		   {    
		      if (!AddToRootDir(handle, i, filesize))
		         return FALSE;
		   }
		   break;
		
	      case FAIL:
	           return FALSE;	       
	   }
       }
    }
    
    return TRUE;
}
Beispiel #14
0
static BOOL Relocate1Cluster(RDWRHandle handle,
                             CLUSTER source,
                             CLUSTER destination,
                             CLUSTER pSource)
{
   int labelsize;
   CLUSTER fatpos=0, freecluster, label;
   //BOOL IsInFAT = FALSE;
   SECTOR srcsector, destsector;
   unsigned long sectorspercluster;
   CLUSTER clustervalue;
   BOOL DOTSprocessed=FALSE;
   struct FSInfoStruct FSInfo;

   /* See wether the destination is actually free. */
   if (!GetNthCluster(handle, destination, &label))
      RETURN_FTEERROR(FALSE);
   if (!FAT_FREE(label)) 
      RETURN_FTEERROR(FALSE);
   
   /* Do some preliminary calculations. */
   srcsector = ConvertToDataSector(handle, source);
   if (!srcsector)
      RETURN_FTEERROR(FALSE);
   destsector = ConvertToDataSector(handle, destination);
   if (!destsector)
      RETURN_FTEERROR(FALSE);
   sectorspercluster = GetSectorsPerCluster(handle);
   if (!sectorspercluster)
      RETURN_FTEERROR(FALSE);
         
   /* Get the value that is stored at the source position in the FAT */
   if (!ReadFatLabel(handle, source, &clustervalue))
      RETURN_FTEERROR(FALSE);


   /* Copy all sectors in this cluster to the new position */
   if (!CopySectors(handle, srcsector, destsector, sectorspercluster))
   {
      RETURN_FTEERROR(FALSE);
   }
   
   if (!WriteFatLabel(handle, destination, clustervalue))
   {
      RETURN_FTEERROR(FALSE);
   }

   /* Adjust the pointer to the relocated cluster */
   if (!WriteFatLabel(handle, pSource, destination))
   {
      RETURN_FTEERROR(FALSE);
   }

   if (!WriteFatLabel(handle, source, FAT_FREE_LABEL))
   {
      if (DOTSprocessed)
         AdaptCurrentAndPreviousDirs(handle, source, source);
   
      RETURN_FTEERROR(FALSE);
   }

   /* Adjust FSInfo on FAT32 */
   labelsize = GetFatLabelSize(handle);
   if (labelsize == FAT32)
   {
      if (!GetFreeClusterSearchStart(handle, &freecluster))
         RETURN_FTEERROR(FALSE);
         
      if (source < freecluster) /* source cluster became available */
      {
         if (!ReadFSInfo(handle, &FSInfo))
            RETURN_FTEERROR(FALSE);
    
         WriteFreeClusterStart(&FSInfo, source);
    
         if (!WriteFSInfo(handle, &FSInfo))
            RETURN_FTEERROR(FALSE);          
      }
      
      if ((freecluster == destination) && /* We are relocating to the first */
	  (destination < source))         /* free cluster */
      {
         CLUSTER dummy;     
 
         if (!FindFirstFreeSpace(handle, &dummy, &dummy))
            RETURN_FTEERROR(FALSE);
      }
   }
   
   return TRUE;
}
Beispiel #15
0
BOOL ScanFileChain(RDWRHandle handle, CLUSTER firstcluster,
                   struct DirectoryPosition* pos, 
                   struct DirectoryEntry* entry,
                   char* filename,
                   BOOL fixit)
{
    char* bitfield;
    unsigned long labelsinfat;    
    BOOL breakoff = FALSE;
    CLUSTER current = firstcluster, label, breakingcluster, lengthBreakingCluster=0;  
    unsigned long length = 0, calculatedsize, bytespercluster;
    static char tempbuf[255];   
    BOOL retVal = TRUE;

    /* If it is a root directory that we have to scan see wether it is
       a FAT32 volume and if it is get the root cluster */ 
    if (!firstcluster)
    {
       switch (GetFatLabelSize(handle))
       {
          case FAT12:
          case FAT16:
               return TRUE;
               
          case FAT32:
               current = GetFAT32RootCluster(handle);
               break; 
               
          default:
               return FAIL;
       }
    }
    else
    {
       bytespercluster = GetSectorsPerCluster(handle) * BYTESPERSECTOR;
       if (!bytespercluster) return FAIL;   
       
       calculatedsize = (entry->filesize / bytespercluster) +
                                   ((entry->filesize % bytespercluster) > 0);       
    }
      
    labelsinfat = GetLabelsInFat(handle);
    if (!labelsinfat) return FAIL;
  
    bitfield = CreateBitField(labelsinfat);
    if (!bitfield)
    {        
       DestroyBitfield(bitfield);
       return FAIL;  
    }
    
    SetBitfieldBit(bitfield, current);  
    
    /* Initialise the checks on the directory entries */
    if (entry->attribute & FA_DIREC)
    {
       InitClusterEntryChecking(handle, current, filename);
    
       switch (PreProcessClusterEntryChecking(handle, current, filename, fixit))
       {
          case FALSE:
               retVal = FALSE;              
               break;
               
          case FAIL:
               DestroyBitfield(bitfield);
               DestroyClusterEntryChecking(handle, current, filename);
               return FAIL;
       }
    }
    
    while (TRUE)
    {   
        length++;
  

        if (!GetNthCluster(handle, current, &label))
        {
           DestroyBitfield(bitfield);
           if (entry->attribute & FA_DIREC)
              DestroyClusterEntryChecking(handle, current, filename);           
           return FAIL;
        }
         
        /* Check the read cluster: */
        /* the last cluster */
        if (FAT_LAST(label))
        {
           if (entry->attribute & FA_DIREC) /* Here the current cluster is valid */
           {            
              switch (CheckEntriesInCluster(handle, current, filename, fixit))
              {
                  case FALSE:
                       retVal = FALSE;                                
                       break;
                   
                  case FAIL:
                       DestroyBitfield(bitfield);     
                       if (entry->attribute & FA_DIREC)
                          DestroyClusterEntryChecking(handle, current, filename);                 
                       return FAIL;                   
              }
           }                        
           break;                 
        }
        
        /* Check wether it is in range */
        if (FAT_NORMAL(label) && !IsLabelValid(handle, label))
        {
           if (firstcluster)
           {
              ShowFileNameViolation(handle, filename,
                                    "%s contains an invalid cluster");
           }     
           else
           {
              ShowFileNameViolation(handle, filename,
                                     "The root directory contains an invalid cluster");           
           }   
               
           breakoff = TRUE;
           breakingcluster = current;
           retVal = FALSE;                         
        }
        
        /* bad cluster */                                         
        if (FAT_BAD(label))
        {
           if (firstcluster)
           {
              ShowFileNameViolation(handle, filename,
                                    "%s contains a bad cluster");
           }     
           else
           {
              ShowFileNameViolation(handle, filename,
                                    "The root directory contains a bad cluster");           
           }     
           
           breakingcluster = current;
           breakoff = TRUE;
           retVal = FALSE;                         
        }       
                       
        if (FAT_FREE(label))
        {
           if (firstcluster)
           {
              ShowFileNameViolation(handle, filename,
                                     "%s contains a free cluster");
           }     
           else
           {
              ShowFileNameViolation(handle, filename,
                                     "The root directory contains a free cluster");           
           }
             
           breakoff = TRUE;      
           breakingcluster = current;     
           retVal = FALSE;                         
        }
                 
        /* Check wether there is a loop */
        if (!breakoff && GetBitfieldBit(bitfield, label))
        {
           if (firstcluster)
           {
              ShowFileNameViolation(handle, filename,
                                    "%s contains a loop");
           }     
           else
           {
              ShowFileNameViolation(handle, filename,
                                    "The root directory contains a loop");           
           }
                
           breakoff = TRUE;      
           breakingcluster = current;              
           retVal = FALSE;                     
        }
/*
        if ((firstcluster && ((entry->attribute & FA_DIREC) == 0)) &&
            (length > calculatedsize)                              &&
            (lengthBreakingCluster == 0))
        {
           lengthBreakingCluster = current;
        }
*/        
        if (breakoff)
        {
           if (fixit)
           {        
              if (!WriteFatLabel(handle, breakingcluster, FAT_LAST_LABEL))
              {
                 DestroyBitfield(bitfield);     
                 if (entry->attribute & FA_DIREC)
                    DestroyClusterEntryChecking(handle, current, filename);                 
                 return FAIL;
              }
           }
                
           break;
        }
        SetBitfieldBit(bitfield, label);  
      
        if (entry->attribute & FA_DIREC) /* Here the current cluster is valid */
        {            
           switch (CheckEntriesInCluster(handle, current, filename, fixit))
           {
              case FALSE:
                   retVal = FALSE;                                
                   break;
                   
              case FAIL:
                   DestroyBitfield(bitfield);     
                   if (entry->attribute & FA_DIREC)
                      DestroyClusterEntryChecking(handle, current, filename);                 
                   return FAIL;                   
           }
        }
        
        current = label;  
    }
    
    /* Check the length of the file */
    if (firstcluster)
    {
/*            
       if (((entry->attribute & FA_DIREC) == 0) && (length > calculatedsize))
       {
          sprintf(tempbuf, 
                  "%%s has an invalid size, the size should be about %lu, but the entry says it's %lu",
                  length * bytespercluster, entry->filesize);     

          ShowFileNameViolation(handle, filename, tempbuf);
          
          if (fixit &&
              !WriteFatLabel(handle, lengthBreakingCluster, FAT_LAST_LABEL))
          {
             DestroyBitfield(bitfield);     
             if (entry->attribute & FA_DIREC)
                DestroyClusterEntryChecking(handle, current, filename);             
             return FAIL;
          }    
 
          retVal = FALSE;                                   
       }                       
*/     

       if (((entry->attribute & FA_DIREC) == 0) && (length != calculatedsize))
       {            
          sprintf(tempbuf, 
                  "%%s has an invalid size, the size should be about %lu, but the entry says it's %lu",
                  length * bytespercluster, entry->filesize);     


          ShowFileNameViolation(handle, filename, tempbuf); 
       
          if (fixit)
          {
             /* Notice that we are modifying the filesize of the same entry in chkentrs.c,
                the entry shall be written to disk there. */     
             entry->filesize = length * bytespercluster;          
          }
          
          retVal = FALSE;                       
       }
    }
    
    /* Destroy the checks on the directory entries */
    if (entry->attribute & FA_DIREC)
    {
       switch (PostProcessClusterEntryChecking(handle, current, filename, fixit))
       {
          case FALSE:
               retVal = FALSE;                           
               break;
               
          case FAIL:
               retVal = FAIL;
       }
       
       DestroyClusterEntryChecking(handle, current, filename);     
    }
   
    DestroyBitfield(bitfield);
    return retVal;
}
Beispiel #16
0
/* This function returns FALSE if the destination is not free. */
BOOL RelocateCluster(RDWRHandle handle, CLUSTER source, CLUSTER destination)
{
   int labelsize, value;
   CLUSTER fatpos=0, freecluster, dircluster, label;
   struct DirectoryPosition dirpos;
   struct DirectoryEntry entry;
   BOOL IsInFAT = FALSE;
   SECTOR srcsector, destsector;
   unsigned long sectorspercluster;
   CLUSTER clustervalue;
   BOOL found, DOTSprocessed=FALSE;
   struct FSInfoStruct FSInfo;

   if (!FatReferedMap)
   {
	if (!CreateFatReferedMap(handle))
	    return FALSE;
   }

   /* See wether the destination is actually free. */
   if (!GetNthCluster(handle, destination, &label))
      RETURN_FTEERROR(FALSE);
   if (!FAT_FREE(label)) 
      RETURN_FTEERROR(FALSE);
   
   /* Do some preliminary calculations. */
   srcsector = ConvertToDataSector(handle, source);
   if (!srcsector)
      RETURN_FTEERROR(FALSE);
   destsector = ConvertToDataSector(handle, destination);
   if (!destsector)
      RETURN_FTEERROR(FALSE);
   sectorspercluster = GetSectorsPerCluster(handle);
   if (!sectorspercluster)
      RETURN_FTEERROR(FALSE);
         
   /* Get the value that is stored at the source position in the FAT */
   if (!ReadFatLabel(handle, source, &clustervalue))
      RETURN_FTEERROR(FALSE);
   
   /* See where the cluster is refered */
   if (!GetVFSBitfieldBit(FatReferedMap, source, &value))
      return FALSE;

   if (value)
   {//CLUSTER fatpos1;

	if (!FindClusterInFAT(handle, source, &fatpos))
	    RETURN_FTEERROR(FALSE);
/*
        if (!FindClusterInFAT1(handle, source, &fatpos1))
            RETURN_FTEERROR(FALSE);

        if (fatpos != fatpos1)
            printf("hola");
*/
   }
      
   if (!fatpos)
   {
      if (!FindClusterInDirectories(handle, source, &dirpos, &found))
         RETURN_FTEERROR(FALSE);
      if (!found)
      {
          /* Note: on FAT32 this cluster may be pointing to the root directory.
                   We do not support relocating the root cluster at this time.          
          */
          
          
          RETURN_FTEERROR(FALSE);                /* Non valid cluster! */
      }
      else
      {
         /*
            This is the first cluster of some file. See if it is a directory
            and if it is, adjust the '.' entry of this directory and all
            of the '..' entries of all the (direct) subdirectories to point
            to the new cluster.
         */
         if (!GetDirectory(handle, &dirpos, &entry))
            RETURN_FTEERROR(FALSE);
            
         if (entry.attribute & FA_DIREC)
         {
            dircluster = GetFirstCluster(&entry);
            if (!AdaptCurrentAndPreviousDirs(handle, dircluster, destination))
            {
               RETURN_FTEERROR(FALSE);
            }
            DOTSprocessed = TRUE;
         }
      }
   }
   else
   {
      IsInFAT = TRUE;
   }

   /* Copy all sectors in this cluster to the new position */
   if (!CopySectors(handle, srcsector, destsector, sectorspercluster))
   {
      if (DOTSprocessed)
         AdaptCurrentAndPreviousDirs(handle, dircluster, source);
      RETURN_FTEERROR(FALSE);
   }
   
   /* Write the entry in the FAT */
   if (!WriteFatReference(handle, destination, clustervalue))
   {
      if (DOTSprocessed)
         AdaptCurrentAndPreviousDirs(handle, dircluster, source);
      RETURN_FTEERROR(FALSE);
   }

   if (!WriteFatLabel(handle, destination, clustervalue))
   {
      if (DOTSprocessed)
         AdaptCurrentAndPreviousDirs(handle, dircluster, source);
      RETURN_FTEERROR(FALSE);
   }

   /* Adjust the pointer to the relocated cluster */
   if (IsInFAT)
   {
      if (!WriteFatReference(handle, fatpos, destination))
      {
         RETURN_FTEERROR(FALSE);
      }

      if (!WriteFatLabel(handle, fatpos, destination))
      {
         RETURN_FTEERROR(FALSE);
      }

      if (!ClearVFSBitfieldBit(FatReferedMap, source))
	  return FALSE;
      if (!SetVFSBitfieldBit(FatReferedMap, destination))
	  return FALSE;
      //if (!IndicateFatClusterMoved(fatpos, source, destination))
      //   return FALSE;
   }
   else
   {
      CLUSTER label;

      if (!GetDirectory(handle, &dirpos, &entry))
      {
         if (DOTSprocessed)
            AdaptCurrentAndPreviousDirs(handle, dircluster, source);
      
         RETURN_FTEERROR(FALSE);
      }
      
      SetFirstCluster(destination, &entry);
      if (!WriteDirectory(handle, &dirpos, &entry))
      {
         if (DOTSprocessed)
            AdaptCurrentAndPreviousDirs(handle, dircluster, source);
      
         RETURN_FTEERROR(FALSE);
      }

      if (!IndicateDirEntryMoved(source, destination))
	  return FALSE;

     if (!GetNthCluster(handle, source, &label))
         return FALSE;

     //if (!IndicateFatClusterMoved(label, source, destination))
     //   return FALSE;
   }

   if (!WriteFatReference(handle, source, FAT_FREE_LABEL))
   {
      if (DOTSprocessed)
         AdaptCurrentAndPreviousDirs(handle, dircluster, source);
   
      RETURN_FTEERROR(FALSE);
   }

   if (!WriteFatLabel(handle, source, FAT_FREE_LABEL))
   {
      if (DOTSprocessed)
         AdaptCurrentAndPreviousDirs(handle, dircluster, source);
   
      RETURN_FTEERROR(FALSE);
   }

   if (!IndicateDirClusterMoved(handle, source, destination))
      RETURN_FTEERROR(FALSE);
      
   /* Adjust FSInfo on FAT32 */
   labelsize = GetFatLabelSize(handle);
   if (labelsize == FAT32)
   {
      if (!GetFreeClusterSearchStart(handle, &freecluster))
         RETURN_FTEERROR(FALSE);
         
      if (source < freecluster) /* source cluster became available */
      {
         if (!ReadFSInfo(handle, &FSInfo))
            RETURN_FTEERROR(FALSE);
    
         WriteFreeClusterStart(&FSInfo, source);
    
         if (!WriteFSInfo(handle, &FSInfo))
            RETURN_FTEERROR(FALSE);          
      }
      
      if ((freecluster == destination) && /* We are relocating to the first */
	  (destination < source))         /* free cluster */
      {
         CLUSTER dummy;     
 
         if (!FindFirstFreeSpace(handle, &dummy, &dummy))
            RETURN_FTEERROR(FALSE);
      }
   }
   
   return TRUE;
}