static BOOL counter(RDWRHandle handle, struct DirectoryPosition* pos, void** buffer) { struct DirectoryEntry* entry; struct PipeStruct* p = *((struct PipeStruct**) buffer); entry = AllocateDirectoryEntry(); if (!entry) return FAIL; if (!GetDirectory(handle, pos, entry)) { FreeDirectoryEntry(entry); return FAIL; } if (entry->attribute == LFN_ATTRIBUTES) { if (IsLFNEntry(entry)) p->count++; } else if ((entry->attribute & p->attribute) || (p->attribute == -1)) { p->count++; } FreeDirectoryEntry(entry); return TRUE; }
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; }
void MemorySortEntries(struct DirectoryEntry* entries, int amofentries) { int i=0, realentries = 0; struct DirectoryEntry* temp = entries; SetResourceConfiguration(&MemConfig); if (amofentries == 0) return; if (IsCurrentDir(entries[0])) { if (amofentries == 1) return; entries++; i++; } if (IsPreviousDir(entries[0])) { entries++; i++; } for (; i < amofentries; i++) if (IsLFNEntry(&temp[i]) == 0) realentries++; if (realentries) SelectionSortEntries(entries, realentries); }
/******************************************************************* ** EntryLength ******************************************************************** ** Returns the number of elementary entries in a, possibly LFN, entry. ********************************************************************/ unsigned long EntryLength(struct DirectoryEntry* entry) { int counter = 1; assert(entry); while (IsLFNEntry(entry)) { entry++; counter++; } return counter; }
static struct DirectoryEntry* PtrGetEntry(struct DirectoryEntry* pEntries, unsigned pos) { unsigned i; for (i = 0; i < pos; i++) { while (IsLFNEntry(pEntries)) pEntries++; pEntries++; } return pEntries; }
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; }
static BOOL ExistanceChecker(RDWRHandle handle, struct DirectoryPosition* pos, void** structure) { struct Pipe* pipe = *((struct Pipe**) structure); struct DirectoryEntry entry; if (!GetDirectory(handle, pos, &entry)) RETURN_FTEERROR(FAIL); if (IsLFNEntry(&entry)) return TRUE; if ((strnicmp(pipe->extension, entry.extension, 3) == 0) && (strnicmp(pipe->filename, entry.filename, 8) == 0)) { pipe->exists = TRUE; return FALSE; } return TRUE; }
static long CountEntriesInRootDirectory(RDWRHandle handle, char attribute) { long count = 0, i; struct DirectoryEntry* entry; long rootcount = GetNumberOfRootEntries(handle); if (!rootcount) return FAIL; entry = AllocateDirectoryEntry(); if (!entry) return FAIL; for (i = 0; i < rootcount; i++) { if (!ReadDirEntry(handle, i, entry)) { FreeDirectoryEntry(entry); return FAIL; } if (IsLastLabel(*entry)) { FreeDirectoryEntry(entry); return count; } if (entry->attribute == LFN_ATTRIBUTES) { if (IsLFNEntry(entry)) count++; } else if ((entry->attribute & attribute) || (attribute == -1)) { count++; } } FreeDirectoryEntry(entry); return rootcount; }
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 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 LFNRemover(RDWRHandle handle, struct DirectoryPosition* pos, void** structure) { struct RemovePipe* pipe = *((struct RemovePipe**) structure); struct DirectoryEntry entry; if (!GetDirectory(handle, pos, &entry)) return FAIL; /* Check the range in which we have to delete the long file name entries */ if (!pipe->hasstarted) /* Outside the interval */ { /* Check wether the starting position was found. */ if (memcmp(pos, pipe->begin, sizeof(struct DirectoryPosition)) == 0) pipe->hasstarted = TRUE; } if (!IsLFNEntry(&entry)) return TRUE; if (pipe->hasstarted) /* Inside the interval, first create a dummy file name entry. */ { struct tm* tmp; time_t now; /* file name and extension, 0xe5 indicates file removed. */ memcpy(entry.filename, "å" "LFNRMVD", 8); memset(entry.extension, ' ', 3); /* attribute */ entry.attribute = 0; /* first cluster */ SetFirstCluster(2, &entry); /* file size */ entry.filesize = 0; /* NT reserved field */ entry.NTReserved = 0; /* Mili second stamp */ entry.MilisecondStamp = 0; /* Last access date */ memset(&entry.LastAccessDate, 0, sizeof(struct PackedDate)); /* Time last modified */ memset(&entry.timestamp, 0, sizeof(struct PackedTime)); /* Date last modified */ memset(&entry.datestamp, 0, sizeof(struct PackedDate)); /* Get the current date and time and store it in the last write time and date. */ time(&now); tmp = localtime(&now); entry.LastWriteTime.second = tmp->tm_sec / 2; if (entry.LastWriteTime.second == 30) /* DJGPP help says range is [0..60] */ entry.LastWriteTime.second--; entry.LastWriteTime.minute = tmp->tm_min; entry.LastWriteTime.hours = tmp->tm_hour; entry.LastWriteDate.day = tmp->tm_mday; entry.LastWriteDate.month = tmp->tm_mon + 1; if (tmp->tm_year < 80) entry.LastWriteDate.year = 0; else entry.LastWriteDate.year = (tmp->tm_year+1900)-1980; if (!WriteDirectory(handle, pos, &entry)) return FAIL; /* Check wether the ending position was found. */ if ((pipe->end != NULL) && (memcmp(pos, pipe->end, sizeof(struct DirectoryPosition)) == 0)) { return 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; }