FileFinder.cpp revision 9102165fd8be64bdc9110d0839a84fcdfa5b68cb
1//
2// Copyright 2011 The Android Open Source Project
3//
4
5// File Finder implementation.
6// Implementation for the functions declared and documented in FileFinder.h
7
8#include <utils/Vector.h>
9#include <utils/String8.h>
10#include <utils/KeyedVector.h>
11
12#include <iostream>
13#include <dirent.h>
14#include <sys/stat.h>
15
16#include "DirectoryWalker.h"
17#include "FileFinder.h"
18
19//#define DEBUG
20
21using android::String8;
22using std::cout;
23using std::endl;
24
25// Private function to check whether a file is a directory or not
26bool isDirectory(const char* filename) {
27    struct stat fileStat;
28    if (stat(filename, &fileStat) == -1) {
29        return false;
30    }
31    return(S_ISDIR(fileStat.st_mode));
32}
33
34
35// Private function to check whether a file is a regular file or not
36bool isFile(const char* filename) {
37    struct stat fileStat;
38    if (stat(filename, &fileStat) == -1) {
39        return false;
40    }
41    return(S_ISREG(fileStat.st_mode));
42}
43
44bool SystemFileFinder::findFiles(String8 basePath, Vector<String8>& extensions,
45                                 KeyedVector<String8,time_t>& fileStore,
46                                 DirectoryWalker* dw)
47{
48    // Scan the directory pointed to by basePath
49    // check files and recurse into subdirectories.
50    if (!dw->openDir(basePath)) {
51        return false;
52    }
53#ifdef DEBUG
54    cout << "FileFinder looking in " << basePath << endl;
55#endif // DEBUG
56    /*
57     *  Go through all directory entries. Check each file using checkAndAddFile
58     *  and recurse into sub-directories.
59     */
60    struct dirent* entry;
61    while ((entry = dw->nextEntry()) != NULL) {
62        String8 entryName(entry->d_name);
63        if (entry->d_name[0] == '.') // Skip hidden files and directories
64            continue;
65
66        String8 fullPath = basePath.appendPathCopy(entryName);
67        // If this entry is a directory we'll recurse into it
68        if (isDirectory(fullPath.string()) ) {
69            DirectoryWalker* copy = dw->clone();
70            findFiles(fullPath, extensions, fileStore,copy);
71            delete copy;
72        }
73
74        // If this entry is a file, we'll pass it over to checkAndAddFile
75        if (isFile(fullPath.string()) ) {
76            checkAndAddFile(fullPath,dw->entryStats(),extensions,fileStore);
77        }
78    }
79
80    // Clean up
81    dw->closeDir();
82
83    return true;
84}
85
86void SystemFileFinder::checkAndAddFile(String8 path, const struct stat* stats,
87                                       Vector<String8>& extensions,
88                                       KeyedVector<String8,time_t>& fileStore)
89{
90#ifdef DEBUG
91    cout << "Checking file " << path << "...";
92#endif // DEBUG
93    // Loop over the extensions, checking for a match
94    bool done = false;
95    String8 ext(path.getPathExtension());
96    ext.toLower();
97    for (size_t i = 0; i < extensions.size() && !done; ++i) {
98        String8 ext2 = extensions[i].getPathExtension();
99        ext2.toLower();
100        // Compare the extensions. If a match is found, add to storage.
101        if (ext == ext2) {
102#ifdef DEBUG
103            cout << "Match";
104#endif // DEBUG
105            done = true;
106            fileStore.add(path,stats->st_mtime);
107        }
108    }
109#ifdef DEBUG
110    cout << endl;
111#endif //DEBUG
112}
113
114