STATIC BOOL SubdirGetter(RDWRHandle handle, struct DirectoryPosition* pos, void** buffer) { struct DirectoryEntry entry; struct Pipe** pipe = (struct Pipe**) buffer; handle = handle; if (!GetDirectory(handle, pos, &entry)) return FAIL; if (IsLFNEntry(&entry) || (IsDeletedLabel(entry)) || (IsCurrentDir(entry)) || (IsPreviousDir(entry))) { return TRUE; } if (entry.attribute & FA_DIREC) { if ((*pipe)->n == (*pipe)->counter) { memcpy((*pipe)->pos, pos, sizeof(struct DirectoryPosition)); return FALSE; } (*pipe)->counter++; } return TRUE; }
BOOL GetNthSubDirectoryPosition(RDWRHandle handle, CLUSTER cluster, unsigned long n, struct DirectoryPosition* result) { int counter = 0; struct DirectoryPosition pos; struct DirectoryEntry* entry; entry = AllocateDirectoryEntry(); if (!entry) return FALSE; n++; /* n is 0 based */ while (n) { pos.sector = 0; pos.offset = 0; if (!GetNthDirectoryPosition(handle, cluster, counter++, &pos)) { FreeDirectoryEntry(entry); return FALSE; } if ((pos.sector == 0) && (pos.offset == 0)) /* Not found*/ { FreeDirectoryEntry(entry); return TRUE; } if (!GetDirectory(handle, &pos, entry)) { FreeDirectoryEntry(entry); return TRUE; } if (!IsLFNEntry((entry)) && (entry->attribute & FA_DIREC) && (!IsDeletedLabel(*entry)) && (!IsCurrentDir(*entry)) && (!IsPreviousDir(*entry))) { n--; } } memcpy(result, &pos, sizeof(struct DirectoryPosition)); FreeDirectoryEntry(entry); return TRUE; }
static BOOL VolumeGetter(RDWRHandle handle, struct DirectoryPosition* pos, void** structure) { struct Pipe *pipe = *((struct Pipe**) structure); struct DirectoryEntry* entry; assert (pos->sector && (pos->offset < 16)); entry = AllocateDirectoryEntry(); if (!entry) RETURN_FTEERR(FAIL); if (!GetDirectory(handle, pos, entry)) { FreeDirectoryEntry(entry); RETURN_FTEERR(FAIL); } if (IsLFNEntry(entry)) { FreeDirectoryEntry(entry); return TRUE; } if (IsDeletedLabel(*entry)) { FreeDirectoryEntry(entry); return TRUE; } if (entry->attribute & FA_LABEL) { pipe->found = TRUE; memcpy(pipe->pos, pos, sizeof(struct DirectoryPosition)); FreeDirectoryEntry(entry); RETURN_FTEERR(FALSE); } FreeDirectoryEntry(entry); return TRUE; }
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; }
BOOL CheckLFNInDirectory(RDWRHandle handle, struct DirectoryPosition* pos, struct DirectoryEntry* entry, char* filename, BOOL fixit) { BOOL retVal = TRUE; unsigned char ChkSum; struct LongFileNameEntry* lfnentry = (struct LongFileNameEntry*) entry; if (IsDeletedLabel(*entry)) { /* Check for the most common of LFN faults, deleting a file in plain DOS. I.e. the SFN is deleted, but the associated LFN entries not. */ if (LFNState == SCANNING_LFN_STATE) { ShowParentViolation(handle, filename, "%s contains a number of invalid long file name entries"); if (fixit) { if (!RemoveInvalidLFNs(handle, LFNCluster, &LFNStart, &PrevPos)) return FAIL; } LFNState = SCANNING_SFN_STATE; /* Reset the state machine */ return FALSE; } return TRUE; } if ((entry->attribute & FA_LABEL) && (!IsLFNEntry(entry))) return TRUE; if (!IsLFNEntry(entry)) /* A short filename entry */ { if (LFNState == SCANNING_LFN_STATE) { /* Calculate the checksum for this SFN entry */ ChkSum = CalculateSFNCheckSum(entry); if ((LFNIndex != 0) || (ChkSum != LFNChkSum)) { ShowParentViolation(handle, filename, "%s contains a number of invalid long file name entries"); if (fixit) { if (!RemoveInvalidLFNs(handle, LFNCluster, &LFNStart, &PrevPos)) return FAIL; } retVal = FALSE; } LFNState = SCANNING_SFN_STATE; } } else if (IsFirstLFNEntry(lfnentry)) /* First LFN entry */ { if (LFNState == SCANNING_LFN_STATE) { ShowParentViolation(handle, filename, "%s contains a number of invalid long file name entries"); if (fixit) { if (!RemoveInvalidLFNs(handle, LFNCluster, &LFNStart, &PrevPos)) return FAIL; } retVal = FALSE; } /* Even if the previous entry was wrong, the new one may be correct */ memcpy(&LFNStart, pos, sizeof(struct DirectoryPosition)); LFNState = SCANNING_LFN_STATE; LFNIndex = GetNrOfLFNEntries(lfnentry)-1; LFNChkSum = lfnentry->checksum; } else /* LFN entry in the middle. */ { if (LFNState == SCANNING_SFN_STATE) { memcpy(&LFNStart, pos, sizeof(struct DirectoryPosition)); } if ((LFNState == SCANNING_SFN_STATE) || (lfnentry->NameIndex != LFNIndex) || (LFNIndex == 0) || (lfnentry->checksum != LFNChkSum)) { ShowParentViolation(handle, filename, "%s contains a number of invalid long file name entries"); if (fixit) { if (!RemoveInvalidLFNs(handle, LFNCluster, &LFNStart, pos)) return FAIL; } retVal = FALSE; } else { LFNIndex--; } } memcpy(&PrevPos, pos, sizeof(struct DirectoryPosition)); return retVal; }
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; }