FileFinder.cpp revision 9102165fd8be64bdc9110d0839a84fcdfa5b68cb
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
128a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include <iostream>
139102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin#include <dirent.h>
149102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin#include <sys/stat.h>
158a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
168a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include "DirectoryWalker.h"
178a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include "FileFinder.h"
188a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
198a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin//#define DEBUG
208a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
218a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskinusing android::String8;
228a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskinusing std::cout;
238a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskinusing std::endl;
248a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
259102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin// Private function to check whether a file is a directory or not
269102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskinbool isDirectory(const char* filename) {
279102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin    struct stat fileStat;
289102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin    if (stat(filename, &fileStat) == -1) {
299102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin        return false;
309102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin    }
319102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin    return(S_ISDIR(fileStat.st_mode));
329102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin}
339102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin
349102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin
359102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin// Private function to check whether a file is a regular file or not
369102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskinbool isFile(const char* filename) {
379102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin    struct stat fileStat;
389102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin    if (stat(filename, &fileStat) == -1) {
399102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin        return false;
409102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin    }
419102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin    return(S_ISREG(fileStat.st_mode));
429102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin}
439102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin
448a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskinbool SystemFileFinder::findFiles(String8 basePath, Vector<String8>& extensions,
458a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin                                 KeyedVector<String8,time_t>& fileStore,
468a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin                                 DirectoryWalker* dw)
478a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin{
488a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // Scan the directory pointed to by basePath
498a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // check files and recurse into subdirectories.
508a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    if (!dw->openDir(basePath)) {
518a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        return false;
528a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    }
538a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#ifdef DEBUG
548a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    cout << "FileFinder looking in " << basePath << endl;
558a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#endif // DEBUG
568a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    /*
578a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin     *  Go through all directory entries. Check each file using checkAndAddFile
588a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin     *  and recurse into sub-directories.
598a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin     */
608a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    struct dirent* entry;
618a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    while ((entry = dw->nextEntry()) != NULL) {
628a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        String8 entryName(entry->d_name);
638a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        if (entry->d_name[0] == '.') // Skip hidden files and directories
648a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            continue;
658a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
668a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        String8 fullPath = basePath.appendPathCopy(entryName);
678a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        // If this entry is a directory we'll recurse into it
689102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin        if (isDirectory(fullPath.string()) ) {
698a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            DirectoryWalker* copy = dw->clone();
708a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            findFiles(fullPath, extensions, fileStore,copy);
718a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            delete copy;
728a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        }
738a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
748a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        // If this entry is a file, we'll pass it over to checkAndAddFile
759102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin        if (isFile(fullPath.string()) ) {
768a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            checkAndAddFile(fullPath,dw->entryStats(),extensions,fileStore);
778a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        }
788a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    }
798a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
808a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // Clean up
818a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    dw->closeDir();
828a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
838a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    return true;
848a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin}
858a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
868a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskinvoid SystemFileFinder::checkAndAddFile(String8 path, const struct stat* stats,
878a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin                                       Vector<String8>& extensions,
888a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin                                       KeyedVector<String8,time_t>& fileStore)
898a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin{
908a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#ifdef DEBUG
918a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    cout << "Checking file " << path << "...";
928a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#endif // DEBUG
938a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    // Loop over the extensions, checking for a match
948a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    bool done = false;
958a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    String8 ext(path.getPathExtension());
968a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    ext.toLower();
978a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    for (size_t i = 0; i < extensions.size() && !done; ++i) {
988a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        String8 ext2 = extensions[i].getPathExtension();
998a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        ext2.toLower();
1008a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        // Compare the extensions. If a match is found, add to storage.
1018a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        if (ext == ext2) {
1028a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#ifdef DEBUG
1038a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            cout << "Match";
1048a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#endif // DEBUG
1058a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            done = true;
1068a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            fileStore.add(path,stats->st_mtime);
1078a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        }
1088a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    }
1098a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#ifdef DEBUG
1108a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    cout << endl;
1118a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#endif //DEBUG
1129102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin}
1139102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin
114