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 <dirent.h>
13#include <sys/stat.h>
14
15#include "DirectoryWalker.h"
16#include "FileFinder.h"
17
18//#define DEBUG
19
20using android::String8;
21
22// Private function to check whether a file is a directory or not
23bool isDirectory(const char* filename) {
24    struct stat fileStat;
25    if (stat(filename, &fileStat) == -1) {
26        return false;
27    }
28    return(S_ISDIR(fileStat.st_mode));
29}
30
31
32// Private function to check whether a file is a regular file or not
33bool isFile(const char* filename) {
34    struct stat fileStat;
35    if (stat(filename, &fileStat) == -1) {
36        return false;
37    }
38    return(S_ISREG(fileStat.st_mode));
39}
40
41bool SystemFileFinder::findFiles(String8 basePath, Vector<String8>& extensions,
42                                 KeyedVector<String8,time_t>& fileStore,
43                                 DirectoryWalker* dw)
44{
45    // Scan the directory pointed to by basePath
46    // check files and recurse into subdirectories.
47    if (!dw->openDir(basePath)) {
48        return false;
49    }
50    /*
51     *  Go through all directory entries. Check each file using checkAndAddFile
52     *  and recurse into sub-directories.
53     */
54    struct dirent* entry;
55    while ((entry = dw->nextEntry()) != NULL) {
56        String8 entryName(entry->d_name);
57        if (entry->d_name[0] == '.') // Skip hidden files and directories
58            continue;
59
60        String8 fullPath = basePath.appendPathCopy(entryName);
61        // If this entry is a directory we'll recurse into it
62        if (isDirectory(fullPath.string()) ) {
63            DirectoryWalker* copy = dw->clone();
64            findFiles(fullPath, extensions, fileStore,copy);
65            delete copy;
66        }
67
68        // If this entry is a file, we'll pass it over to checkAndAddFile
69        if (isFile(fullPath.string()) ) {
70            checkAndAddFile(fullPath,dw->entryStats(),extensions,fileStore);
71        }
72    }
73
74    // Clean up
75    dw->closeDir();
76
77    return true;
78}
79
80void SystemFileFinder::checkAndAddFile(String8 path, const struct stat* stats,
81                                       Vector<String8>& extensions,
82                                       KeyedVector<String8,time_t>& fileStore)
83{
84    // Loop over the extensions, checking for a match
85    bool done = false;
86    String8 ext(path.getPathExtension());
87    ext.toLower();
88    for (size_t i = 0; i < extensions.size() && !done; ++i) {
89        String8 ext2 = extensions[i].getPathExtension();
90        ext2.toLower();
91        // Compare the extensions. If a match is found, add to storage.
92        if (ext == ext2) {
93            done = true;
94            fileStore.add(path,stats->st_mtime);
95        }
96    }
97}
98
99