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