18a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin//
28a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin// Copyright 2011 The Android Open Source Project
38a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin//
48a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
58a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin// File Finder implementation.
68a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin// Implementation for the functions declared and documented in FileFinder.h
78a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
88a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include <utils/Vector.h>
98a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include <utils/String8.h>
108a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include <utils/KeyedVector.h>
118a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
129102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin#include <dirent.h>
139102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin#include <sys/stat.h>
148a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
158a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include "DirectoryWalker.h"
168a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include "FileFinder.h"
178a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
188a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin//#define DEBUG
198a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
208a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskinusing android::String8;
218a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
229102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin// Private function to check whether a file is a directory or not
239102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskinbool isDirectory(const char* filename) {
249102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin    struct stat fileStat;
259102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin    if (stat(filename, &fileStat) == -1) {
269102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin        return false;
279102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin    }
289102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin    return(S_ISDIR(fileStat.st_mode));
299102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin}
309102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin
319102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin
329102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin// Private function to check whether a file is a regular file or not
339102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskinbool isFile(const char* filename) {
349102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin    struct stat fileStat;
359102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin    if (stat(filename, &fileStat) == -1) {
369102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin        return false;
379102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin    }
389102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin    return(S_ISREG(fileStat.st_mode));
399102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin}
409102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin
418a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskinbool SystemFileFinder::findFiles(String8 basePath, Vector<String8>& extensions,
428a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin                                 KeyedVector<String8,time_t>& fileStore,
438a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin                                 DirectoryWalker* dw)
448a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin{
458a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // Scan the directory pointed to by basePath
468a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // check files and recurse into subdirectories.
478a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    if (!dw->openDir(basePath)) {
488a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        return false;
498a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    }
508a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    /*
518a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin     *  Go through all directory entries. Check each file using checkAndAddFile
528a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin     *  and recurse into sub-directories.
538a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin     */
548a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    struct dirent* entry;
558a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    while ((entry = dw->nextEntry()) != NULL) {
568a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        String8 entryName(entry->d_name);
578a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        if (entry->d_name[0] == '.') // Skip hidden files and directories
588a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            continue;
598a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
608a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        String8 fullPath = basePath.appendPathCopy(entryName);
618a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        // If this entry is a directory we'll recurse into it
629102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin        if (isDirectory(fullPath.string()) ) {
638a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            DirectoryWalker* copy = dw->clone();
648a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            findFiles(fullPath, extensions, fileStore,copy);
658a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            delete copy;
668a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        }
678a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
688a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        // If this entry is a file, we'll pass it over to checkAndAddFile
699102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin        if (isFile(fullPath.string()) ) {
708a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            checkAndAddFile(fullPath,dw->entryStats(),extensions,fileStore);
718a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        }
728a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    }
738a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
748a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // Clean up
758a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    dw->closeDir();
768a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
778a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    return true;
788a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin}
798a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
808a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskinvoid SystemFileFinder::checkAndAddFile(String8 path, const struct stat* stats,
818a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin                                       Vector<String8>& extensions,
828a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin                                       KeyedVector<String8,time_t>& fileStore)
838a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin{
848a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // Loop over the extensions, checking for a match
858a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    bool done = false;
868a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    String8 ext(path.getPathExtension());
878a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    ext.toLower();
888a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    for (size_t i = 0; i < extensions.size() && !done; ++i) {
898a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        String8 ext2 = extensions[i].getPathExtension();
908a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        ext2.toLower();
918a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        // Compare the extensions. If a match is found, add to storage.
928a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        if (ext == ext2) {
938a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            done = true;
948a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            fileStore.add(path,stats->st_mtime);
958a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        }
968a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    }
979102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin}
989102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin
99