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; }
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 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 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 WalkDirectoryTree(RDWRHandle handle, int (*func) (RDWRHandle handle, struct DirectoryPosition* position, void** structure), void** structure) { int top = 0; struct StackElement* stack; CLUSTER cluster = 0, temp; unsigned long current = 0; struct DirectoryPosition pos; struct DirectoryEntry* entry; struct StackElement element; struct PipeStruct pipe, *ppipe = &pipe; pipe.func = func; pipe.structure = structure; pipe.stop = FALSE; if (!TraverseRootDir(handle, ActionWalker, (void**)&ppipe, TRUE)) return FALSE; if (pipe.stop) return TRUE; stack = (struct StackElement*)FTEAlloc(DIR_STACK_DEPTH * sizeof(struct StackElement)); if (!stack) return FALSE; for (;;) { /* If there still are sub directories in this directory, push the cluster of that directory. */ pos.sector = 0; pos.offset = 0; if (!GetNthSubDirectoryPosition(handle, cluster, current, &pos)) { FTEFree(stack); return FALSE; } if ((pos.sector != 0) || (pos.offset != 0)) { entry = AllocateDirectoryEntry(); if (!entry) { FTEFree(stack); return FALSE; } if (top < DIR_STACK_DEPTH) { element.cluster = cluster; element.index = current; PushDirectoryEntry(stack, &top, &element); } else { FreeDirectoryEntry(entry); /* Directory level to deep!? */ FTEFree(stack); return FALSE; } if (!GetDirectory(handle, &pos, entry)) { FreeDirectoryEntry(entry); FTEFree(stack); return FALSE; } /* Descend in the directory tree and call the function for every directory entry in that directory. */ temp = GetFirstCluster(entry); /* Don't descend in any directory that is invalid. */ if (temp && FAT_NORMAL(temp) && IsLabelValid(handle, temp)) { current = 0; cluster = temp; if (!TraverseSubdir(handle, cluster, ActionWalker, (void**) &ppipe, TRUE)) { FreeDirectoryEntry(entry); FTEFree(stack); return FALSE; } if (pipe.stop) { FreeDirectoryEntry(entry); FTEFree(stack); return TRUE; } } else /* cluster not valid, leave this directory */ { if (top-1 > 0) /* Be carefull when there are no sub directories in the volume. */ { PopDirectoryEntry(stack, &top, &element); PopDirectoryEntry(stack, &top, &element); current = element.index+1; /* Then find the next sub directory. */ cluster = element.cluster; } else { FreeDirectoryEntry(entry); break; } } FreeDirectoryEntry(entry); } /* If there are no more sub directories in the current directory, pop the current directory from the stack. */ else { if (top) /* Be carefull when there are no sub directories in the volume. */ { PopDirectoryEntry(stack, &top, &element); current = element.index+1; /* Then find the next sub directory. */ cluster = element.cluster; } else { break; } } } FTEFree(stack); return TRUE; }