1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Copyright 2011 The Android Open Source Project 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// File Finder implementation. 6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Implementation for the functions declared and documented in FileFinder.h 7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/Vector.h> 9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/String8.h> 10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/KeyedVector.h> 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <dirent.h> 13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <sys/stat.h> 14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "DirectoryWalker.h" 16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "FileFinder.h" 17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski//#define DEBUG 19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiusing android::String8; 21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Private function to check whether a file is a directory or not 23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool isDirectory(const char* filename) { 24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski struct stat fileStat; 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (stat(filename, &fileStat) == -1) { 26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return(S_ISDIR(fileStat.st_mode)); 29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Private function to check whether a file is a regular file or not 33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool isFile(const char* filename) { 34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski struct stat fileStat; 35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (stat(filename, &fileStat) == -1) { 36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return(S_ISREG(fileStat.st_mode)); 39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool SystemFileFinder::findFiles(String8 basePath, Vector<String8>& extensions, 42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski KeyedVector<String8,time_t>& fileStore, 43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski DirectoryWalker* dw) 44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Scan the directory pointed to by basePath 46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // check files and recurse into subdirectories. 47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!dw->openDir(basePath)) { 48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Go through all directory entries. Check each file using checkAndAddFile 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * and recurse into sub-directories. 53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski struct dirent* entry; 55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((entry = dw->nextEntry()) != NULL) { 56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 entryName(entry->d_name); 57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (entry->d_name[0] == '.') // Skip hidden files and directories 58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 fullPath = basePath.appendPathCopy(entryName); 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If this entry is a directory we'll recurse into it 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (isDirectory(fullPath.string()) ) { 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski DirectoryWalker* copy = dw->clone(); 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski findFiles(fullPath, extensions, fileStore,copy); 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski delete copy; 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If this entry is a file, we'll pass it over to checkAndAddFile 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (isFile(fullPath.string()) ) { 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski checkAndAddFile(fullPath,dw->entryStats(),extensions,fileStore); 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Clean up 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski dw->closeDir(); 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid SystemFileFinder::checkAndAddFile(String8 path, const struct stat* stats, 81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<String8>& extensions, 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski KeyedVector<String8,time_t>& fileStore) 83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Loop over the extensions, checking for a match 85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool done = false; 86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 ext(path.getPathExtension()); 87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ext.toLower(); 88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i = 0; i < extensions.size() && !done; ++i) { 89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 ext2 = extensions[i].getPathExtension(); 90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ext2.toLower(); 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Compare the extensions. If a match is found, add to storage. 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (ext == ext2) { 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski done = true; 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fileStore.add(path,stats->st_mtime); 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 99