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; }
CLUSTER LocatePreviousDir(RDWRHandle handle, CLUSTER firstdircluster) { SECTOR* sectbuf; SECTOR sector; assert(firstdircluster); sectbuf = AllocateSector(handle); if (!sectbuf) RETURN_FTEERR(0xFFFFFFFFL); sector = ConvertToDataSector(handle, firstdircluster); if (!sector) { FreeSectors(sectbuf); RETURN_FTEERR(0xFFFFFFFFL); } if (!ReadDataSectors(handle, 1, sector, (void*) sectbuf)) { FreeSectors(sectbuf); RETURN_FTEERR(0xFFFFFFFFL); } if (IsPreviousDir(((struct DirectoryEntry*) sectbuf)[1])) { CLUSTER retVal = GetFirstCluster(&(((struct DirectoryEntry*) sectbuf)[1])); FreeSectors(sectbuf); return retVal; } SetFTEerror(FTE_FILESYSTEM_BAD); FreeSectors(sectbuf); RETURN_FTEERR(0xFFFFFFFFL); }
void Clust::DeleteMetric(unsigned uIndex) { for (unsigned uNodeIndex = GetFirstCluster(); uNodeIndex != uInsane; uNodeIndex = GetNextCluster(uNodeIndex)) { if (uIndex == uNodeIndex) continue; DeleteMetric(uIndex, uNodeIndex); } }
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; }
BOOL WalkDirectoryTree(RDWRHandle handle, int (*func) (RDWRHandle handle, struct DirectoryPosition* position, void** structure), void** structure) { int top = 0; struct StackElement* stack; CLUSTER cluster = 0, temp; unsigned long current = 0; struct DirectoryPosition pos; struct DirectoryEntry* entry; struct StackElement element; struct PipeStruct pipe, *ppipe = &pipe; pipe.func = func; pipe.structure = structure; pipe.stop = FALSE; if (!TraverseRootDir(handle, ActionWalker, (void**)&ppipe, TRUE)) return FALSE; if (pipe.stop) return TRUE; stack = (struct StackElement*)FTEAlloc(DIR_STACK_DEPTH * sizeof(struct StackElement)); if (!stack) return FALSE; for (;;) { /* If there still are sub directories in this directory, push the cluster of that directory. */ pos.sector = 0; pos.offset = 0; if (!GetNthSubDirectoryPosition(handle, cluster, current, &pos)) { FTEFree(stack); return FALSE; } if ((pos.sector != 0) || (pos.offset != 0)) { entry = AllocateDirectoryEntry(); if (!entry) { FTEFree(stack); return FALSE; } if (top < DIR_STACK_DEPTH) { element.cluster = cluster; element.index = current; PushDirectoryEntry(stack, &top, &element); } else { FreeDirectoryEntry(entry); /* Directory level to deep!? */ FTEFree(stack); return FALSE; } if (!GetDirectory(handle, &pos, entry)) { FreeDirectoryEntry(entry); FTEFree(stack); return FALSE; } /* Descend in the directory tree and call the function for every directory entry in that directory. */ temp = GetFirstCluster(entry); /* Don't descend in any directory that is invalid. */ if (temp && FAT_NORMAL(temp) && IsLabelValid(handle, temp)) { current = 0; cluster = temp; if (!TraverseSubdir(handle, cluster, ActionWalker, (void**) &ppipe, TRUE)) { FreeDirectoryEntry(entry); FTEFree(stack); return FALSE; } if (pipe.stop) { FreeDirectoryEntry(entry); FTEFree(stack); return TRUE; } } else /* cluster not valid, leave this directory */ { if (top-1 > 0) /* Be carefull when there are no sub directories in the volume. */ { PopDirectoryEntry(stack, &top, &element); PopDirectoryEntry(stack, &top, &element); current = element.index+1; /* Then find the next sub directory. */ cluster = element.cluster; } else { FreeDirectoryEntry(entry); break; } } FreeDirectoryEntry(entry); } /* If there are no more sub directories in the current directory, pop the current directory from the stack. */ else { if (top) /* Be carefull when there are no sub directories in the volume. */ { PopDirectoryEntry(stack, &top, &element); current = element.index+1; /* Then find the next sub directory. */ cluster = element.cluster; } else { break; } } } FTEFree(stack); 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 FilesSummaryGetter(RDWRHandle handle, struct DirectoryPosition* position, struct DirectoryEntry* entry, void** structure) { CLUSTER firstcluster; struct FilesSummary** info = (struct FilesSummary**) structure; unsigned long dirsize=0, *pdirsize = &dirsize, bytespercluster, labelsinfat; position = position; bytespercluster = GetSectorsPerCluster(handle) * BYTESPERSECTOR; if (!bytespercluster) return FAIL; if (entry->attribute & FA_LABEL) return TRUE; if (IsLFNEntry(entry)) return TRUE; if (IsDeletedLabel(*entry)) return TRUE; if (entry->attribute & FA_DIREC) { if (IsCurrentDir(*entry)) return TRUE; if (IsPreviousDir(*entry)) return TRUE; (*info)->DirectoryCount++; labelsinfat = GetLabelsInFat(handle); if (!labelsinfat) return FAIL; fatmap = CreateBitField(labelsinfat); if (!fatmap) return FAIL; firstcluster = GetFirstCluster(entry); if (!TraverseSubdir(handle, firstcluster, DirSizeGetter, (void**) &pdirsize, FALSE)) { return FAIL; } DestroyBitfield(fatmap); AddUlongLong(&(*info)->SizeOfDirectories[0],dirsize); return TRUE; /* Not taking directories into account when gathering information on files. */ } (*info)->TotalFileCount++; AddUlongLong(&(*info)->TotalSizeofFiles[0],entry->filesize); AddUlongLong(&(*info)->SizeOfAllFiles[0], CalculateClustersSize(entry->filesize, bytespercluster)); if (entry->attribute & FA_SYSTEM) { (*info)->SystemFileCount++; AddUlongLong(&(*info)->SizeOfSystemFiles[0], CalculateClustersSize(entry->filesize, bytespercluster)); } if (entry->attribute & FA_HIDDEN) { (*info)->HiddenFileCount++; AddUlongLong(&(*info)->SizeOfHiddenFiles[0], CalculateClustersSize(entry->filesize, bytespercluster)); } 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; }