blob: f336a1405bb9e08d89e50763cfc4fa8f2fcfa628 [file] [log] [blame]
// Copyright (C) 2018 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.
#ifndef IORAP_SRC_INODE2FILENAME_INODE_H_
#define IORAP_SRC_INODE2FILENAME_INODE_H_
#include <functional>
#include <ostream>
#include <string>
#include <stddef.h>
namespace iorap::inode2filename {
// Avoid polluting headers.
#if defined(__ANDROID__)
# if !defined(__LP64__)
/* This historical accident means that we had a 32-bit dev_t on 32-bit architectures. */
using dev_t = uint32_t;
# else
using dev_t = uint64_t;
# endif
using ino_t = unsigned long;
#else
# if !defined(__x86_64__)
using dev_t = unsigned long long;
using ino_t = unsigned long long;
# else
using dev_t = unsigned long;
using ino_t = unsigned long;
# endif
#endif
#ifdef makedev
#undef makedev
#endif
/** Combines `major` and `minor` into a device number. */
constexpr inline dev_t makedev(unsigned int major, unsigned int minor) {
return
(((major) & 0xfffff000ULL) << 32) | (((major) & 0xfffULL) << 8) |
(((minor) & 0xffffff00ULL) << 12) | (((minor) & 0xffULL));
}
#ifdef major
#undef major
#endif
/** Extracts the major part of a device number. */
constexpr inline unsigned int major(dev_t dev) {
return
((unsigned) ((((unsigned long long) (dev) >> 32) & 0xfffff000) | (((dev) >> 8) & 0xfff)));
}
#ifdef minor
#undef minor
#endif
/** Extracts the minor part of a device number. */
constexpr inline unsigned int minor(dev_t dev) {
return
((unsigned) ((((dev) >> 12) & 0xffffff00) | ((dev) & 0xff)));
};
// Note: above definitions copied from sysmacros.h, to avoid polluting global namespace in a header.
/*
* A convenient datum representing a (dev_t, ino_t) tuple.
*
* ino_t values may be reused across different devices (e.g. different partitions),
* so we need the full tuple to uniquely identify an inode on a system.
*/
struct Inode {
size_t device_major; // dev_t = makedev(major, minor)
size_t device_minor;
size_t inode; // ino_t = inode
// "Major:minor:inode" OR "dev_t@inode"
static bool Parse(const std::string& str, /*out*/Inode* out, /*out*/std::string* error_msg);
constexpr bool operator==(const Inode& rhs) const {
return device_major == rhs.device_major &&
device_minor == rhs.device_minor &&
inode == rhs.inode;
}
constexpr bool operator!=(const Inode& rhs) const {
return !(*this == rhs);
}
Inode() = default;
constexpr Inode(size_t device_major, size_t device_minor, size_t inode)
: device_major{device_major}, device_minor{device_minor}, inode{inode} {
}
static constexpr Inode FromDeviceAndInode(dev_t dev, ino_t inode) {
return Inode{major(dev), minor(dev), static_cast<size_t>(inode)};
}
constexpr dev_t GetDevice() const {
return makedev(device_major, device_minor);
}
constexpr ino_t GetInode() const {
return static_cast<ino_t>(inode);
}
};
inline std::ostream& operator<<(std::ostream& os, const Inode& inode) {
os << inode.device_major << ":" << inode.device_minor << ":" << inode.inode;
return os;
}
} // namespace iorap::inode2filename
namespace std {
template <>
struct hash<iorap::inode2filename::Inode> {
using argument_type = iorap::inode2filename::Inode;
using result_type = size_t;
result_type operator()(argument_type const& s) const noexcept {
// Hash the inode by using only the inode#. Ignore devices, we are extremely unlikely
// to ever collide on the devices.
result_type const h1 = std::hash<size_t>{}(s.inode);
return h1;
}
};
} // namespace std
namespace rxcpp {
template <class T, typename>
struct filtered_hash;
// support for the 'distinct' rx operator.
template <>
struct filtered_hash<iorap::inode2filename::Inode, void> : std::hash<iorap::inode2filename::Inode> {
};
} // namespace rxcpp
#endif // IORAP_SRC_INODE2FILENAME_INODE_H_