def findEntry(name, flags = FE_EITHER)
      de = nil # found directory entry.
      skip_next = found = false
      offset = 0

      # Look for appropriate records.
      0.step(@data.length - 1, DIR_ENT_SIZE) do|offset|
        # Check allocation status (ignore if deleted, done if not allocated).
        alloc_flags = @data[offset]
        next if alloc_flags == DirectoryEntry::AF_DELETED
        break if alloc_flags == DirectoryEntry::AF_NOT_ALLOCATED

        # Skip LFN entries unless it's the first (last iteration already chewed them all up).
        attrib = @data[offset + ATTRIB_OFFSET]
        if attrib == DirectoryEntry::FA_LFN && (alloc_flags & DirectoryEntry::AF_LFN_LAST != DirectoryEntry::AF_LFN_LAST)
          # Also skip the next entry (it's the base entry for the last dir ent).
          skip_next = true; next
        end
        if skip_next
          skip_next = false; next
        end

        # If a specific type of record was requested, look for only that type.
        # NOTE: You know, it's possible to look ahead and see what the base entry is.
        if flags != FE_EITHER && attrib != DirectoryEntry::FA_LFN
          next if flags == FE_DIR && (attrib & DirectoryEntry::FA_DIRECTORY == 0)
          next if flags == FE_FILE && (attrib & DirectoryEntry::FA_DIRECTORY != 0)
        end

        # Potential match... get a DirectoryEntry & stop if found.
        de = DirectoryEntry.new(@data[offset, MAX_ENT_SIZE])
        # TODO: - what if the name ends with a dot & there's another dot in the name?
        if de.name.downcase == name.downcase || de.shortName.downcase == name.downcase
          found = true
          break
        end
      end
      return nil unless found
      parentLoc = offset.divmod(@bs.bytesPerCluster)
      de.parentCluster = @all_clusters[parentLoc[0]].number
      de.parentOffset = parentLoc[1]
      de
    end
def findEntry(name, flags = FE_EITHER)
      de = nil # found directory entry.
      skip_next = found = false
      offset = 0

      # Look for appropriate records.
      0.step(@data.length - 1, DIR_ENT_SIZE) do|offset|
        # Check allocation status (ignore if deleted, done if not allocated).
        alloc_flags = @data[offset]
        next if alloc_flags == DirectoryEntry::AF_DELETED
        break if alloc_flags == DirectoryEntry::AF_NOT_ALLOCATED

        # Skip LFN entries unless it's the first (last iteration already chewed them all up).
        attrib = @data[offset + ATTRIB_OFFSET]
        if attrib == DirectoryEntry::FA_LFN && (alloc_flags & DirectoryEntry::AF_LFN_LAST != DirectoryEntry::AF_LFN_LAST)
          # Also skip the next entry (it's the base entry for the last dir ent).
          skip_next = true; next
        end
        if skip_next
          skip_next = false; next
        end

        # If a specific type of record was requested, look for only that type.
        # NOTE: You know, it's possible to look ahead and see what the base entry is.
        if flags != FE_EITHER && attrib != DirectoryEntry::FA_LFN
          next if flags == FE_DIR && (attrib & DirectoryEntry::FA_DIRECTORY == 0)
          next if flags == FE_FILE && (attrib & DirectoryEntry::FA_DIRECTORY != 0)
        end

        # Potential match... get a DirectoryEntry & stop if found.
        de = DirectoryEntry.new(@data[offset, MAX_ENT_SIZE])
        # TODO: - what if the name ends with a dot & there's another dot in the name?
        if de.name.downcase == name.downcase || de.shortName.downcase == name.downcase
          found = true
          break
        end
      end
      return nil unless found
      parentLoc = offset.divmod(@bs.bytesPerCluster)
      de.parentCluster = @all_clusters[parentLoc[0]].number
      de.parentOffset = parentLoc[1]
      de
    end
Return a DirectoryEntry for a specific file (or subdirectory).