18a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin// 28a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin// Copyright 2011 The Android Open Source Project 38a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin// 48a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin 58a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin// File Finder implementation. 68a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin// Implementation for the functions declared and documented in FileFinder.h 78a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin 88a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include <utils/Vector.h> 98a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include <utils/String8.h> 108a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include <utils/KeyedVector.h> 118a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin 129102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin#include <dirent.h> 139102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin#include <sys/stat.h> 148a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin 158a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include "DirectoryWalker.h" 168a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include "FileFinder.h" 178a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin 188a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin//#define DEBUG 198a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin 208a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskinusing android::String8; 218a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin 229102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin// Private function to check whether a file is a directory or not 239102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskinbool isDirectory(const char* filename) { 249102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin struct stat fileStat; 259102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin if (stat(filename, &fileStat) == -1) { 269102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin return false; 279102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin } 289102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin return(S_ISDIR(fileStat.st_mode)); 299102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin} 309102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin 319102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin 329102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin// Private function to check whether a file is a regular file or not 339102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskinbool isFile(const char* filename) { 349102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin struct stat fileStat; 359102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin if (stat(filename, &fileStat) == -1) { 369102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin return false; 379102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin } 389102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin return(S_ISREG(fileStat.st_mode)); 399102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin} 409102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin 418a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskinbool SystemFileFinder::findFiles(String8 basePath, Vector<String8>& extensions, 428a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin KeyedVector<String8,time_t>& fileStore, 438a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin DirectoryWalker* dw) 448a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin{ 458a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin // Scan the directory pointed to by basePath 468a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin // check files and recurse into subdirectories. 478a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin if (!dw->openDir(basePath)) { 488a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin return false; 498a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin } 508a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin /* 518a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin * Go through all directory entries. Check each file using checkAndAddFile 528a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin * and recurse into sub-directories. 538a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin */ 548a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin struct dirent* entry; 558a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin while ((entry = dw->nextEntry()) != NULL) { 568a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin String8 entryName(entry->d_name); 578a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin if (entry->d_name[0] == '.') // Skip hidden files and directories 588a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin continue; 598a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin 608a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin String8 fullPath = basePath.appendPathCopy(entryName); 618a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin // If this entry is a directory we'll recurse into it 629102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin if (isDirectory(fullPath.string()) ) { 638a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin DirectoryWalker* copy = dw->clone(); 648a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin findFiles(fullPath, extensions, fileStore,copy); 658a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin delete copy; 668a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin } 678a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin 688a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin // If this entry is a file, we'll pass it over to checkAndAddFile 699102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin if (isFile(fullPath.string()) ) { 708a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin checkAndAddFile(fullPath,dw->entryStats(),extensions,fileStore); 718a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin } 728a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin } 738a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin 748a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin // Clean up 758a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin dw->closeDir(); 768a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin 778a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin return true; 788a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin} 798a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin 808a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskinvoid SystemFileFinder::checkAndAddFile(String8 path, const struct stat* stats, 818a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin Vector<String8>& extensions, 828a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin KeyedVector<String8,time_t>& fileStore) 838a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin{ 848a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin // Loop over the extensions, checking for a match 858a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin bool done = false; 868a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin String8 ext(path.getPathExtension()); 878a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin ext.toLower(); 888a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin for (size_t i = 0; i < extensions.size() && !done; ++i) { 898a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin String8 ext2 = extensions[i].getPathExtension(); 908a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin ext2.toLower(); 918a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin // Compare the extensions. If a match is found, add to storage. 928a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin if (ext == ext2) { 938a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin done = true; 948a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin fileStore.add(path,stats->st_mtime); 958a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin } 968a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin } 979102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin} 989102165fd8be64bdc9110d0839a84fcdfa5b68cbJosiah Gaskin 99