1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "io/FileSystem.h" 18 19 #include <dirent.h> 20 21 #include "android-base/errors.h" 22 #include "androidfw/StringPiece.h" 23 #include "utils/FileMap.h" 24 25 #include "Source.h" 26 #include "io/FileStream.h" 27 #include "util/Files.h" 28 #include "util/Maybe.h" 29 #include "util/Util.h" 30 31 using ::android::StringPiece; 32 using ::android::base::SystemErrorCodeToString; 33 34 namespace aapt { 35 namespace io { 36 37 RegularFile::RegularFile(const Source& source) : source_(source) {} 38 39 std::unique_ptr<IData> RegularFile::OpenAsData() { 40 android::FileMap map; 41 if (Maybe<android::FileMap> map = file::MmapPath(source_.path, nullptr)) { 42 if (map.value().getDataPtr() && map.value().getDataLength() > 0) { 43 return util::make_unique<MmappedData>(std::move(map.value())); 44 } 45 return util::make_unique<EmptyData>(); 46 } 47 return {}; 48 } 49 50 std::unique_ptr<io::InputStream> RegularFile::OpenInputStream() { 51 return util::make_unique<FileInputStream>(source_.path); 52 } 53 54 const Source& RegularFile::GetSource() const { 55 return source_; 56 } 57 58 FileCollectionIterator::FileCollectionIterator(FileCollection* collection) 59 : current_(collection->files_.begin()), end_(collection->files_.end()) {} 60 61 bool FileCollectionIterator::HasNext() { 62 return current_ != end_; 63 } 64 65 IFile* FileCollectionIterator::Next() { 66 IFile* result = current_->second.get(); 67 ++current_; 68 return result; 69 } 70 71 std::unique_ptr<FileCollection> FileCollection::Create(const android::StringPiece& root, 72 std::string* outError) { 73 std::unique_ptr<FileCollection> collection = 74 std::unique_ptr<FileCollection>(new FileCollection()); 75 76 std::unique_ptr<DIR, decltype(closedir) *> d(opendir(root.data()), closedir); 77 if (!d) { 78 *outError = "failed to open directory: " + SystemErrorCodeToString(errno); 79 return nullptr; 80 } 81 82 std::vector<std::string> sorted_files; 83 while (struct dirent *entry = readdir(d.get())) { 84 std::string prefix_path = root.to_string(); 85 file::AppendPath(&prefix_path, entry->d_name); 86 87 // The directory to iterate over looking for files 88 if (file::GetFileType(prefix_path) != file::FileType::kDirectory 89 || file::IsHidden(prefix_path)) { 90 continue; 91 } 92 93 std::unique_ptr<DIR, decltype(closedir)*> subdir(opendir(prefix_path.data()), closedir); 94 if (!subdir) { 95 *outError = "failed to open directory: " + SystemErrorCodeToString(errno); 96 return nullptr; 97 } 98 99 while (struct dirent* leaf_entry = readdir(subdir.get())) { 100 std::string full_path = prefix_path; 101 file::AppendPath(&full_path, leaf_entry->d_name); 102 103 // Do not add folders to the file collection 104 if (file::GetFileType(full_path) == file::FileType::kDirectory 105 || file::IsHidden(full_path)) { 106 continue; 107 } 108 109 sorted_files.push_back(full_path); 110 } 111 } 112 113 std::sort(sorted_files.begin(), sorted_files.end()); 114 for (const std::string& full_path : sorted_files) { 115 collection->InsertFile(full_path); 116 } 117 118 return collection; 119 } 120 121 IFile* FileCollection::InsertFile(const StringPiece& path) { 122 return (files_[path.to_string()] = util::make_unique<RegularFile>(Source(path))).get(); 123 } 124 125 IFile* FileCollection::FindFile(const StringPiece& path) { 126 auto iter = files_.find(path.to_string()); 127 if (iter != files_.end()) { 128 return iter->second.get(); 129 } 130 return nullptr; 131 } 132 133 std::unique_ptr<IFileCollectionIterator> FileCollection::Iterator() { 134 return util::make_unique<FileCollectionIterator>(this); 135 } 136 137 char FileCollection::GetDirSeparator() { 138 return file::sDirSep; 139 } 140 141 } // namespace io 142 } // namespace aapt 143