BOOL CopyConsecutiveClusters(RDWRHandle handle, CLUSTER source, CLUSTER dest, unsigned long length) { SECTOR ssource, sdest; unsigned long sectorspercluster, i, blocks; unsigned rest; ssource = ConvertToDataSector(handle, source); if (!ssource) RETURN_FTEERROR(FALSE); sdest = ConvertToDataSector(handle, dest); if (!sdest) RETURN_FTEERROR(FALSE); sectorspercluster = GetSectorsPerCluster(handle); if (!sectorspercluster) RETURN_FTEERROR(FALSE); blocks = (length * sectorspercluster) / 32768L; rest = (unsigned)((length * sectorspercluster) % 32768L); for (i=0; i<blocks; i++) { if (!CopySectors(handle, ssource, sdest, 32768U)) RETURN_FTEERROR(FALSE); ssource += 32768L; sdest += 32768L; } if (rest > 0) { if (!CopySectors(handle, ssource, sdest, rest)) RETURN_FTEERROR(FALSE); } return TRUE; }
BOOL PreReadClusterSequence(RDWRHandle handle, CLUSTER start, unsigned long length) { char* ReadBuf; unsigned BufSize; unsigned long blocks, i, sectorstoread; unsigned rest; unsigned char sectorspercluster; SECTOR startsector; if (!CacheActive()) return TRUE; if (length == 0) return TRUE; sectorspercluster = GetSectorsPerCluster(handle); if (!sectorspercluster) return FALSE; sectorstoread = length * sectorspercluster; startsector = ConvertToDataSector(handle, start); if (!startsector) return FALSE; ReadBuf = AllocateReadBuf(sectorstoread * BYTESPERSECTOR, &BufSize); BufSize /= BYTESPERSECTOR; blocks = (length * sectorspercluster) / BufSize; rest = (unsigned)((length * sectorspercluster) % BufSize); for (i = 0; i < blocks; i++) { if (!OnlyFilledRead(handle, startsector, BufSize, ReadBuf) == -1) { FreeReadBuf(ReadBuf); return FALSE; } startsector += BufSize; } if (rest) { if (!OnlyFilledRead(handle, startsector, rest, ReadBuf) == -1) { FreeReadBuf(ReadBuf); return FALSE; } } FreeReadBuf(ReadBuf); return TRUE; }
static BOOL ClusterPreReader(RDWRHandle handle, CLUSTER label, SECTOR datasector, void** structure) { SECTOR firstsector; CLUSTER cluster; unsigned char sectorspercluster; struct Pipe* pipe = *((struct Pipe**) structure); if (label); sectorspercluster = GetSectorsPerCluster(handle); if (!sectorspercluster) return FAIL; if (pipe->maxindex == 0) /* cluster > read buf */ { if (!PreReadLargeCluster(handle, datasector, sectorspercluster, pipe->buf, pipe->bufsize)) return FAIL; } else { cluster = DataSectorToCluster(handle, datasector); if ((pipe->index > 0) && ((pipe->prevcluster != cluster-1) || (pipe->index == pipe->maxindex))) { firstsector = ConvertToDataSector(handle, pipe->firstcluster); if (!firstsector) return FAIL; if (ReadSectors(handle, pipe->index*sectorspercluster, firstsector, pipe->buf) == -1) { return FAIL; } pipe->index = 0; pipe->firstcluster = cluster; } else { pipe->index++; } } pipe->prevcluster = cluster; return TRUE; }
BOOL PreReadClusterChain(RDWRHandle handle, CLUSTER start) { SECTOR firstsector; char* ReadBuf; struct Pipe pipe, *ppipe = &pipe; unsigned char sectorspercluster; unsigned BufSize; if (!CacheActive()) return TRUE; sectorspercluster = GetSectorsPerCluster(handle); if (!sectorspercluster) return FALSE; ReadBuf = AllocateReadBuf(MAX_ALLOCATING, &BufSize); BufSize /= BYTESPERSECTOR; pipe.buf = ReadBuf; pipe.bufsize = BufSize; pipe.index = 0; pipe.maxindex = BufSize / sectorspercluster; pipe.prevcluster = 0; pipe.firstcluster = start; if (!FileTraverseFat(handle, start, ClusterPreReader, (void**) &ppipe)) { FreeReadBuf(ReadBuf); return FALSE; } if (pipe.index) { firstsector = ConvertToDataSector(handle, pipe.firstcluster); if (!firstsector) { FreeReadBuf(ReadBuf); return FALSE; } if (ReadSectors(handle, pipe.index*sectorspercluster, firstsector, pipe.buf) == -1) { FreeReadBuf(ReadBuf); return FALSE; } } FreeReadBuf(ReadBuf); return TRUE; }
static BOOL CopyClusters(RDWRHandle handle, CLUSTER source, CLUSTER dest, unsigned long length) { SECTOR ssource, sdest; unsigned long sectorspercluster, i, blocks, totallength; unsigned rest; ssource = ConvertToDataSector(handle, source); if (!ssource) RETURN_FTEERROR(FALSE); sdest = ConvertToDataSector(handle, dest); if (!sdest) RETURN_FTEERROR(FALSE); sectorspercluster = GetSectorsPerCluster(handle); if (!sectorspercluster) RETURN_FTEERROR(FALSE); totallength = length * sectorspercluster; blocks = totallength / COPY_BLOCK_SIZE; rest = (unsigned)(totallength % COPY_BLOCK_SIZE); for (i=0; i<blocks; i++) { if (!CopySectors(handle, ssource, sdest, COPY_BLOCK_SIZE)) RETURN_FTEERROR(FALSE); ssource += COPY_BLOCK_SIZE; sdest += COPY_BLOCK_SIZE; } if (rest > 0) { if (!CopySectors(handle, ssource, sdest, rest)) RETURN_FTEERROR(FALSE); } return TRUE; }
static BOOL DirSizeGetter(RDWRHandle handle, struct DirectoryPosition* pos, void** structure) { BOOL InRoot; unsigned long **dirsize = (unsigned long**) structure; unsigned char sectorspercluster; CLUSTER label; pos = pos, handle = handle; /* Check for loops in the directory structure */ InRoot = IsRootDirPosition(handle, pos); if (InRoot == -1) return FAIL; if (!InRoot && (pos->offset == 0)) { sectorspercluster = GetSectorsPerCluster(handle); if (!sectorspercluster) return FAIL; if ((pos->sector % sectorspercluster) == 0) { label = DataSectorToCluster(handle, pos->sector); if (!label) return FAIL; if (GetBitfieldBit(fatmap, label)) { return FALSE; } SetBitfieldBit(fatmap, label); } } **dirsize += sizeof(struct DirectoryEntry); return TRUE; }
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; }
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 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; }
/* 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; }