1 /* 2 * Copyright (C) 2019 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 #pragma once 18 19 #include <android-base/unique_fd.h> 20 21 #include <functional> 22 #include <map> 23 #include <mutex> 24 #include <string> 25 #include <string_view> 26 #include <utility> 27 #include <vector> 28 29 namespace android::incfs { 30 31 // 32 // MountRegistry - a collection of mount points for a particular filesystem, with 33 // live tracking of binds, mounts and unmounts on it 34 // 35 36 class MountRegistry final { 37 public: 38 struct Bind { 39 std::string subdir; 40 int rootIndex; 41 }; 42 // std::less<> enables heterogeneous lookups, e.g. by a string_view 43 using BindMap = std::map<std::string, Bind, std::less<>>; 44 45 class Mounts final { 46 struct Root { 47 std::string path; 48 std::string backing; 49 std::vector<BindMap::const_iterator> binds; 50 emptyRoot51 bool empty() const { return path.empty(); } clearRoot52 void clear() { 53 decltype(path)().swap(path); 54 decltype(binds)().swap(binds); 55 } 56 }; 57 58 public: 59 struct Mount final { Mountfinal60 Mount(std::vector<Root>::const_iterator base) : mBase(base) {} 61 rootfinal62 std::string_view root() const { return mBase->path; } backingDirfinal63 std::string_view backingDir() const { return mBase->backing; } 64 std::vector<std::pair<std::string_view, std::string_view>> binds() const; 65 66 private: 67 std::vector<Root>::const_iterator mBase; 68 }; 69 70 struct iterator final : public std::vector<Root>::const_iterator { 71 using base = std::vector<Root>::const_iterator; 72 using value_type = Mount; 73 value_type operator*() const { return Mount(*this); } 74 iteratorfinal75 explicit iterator(base b) : base(b) {} 76 }; 77 78 static Mounts load(base::borrowed_fd fd, std::string_view filesystem); 79 bool loadFrom(base::borrowed_fd fd, std::string_view filesystem); 80 begin()81 iterator begin() const { return iterator(roots.begin()); } end()82 iterator end() const { return iterator(roots.end()); } size()83 size_t size() const { return roots.size(); } empty()84 bool empty() const { return roots.empty(); } 85 86 std::string_view rootFor(std::string_view path) const; 87 std::pair<const Root*, std::string> rootAndSubpathFor(std::string_view path) const; 88 89 void swap(Mounts& other); 90 void clear(); 91 92 void addRoot(std::string_view root, std::string_view backingDir); 93 void removeRoot(std::string_view root); 94 void addBind(std::string_view what, std::string_view where); 95 void removeBind(std::string_view what); 96 97 private: 98 std::pair<int, BindMap::const_iterator> rootIndex(std::string_view path) const; 99 100 std::vector<Root> roots; 101 BindMap rootByBindPoint; 102 }; 103 104 MountRegistry(std::string_view filesystem = {}); 105 ~MountRegistry(); 106 107 std::string rootFor(std::string_view path); 108 std::pair<std::string, std::string> rootAndSubpathFor(std::string_view path); 109 110 struct Details { 111 std::string root; 112 std::string backing; 113 std::string subpath; 114 }; 115 Details detailsFor(std::string_view path); 116 117 Mounts copyMounts(); 118 119 void reload(); 120 121 private: 122 [[nodiscard]] std::unique_lock<std::mutex> ensureUpToDate(); 123 124 private: 125 const std::string mFilesystem; 126 base::unique_fd mMountInfo; 127 Mounts mMounts; 128 mutable std::mutex mDataMutex; 129 }; 130 131 } // namespace android::incfs 132