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 
20 using android::String8;
21 
22 // Private function to check whether a file is a directory or not
isDirectory(const char * filename)23 bool 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
isFile(const char * filename)33 bool 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 
findFiles(String8 basePath,Vector<String8> & extensions,KeyedVector<String8,time_t> & fileStore,DirectoryWalker * dw)41 bool 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 
checkAndAddFile(const String8 & path,const struct stat * stats,Vector<String8> & extensions,KeyedVector<String8,time_t> & fileStore)80 void SystemFileFinder::checkAndAddFile(const 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