void ShowParentViolation(RDWRHandle handle, char* filename, char* message) { int i; strcpy(FilePrintBuffer, filename); for (i = strlen(FilePrintBuffer)-1; i >= 0; i--) { if (FilePrintBuffer[i] == '\\') { FilePrintBuffer[i] = '\0'; break; } } if (i <= 0) { ShowFileNameViolation(handle, "The root directory", message); } else { ShowFileNameViolation(handle, FilePrintBuffer, message); } }
BOOL PostProcesLFNChecking(RDWRHandle handle, CLUSTER cluster, char* filename, BOOL fixit) { /* After cheking the directory the state machine must be in SFN state. */ if ((LFNState != SCANNING_SFN_STATE) || (LFNIndex > 0))/* And the right number of LFN entries must be found. */ { ShowFileNameViolation(handle, filename, "%s contains a number of invalid long file name entries"); if (fixit) { if (!RemoveInvalidLFNs(handle, cluster, &LFNStart, NULL)) return FAIL; } return 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; }
BOOL CheckDirectoryForDoubles(RDWRHandle handle, struct DirectoryPosition* pos, struct DirectoryEntry* entry, char* filename, BOOL fixit) { unsigned slot, now, previous = 0xffff; if ((entry->attribute & FA_LABEL) || IsLFNEntry(entry) || IsDeletedLabel(*entry)) { return TRUE; } slot = HashFilename(entry->filename); /* Now walk the list starting at the head in the hash table. */ now = hashtable[slot].ptr; while (now != 0xFFFF) { if ((memcmp(entry->filename, filenamearray[now].filename, 8) == 0) && (memcmp(entry->extension, filenamearray[now].extension, 3) == 0)) { /* Print out the message and the file name */ ShowFileNameViolation(handle, filename, "Found double file %s"); if (fixit) { if (!RenameDoubleFile(handle, pos, entry, surroundingdir)) return FAIL; } return FALSE; } previous = now; now = filenamearray[now].next; } /* Not found, add it to the end of the list */ if (previous == 0xFFFF) /* First one in the slot. */ { hashtable[slot].ptr = ArrayFreePointer; } else { /* We already have the end of the list */ filenamearray[previous].next = ArrayFreePointer; } memcpy(filenamearray[ArrayFreePointer].filename, entry->filename, 8); memcpy(filenamearray[ArrayFreePointer].extension, entry->extension, 3); filenamearray[ArrayFreePointer].next = 0xFFFF; ArrayFreePointer++; return TRUE; }
BOOL CheckEntryForInvalidChars(RDWRHandle handle, struct DirectoryPosition* pos, struct DirectoryEntry* direct, char* filename, BOOL fixit) { int i; BOOL invalidname = FALSE; BOOL InRoot; struct DirectoryEntry entry; memcpy(&entry, direct, sizeof(struct DirectoryEntry)); if (((entry.attribute & FA_LABEL) == 0) && /* Not checking volume labels */ !IsDeletedLabel(entry)) { if (IsPreviousDir(entry) || /* .. */ IsCurrentDir(entry)) /* . */ { /* See wether the given directory entry is in the root directory */ InRoot = IsRootDirPosition(handle, pos); if (InRoot == FAIL) return FAIL; /* All the '.' and '..' entries must be directories */ if (((entry.attribute & FA_DIREC) == 0) || (InRoot)) { if (IsCurrentDir(entry)) { if (InRoot) { ShowFileNameViolation(handle, "", "The root directory contains an '.' entry"); } else { ShowParentViolation(handle, filename, "%s contains an '.' entry that is not a directory"); } memcpy(entry.filename, "DOT ", 8); } else { if (InRoot) { ShowFileNameViolation(handle, "", "The root directory contains an '..' entry"); } else { ShowParentViolation(handle, filename, "%s contains an '..' entry that is not a directory"); } memcpy(entry.filename, "DOTDOT ", 8); } if (fixit) { memcpy(entry.extension, " ", 3); if (!RenameFile(handle, pos, &entry, DirCluster)) /* Write the changes to disk */ return FAIL; } return FALSE; } /* Check wether you realy have '.' and '..' */ if (IsCurrentDir(entry)) { if ((memcmp(entry.filename, ". ", 8) != 0) || (memcmp(entry.extension, " ", 3) != 0)) { ShowFileNameViolation(handle, filename, "%s contains invalid char(s)"); if (fixit) { memcpy(entry.filename, ". ", 8); memcpy(entry.extension, " ", 3); if (!RenameFile(handle, pos, &entry, DirCluster)) /* Write the changes to disk */ return FAIL; } } } if (IsPreviousDir(entry)) { if ((memcmp(entry.filename, ".. ", 8) != 0) || (memcmp(entry.extension, " ", 3) != 0)) { ShowFileNameViolation(handle, filename, "%s contains invalid char(s)"); if (fixit) { memcpy(entry.filename, ".. ", 8); memcpy(entry.extension, " ", 3); if (!RenameFile(handle, pos, &entry, DirCluster)) /* Write the changes to disk */ return FAIL; } } } } else { if (entry.filename[0] == ' ') { invalidname = TRUE; entry.filename[0] = 'A'; } /* file name */ for (i = 0; i < 8; i++) { if ((strchr(INVALIDSFNCHARS, entry.filename[i])) || (((unsigned char)(entry.filename[i]) < 0x20) && (entry.filename[i] != 0x05)) || (islower(entry.filename[i]))) { entry.filename[i] = 'A'; invalidname = TRUE; } } /* extension */ for (i = 0; i < 3; i++) { if ((strchr(INVALIDSFNCHARS, entry.extension[i])) || (((unsigned char)(entry.extension[i]) < 0x20) && (entry.extension[i] != 0x05)) || (islower(entry.extension[i]))) { entry.extension[i] = 'A'; invalidname = TRUE; } } if (invalidname) { ShowFileNameViolation(handle, filename, "%s contains invalid char(s)"); if (fixit) { if (!RenameFile(handle, pos, &entry, DirCluster)) /* Write the changes to disk */ return FAIL; } return FALSE; } } } return TRUE; }