/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include #include #include namespace android::incfs { // // MountRegistry - a collection of mount points for a particular filesystem, with // live tracking of binds, mounts and unmounts on it // class MountRegistry final { public: struct Bind { std::string subdir; int rootIndex; }; // std::less<> enables heterogeneous lookups, e.g. by a string_view using BindMap = std::map>; class Mounts final { struct Root { std::string path; std::string backing; std::vector binds; bool empty() const { return path.empty(); } void clear() { decltype(path)().swap(path); decltype(binds)().swap(binds); } }; public: struct Mount final { Mount(std::vector::const_iterator base) : mBase(base) {} std::string_view root() const { return mBase->path; } std::string_view backingDir() const { return mBase->backing; } std::vector> binds() const; private: std::vector::const_iterator mBase; }; struct iterator final : public std::vector::const_iterator { using base = std::vector::const_iterator; using value_type = Mount; value_type operator*() const { return Mount(*this); } explicit iterator(base b) : base(b) {} }; static Mounts load(base::borrowed_fd fd, std::string_view filesystem); bool loadFrom(base::borrowed_fd fd, std::string_view filesystem); iterator begin() const { return iterator(roots.begin()); } iterator end() const { return iterator(roots.end()); } size_t size() const { return roots.size(); } bool empty() const { return roots.empty(); } std::string_view rootFor(std::string_view path) const; std::pair rootAndSubpathFor(std::string_view path) const; void swap(Mounts& other); void clear(); void addRoot(std::string_view root, std::string_view backingDir); void removeRoot(std::string_view root); void addBind(std::string_view what, std::string_view where); void removeBind(std::string_view what); private: std::pair rootIndex(std::string_view path) const; std::vector roots; BindMap rootByBindPoint; }; MountRegistry(std::string_view filesystem = {}); ~MountRegistry(); std::string rootFor(std::string_view path); std::pair rootAndSubpathFor(std::string_view path); struct Details { std::string root; std::string backing; std::string subpath; }; Details detailsFor(std::string_view path); Mounts copyMounts(); void reload(); private: [[nodiscard]] std::unique_lock ensureUpToDate(); private: const std::string mFilesystem; base::unique_fd mMountInfo; Mounts mMounts; mutable std::mutex mDataMutex; }; } // namespace android::incfs