Home | History | Annotate | Download | only in libidmap2
      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