blob: 1ff320f76b7d2fa2ed432b651c63ae5bb5ba6aa7 [file] [log] [blame]
/*
* 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 <android-base/unique_fd.h>
#include <functional>
#include <map>
#include <mutex>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
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<std::string, Bind, std::less<>>;
class Mounts final {
struct Root {
std::string path;
std::string backing;
std::vector<BindMap::const_iterator> binds;
bool empty() const { return path.empty(); }
void clear() {
decltype(path)().swap(path);
decltype(binds)().swap(binds);
}
};
public:
struct Mount final {
Mount(std::vector<Root>::const_iterator base) : mBase(base) {}
std::string_view root() const { return mBase->path; }
std::string_view backingDir() const { return mBase->backing; }
std::vector<std::pair<std::string_view, std::string_view>> binds() const;
private:
std::vector<Root>::const_iterator mBase;
};
struct iterator final : public std::vector<Root>::const_iterator {
using base = std::vector<Root>::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<const Root*, std::string> 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<int, BindMap::const_iterator> rootIndex(std::string_view path) const;
std::vector<Root> roots;
BindMap rootByBindPoint;
};
MountRegistry(std::string_view filesystem = {});
~MountRegistry();
std::string rootFor(std::string_view path);
std::pair<std::string, std::string> 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<std::mutex> ensureUpToDate();
private:
const std::string mFilesystem;
base::unique_fd mMountInfo;
Mounts mMounts;
mutable std::mutex mDataMutex;
};
} // namespace android::incfs