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