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; }
/* 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; }
static BOOL RelocateFirstCluster(RDWRHandle handle, struct DirectoryPosition* pos, struct DirectoryEntry* entry, CLUSTER destination) { int labelsize; CLUSTER fatpos=0, freecluster, label; BOOL IsInFAT = FALSE; SECTOR srcsector, destsector; unsigned long sectorspercluster; CLUSTER clustervalue; BOOL DOTSprocessed=FALSE; struct FSInfoStruct FSInfo; CLUSTER source; /* Do some preliminary calculations. */ source = GetFirstCluster(entry); 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); /* We know the first cluster is refered to in the directory entry given */ /* 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 (entry->attribute & FA_DIREC) { if (!AdaptCurrentAndPreviousDirs(handle, source, destination)) { RETURN_FTEERROR(FALSE); } DOTSprocessed = TRUE; } /* Copy all sectors in this cluster to the new position */ if (!CopySectors(handle, srcsector, destsector, sectorspercluster)) { RETURN_FTEERROR(FALSE); } /* Write the entry in the FAT */ if (!WriteFatLabel(handle, destination, clustervalue)) { RETURN_FTEERROR(FALSE); } SetFirstCluster(destination, entry); if (!WriteDirectory(handle, pos, entry)) { RETURN_FTEERROR(FALSE); } // if (!GetNthCluster(handle, source, &label)) // return FALSE; if (!WriteFatLabel(handle, source, FAT_FREE_LABEL)) { 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; }
/* Beware of circular references: fatpos1 = cluster2 cluster1 = clustervalue2 A -> B -> C D -> A -> B D -> A -> B -> C => D -> B -> A -> C A: C A: A / B: B A D: B cluster1 = fatpos2 clustervalue1 = cluster2 A -> B -> C B -> C -> D A -> B -> C -> D => A -> C -> B -> D C: C B A: C B: D B: B / */ BOOL SwapClusters (RDWRHandle handle, CLUSTER clust1, CLUSTER clust2) { BOOL found, IsInFAT1 = FALSE, IsInFAT2 = FALSE, error = FALSE; CLUSTER freeclust, clustervalue1, fatpos1, fatpos2; CLUSTER clustervalue2, dircluster1, dircluster2; unsigned char sectorspercluster; SECTOR startsector; struct DirectoryPosition dirpos1, dirpos2; struct DirectoryEntry entry; unsigned long neededmem; void *MemCluster; BOOL DOTSProcessed1, DOTSProcessed2; SECTOR srcsector, destsector; /* First check wether we shouldn't be using RelocateCluster instead. */ if (!ReadFatLabel (handle, clust1, &clustervalue1)) return FALSE; if (!ReadFatLabel (handle, clust2, &clustervalue2)) return FALSE; if (FAT_FREE (clustervalue1) && (FAT_FREE (clustervalue2))) { return TRUE; } if (FAT_FREE (clustervalue1)) { return RelocateCluster (handle, clust2, clust1); } if (FAT_FREE (clustervalue2)) { return RelocateCluster (handle, clust1, clust2); } /* See if we have enough memory to load the data for one cluster into memory. */ sectorspercluster = GetSectorsPerCluster (handle); if (!sectorspercluster) return FALSE; neededmem = sectorspercluster * BYTESPERSECTOR; MemCluster = malloc (neededmem); if (MemCluster) { /* First prepare the first cluster. */ /* See where the cluster is refered */ /* In FAT? */ if (!FindClusterInFAT (handle, clust1, &fatpos1)) { free (MemCluster); return FALSE; } /* No, then look if this is the first cluster of a file. */ if (!fatpos1) { if (!FindClusterInDirectories (handle, clust1, &dirpos1, &found)) { free (MemCluster); return FALSE; } if (!found) { free (MemCluster); return FALSE; /* Non valid cluster! */ } else { /* Special case: if this is the first cluster of a directory then adjust all the . and .. pointers to reflect the new position on the volume. */ if (!GetDirectory (handle, &dirpos1, &entry)) { free (MemCluster); return FALSE; } if (entry.attribute & FA_DIREC) { dircluster1 = GetFirstCluster (&entry); if (!AdaptCurrentAndPreviousDirs(handle, dircluster1, clust2)) { AdaptCurrentAndPreviousDirs (handle, dircluster1, clust1); free (MemCluster); return FALSE; } DOTSProcessed1 = TRUE; } } } else { IsInFAT1 = TRUE; } /* Then prepare the second cluster. */ /* See where the cluster is refered */ /* In FAT? */ if (!FindClusterInFAT (handle, clust2, &fatpos2)) { if (DOTSProcessed1) AdaptCurrentAndPreviousDirs (handle, dircluster1, clust1); free (MemCluster); return FALSE; } /* No, then look if this is the first cluster of a file. */ if (!fatpos2) { if (!FindClusterInDirectories (handle, clust2, &dirpos2, &found)) { if (DOTSProcessed1) AdaptCurrentAndPreviousDirs (handle, dircluster1, clust1); free (MemCluster); return FALSE; } if (!found) { if (DOTSProcessed1) AdaptCurrentAndPreviousDirs (handle, dircluster1, clust1); free (MemCluster); return FALSE; /* Non valid cluster! */ } else { /* Special case: if this is the first cluster of a directory then adjust all the . and .. pointers to reflect the new position on the volume. */ if (!GetDirectory (handle, &dirpos2, &entry)) { if (DOTSProcessed1) AdaptCurrentAndPreviousDirs (handle, dircluster1, clust1); free (MemCluster); return FALSE; } if (entry.attribute & FA_DIREC) { dircluster2 = GetFirstCluster (&entry); if (!AdaptCurrentAndPreviousDirs(handle, dircluster2, clust1)) { AdaptCurrentAndPreviousDirs (handle, dircluster2, clust2); AdaptCurrentAndPreviousDirs (handle, dircluster1, clust1); free (MemCluster); return FALSE; } DOTSProcessed2 = TRUE; } } } else { IsInFAT2 = TRUE; } startsector = ConvertToDataSector (handle, clust1); if (!startsector) { if (DOTSProcessed1) AdaptCurrentAndPreviousDirs (handle, dircluster1, clust1); if (DOTSProcessed2) AdaptCurrentAndPreviousDirs (handle, dircluster2, clust2); free (MemCluster); return FALSE; } /* Then copy the data of the second cluster to the new position */ /* Copy all sectors in this cluster to the new position */ srcsector = ConvertToDataSector (handle, clust2); if (!srcsector) { if (DOTSProcessed1) AdaptCurrentAndPreviousDirs (handle, dircluster1, clust1); if (DOTSProcessed2) AdaptCurrentAndPreviousDirs (handle, dircluster2, clust2); free (MemCluster); return FALSE; } destsector = ConvertToDataSector (handle, clust1); if (!startsector) { if (DOTSProcessed1) AdaptCurrentAndPreviousDirs (handle, dircluster1, clust1); if (DOTSProcessed2) AdaptCurrentAndPreviousDirs (handle, dircluster2, clust2); free (MemCluster); return FALSE; } /* AS OF THIS POINT WE WILL NOT BE ABLE TO BACKTRACK, THEREFORE WE KEEP ON GOING EVEN IF THERE WERE ERRORS. */ /* Change the pointers of the first cluster that has to be moved to the second cluster. */ /* Write the entry in the FAT */ if (clust2 == clustervalue1) /* Beware of circular references */ { if (!WriteFatLabel (handle, clust2, clust1)) error = TRUE; } else { if (!WriteFatLabel (handle, clust2, clustervalue1)) error = TRUE; } /* Adjust the pointer to the relocated cluster */ if (IsInFAT1) /* the previous one in the file */ { if (fatpos1 != clust2) /* Beware of circular references */ { if (!WriteFatLabel (handle, fatpos1, clust2)) error = TRUE; } } else /* or the directory entry to the file */ { if (!GetDirectory (handle, &dirpos1, &entry)) error = TRUE; if (GetFirstCluster (&entry) != clust2) { SetFirstCluster (clust2, &entry); if (!WriteDirectory (handle, &dirpos1, &entry)) error = TRUE; } } /* Change the pointers of the second cluster that has to be moved to the first cluster. */ /* Write the entry in the FAT */ if (clust1 == clustervalue2) /* Beware of circular references */ { if (!WriteFatLabel (handle, clust1, clustervalue1)) error = TRUE; } else { if (!WriteFatLabel (handle, clust1, clustervalue2)) error = TRUE; } /* Adjust the pointer to the relocated cluster */ if (IsInFAT2) /* the previous one in the file */ { if (fatpos2 != clust1) /* Beware of circular references */ { if (!WriteFatLabel (handle, fatpos2, clust1)) error = TRUE; } } else /* or the directory entry to the file */ { if (!GetDirectory (handle, &dirpos2, &entry)) error = TRUE; if (GetFirstCluster (&entry) != clust1) /* Beware of circular references */ { SetFirstCluster (clust1, &entry); if (!WriteDirectory (handle, &dirpos2, &entry)) error = TRUE; }