1 /* 2 * Copyright (C) 2018 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 "idmap2/FileUtils.h" 18 19 #include <dirent.h> 20 #include <sys/types.h> 21 #include <unistd.h> 22 23 #include <cerrno> 24 #include <climits> 25 #include <cstdlib> 26 #include <cstring> 27 #include <fstream> 28 #include <memory> 29 #include <string> 30 #include <utility> 31 #include <vector> 32 33 #include "android-base/file.h" 34 #include "android-base/macros.h" 35 #include "android-base/stringprintf.h" 36 #include "private/android_filesystem_config.h" 37 38 namespace android::idmap2::utils { 39 40 std::unique_ptr<std::vector<std::string>> FindFiles(const std::string& root, bool recurse, 41 const FindFilesPredicate& predicate) { 42 DIR* dir = opendir(root.c_str()); 43 if (dir == nullptr) { 44 return nullptr; 45 } 46 std::unique_ptr<std::vector<std::string>> vector(new std::vector<std::string>()); 47 struct dirent* dirent; 48 while ((dirent = readdir(dir)) != nullptr) { 49 const std::string path = root + "/" + dirent->d_name; 50 if (predicate(dirent->d_type, path)) { 51 vector->push_back(path); 52 } 53 if (recurse && dirent->d_type == DT_DIR && strcmp(dirent->d_name, ".") != 0 && 54 strcmp(dirent->d_name, "..") != 0) { 55 auto sub_vector = FindFiles(path, recurse, predicate); 56 if (!sub_vector) { 57 closedir(dir); 58 return nullptr; 59 } 60 vector->insert(vector->end(), sub_vector->begin(), sub_vector->end()); 61 } 62 } 63 closedir(dir); 64 65 return vector; 66 } 67 68 std::unique_ptr<std::string> ReadFile(const std::string& path) { 69 std::unique_ptr<std::string> str(new std::string()); 70 std::ifstream fin(path); 71 str->append({std::istreambuf_iterator<char>(fin), std::istreambuf_iterator<char>()}); 72 fin.close(); 73 return str; 74 } 75 76 std::unique_ptr<std::string> ReadFile(int fd) { 77 static constexpr const size_t kBufSize = 1024; 78 79 std::unique_ptr<std::string> str(new std::string()); 80 char buf[kBufSize]; 81 ssize_t r; 82 while ((r = read(fd, buf, sizeof(buf))) > 0) { 83 str->append(buf, r); 84 } 85 return r == 0 ? std::move(str) : nullptr; 86 } 87 88 #ifdef __ANDROID__ 89 bool UidHasWriteAccessToPath(uid_t uid, const std::string& path) { 90 // resolve symlinks and relative paths; the directories must exist 91 std::string canonical_path; 92 if (!base::Realpath(base::Dirname(path), &canonical_path)) { 93 return false; 94 } 95 96 const std::string cache_subdir = base::StringPrintf("%s/", kIdmapCacheDir); 97 if (canonical_path == kIdmapCacheDir || 98 canonical_path.compare(0, cache_subdir.size(), cache_subdir) == 0) { 99 // limit access to /data/resource-cache to root and system 100 return uid == AID_ROOT || uid == AID_SYSTEM; 101 } 102 return true; 103 } 104 #else 105 bool UidHasWriteAccessToPath(uid_t uid ATTRIBUTE_UNUSED, const std::string& path ATTRIBUTE_UNUSED) { 106 return true; 107 } 108 #endif 109 110 } // namespace android::idmap2::utils 111