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     // std::less<> enables heterogeneous lookups, e.g. by a string_view
39     using BindMap = std::map<std::string, std::pair<std::string, int>, std::less<>>;
40 
41     class Mounts final {
42         struct Root {
43             std::string path;
44             std::string backing;
45             std::vector<BindMap::const_iterator> binds;
46 
emptyRoot47             bool empty() const { return path.empty(); }
clearRoot48             void clear() {
49                 decltype(path)().swap(path);
50                 decltype(binds)().swap(binds);
51             }
52         };
53 
54     public:
55         struct Mount final {
Mountfinal56             Mount(std::vector<Root>::const_iterator base) : mBase(base) {}
57 
rootfinal58             std::string_view root() const { return mBase->path; }
backingDirfinal59             std::string_view backingDir() const { return mBase->backing; }
60             std::vector<std::pair<std::string_view, std::string_view>> binds() const;
61 
62         private:
63             std::vector<Root>::const_iterator mBase;
64         };
65 
66         struct iterator final : public std::vector<Root>::const_iterator {
67             using base = std::vector<Root>::const_iterator;
68             using value_type = Mount;
69             value_type operator*() const { return Mount(*this); }
70 
iteratorfinal71             explicit iterator(base b) : base(b) {}
72         };
73 
74         static Mounts load(base::borrowed_fd fd, std::string_view filesystem);
75         bool loadFrom(base::borrowed_fd fd, std::string_view filesystem);
76 
begin()77         iterator begin() const { return iterator(roots.begin()); }
end()78         iterator end() const { return iterator(roots.end()); }
size()79         size_t size() const { return roots.size(); }
empty()80         bool empty() const { return roots.empty(); }
81 
82         std::string_view rootFor(std::string_view path) const;
83         std::pair<std::string_view, std::string> rootAndSubpathFor(std::string_view path) const;
84 
85         void swap(Mounts& other);
86         void clear();
87 
88         void addRoot(std::string_view root, std::string_view backingDir);
89         void removeRoot(std::string_view root);
90         void addBind(std::string_view what, std::string_view where);
91         void moveBind(std::string_view src, std::string_view dest);
92         void removeBind(std::string_view what);
93 
94     private:
95         std::pair<int, BindMap::const_iterator> rootIndex(std::string_view path) const;
96 
97         std::vector<Root> roots;
98         BindMap rootByBindPoint;
99     };
100 
101     MountRegistry(std::string_view filesystem = {});
102     ~MountRegistry();
103 
104     std::string rootFor(std::string_view path);
105     std::pair<std::string, std::string> rootAndSubpathFor(std::string_view path);
106     Mounts copyMounts();
107 
108     void reload();
109 
110 private:
111     [[nodiscard]] std::unique_lock<std::mutex> ensureUpToDate();
112 
113 private:
114     const std::string mFilesystem;
115     base::unique_fd mMountInfo;
116     Mounts mMounts;
117     mutable std::mutex mDataMutex;
118 };
119 
120 } // namespace android::incfs
121