BOOL BackupBoot(RDWRHandle handle) { int fatlabelsize = GetFatLabelSize(handle); SECTOR BackupSector; struct BootSectorStruct* boot; BOOL retVal = TRUE; if (fatlabelsize == FAT32) { BackupSector = GetFAT32BackupBootSector(handle); if (!BackupSector) { RETURN_FTEERR(FALSE); } boot = AllocateBootSector(); if (!boot) RETURN_FTEERR(FALSE); if (!ReadBootSector(handle, boot) || (WriteSectors(handle, 1, BackupSector, (void*) boot, WR_UNKNOWN) == -1)) { RETURN_FTEERR(FALSE); } FreeBootSector(boot); } RETURN_FTEERR(retVal); }
long low_dircount(RDWRHandle handle, CLUSTER cluster, char attribute) { int fatlabelsize; struct PipeStruct pipe, *ppipe = &pipe; if (cluster == 0) { fatlabelsize = GetFatLabelSize(handle); switch (fatlabelsize) { case FAT12: case FAT16: return CountEntriesInRootDirectory(handle, attribute); case FAT32: cluster = GetFAT32RootCluster(handle); if (cluster) break; else return FAIL; default: return FAIL; } } pipe.count = 0; pipe.attribute = attribute; if (!TraverseSubdir(handle, cluster, counter, (void**) &ppipe, TRUE)) return FAIL; return pipe.count; }
BOOL GetNthDirectoryPosition(RDWRHandle handle, CLUSTER cluster, unsigned long n, struct DirectoryPosition* result) { int fatlabelsize; struct Pipe pipe, *ppipe = &pipe; pipe.n = n; pipe.counter = 0; pipe.pos = result; if (cluster == 0) { fatlabelsize = GetFatLabelSize(handle); switch (fatlabelsize) { case FAT12: case FAT16: { BOOL retVal; struct DirectoryPosition pos; struct DirectoryEntry* entry; retVal = GetRootDirPosition(handle, (unsigned short) n, &pos); if (retVal) { entry = AllocateDirectoryEntry(); if (!entry) return FALSE; if (!GetDirectory(handle, &pos, entry)) { FreeDirectoryEntry(entry); return FALSE; } if (entry->filename[0] != LASTLABEL) { memcpy(result, &pos, sizeof(struct DirectoryPosition)); } FreeDirectoryEntry(entry); } return retVal; } case FAT32: cluster = GetFAT32RootCluster(handle); if (cluster) break; else return FALSE; default: return FALSE; } } return TraverseSubdir(handle, cluster, positiongetter, (void**) &ppipe, TRUE); }
BOOL PerformRootDirChecks(RDWRHandle handle, BOOL fixit) { int fatlabelsize; struct Pipe pipe, *ppipe = &pipe; fatlabelsize = GetFatLabelSize(handle); switch (fatlabelsize) { case FAT12: case FAT16: pipe.fixit = fixit; pipe.result = TRUE; InitClusterEntryChecking(handle, 0, "The root directory"); switch (PreProcessClusterEntryChecking(handle, 0, "The root directory", fixit)) { case FALSE: pipe.result = FALSE; break; case FAIL: DestroyClusterEntryChecking(handle, 0, "The root directory"); return FAIL; } if (!TraverseRootDir(handle, RootDirChecker, (void**) &ppipe, TRUE)) { DestroyClusterEntryChecking(handle, 0, "The root directory"); return FAIL; } switch (PostProcessClusterEntryChecking(handle, 0, "The root directory", fixit)) { case FALSE: pipe.result = FALSE; break; case FAIL: pipe.result = FAIL; } DestroyClusterEntryChecking(handle, 0, "The root directory"); return pipe.result; case FAT32: return ScanFileChain(handle, 0, (struct DirectoryPosition*) NULL, (struct DirectoryEntry*) NULL, "\\", fixit); default: return FAIL; } }
BOOL MultipleBootCheck(RDWRHandle handle) { BOOL retval; int fatlabelsize = GetFatLabelSize(handle); SECTOR BackupSector; struct BootSectorStruct* boot1, *boot2; if (fatlabelsize == FAT32) { BackupSector = GetFAT32BackupBootSector(handle); if (!BackupSector) { RETURN_FTEERR(FAIL); } boot1 = AllocateBootSector(); if (!boot1) RETURN_FTEERR(FAIL); boot2 = AllocateBootSector(); if (!boot2) { FreeBootSector(boot1); RETURN_FTEERR(FAIL); } if (!ReadBootSector(handle, boot1) == -1) { FreeBootSector(boot1); RETURN_FTEERR(FAIL); } if (!ReadSectors(handle, 1, BackupSector, (void*) boot2) == -1) { FreeBootSector(boot1); FreeBootSector(boot2); RETURN_FTEERR(FAIL); } retval = (memcmp(boot1, boot2, BYTESPERSECTOR) == 0); FreeBootSector(boot1); FreeBootSector(boot2); return retval; } RETURN_FTEERR((fatlabelsize) ? TRUE : FAIL); }
static char* GetCorrectFSString(RDWRHandle handle) { switch (GetFatLabelSize(handle)) { case FAT12: return fat12str; case FAT16: return fat16str; case FAT32: return fat32str; default: return NULL; } }
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; } }
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; }
BOOL GetNthCluster(RDWRHandle handle, CLUSTER n, CLUSTER* label) { CLUSTER result; int fatlabelsize = GetFatLabelSize(handle); if (!ReadFatLabel(handle, n, &result)) RETURN_FTEERROR(FALSE); switch (fatlabelsize) { case FAT12: if (FAT12_FREE(result)) { *label = FAT_FREE_LABEL; return TRUE; } if (FAT12_BAD(result)) { *label = FAT_BAD_LABEL; return TRUE; } if (FAT12_LAST(result)) { *label = FAT_LAST_LABEL; return TRUE; } break; case FAT16: if (FAT16_FREE(result)) { *label = FAT_FREE_LABEL; return TRUE; } if (FAT16_BAD(result)) { *label = FAT_BAD_LABEL; return TRUE; } if (FAT16_LAST(result)) { *label = FAT_LAST_LABEL; return TRUE; } break; case FAT32: if (FAT32_FREE(result)) { *label = FAT_FREE_LABEL; return TRUE; } if (FAT32_BAD(result)) { *label = FAT_BAD_LABEL; return TRUE; } if (FAT32_LAST(result)) { *label = FAT_LAST_LABEL; return TRUE; } break; } *label = result; return TRUE; }