summaryrefslogtreecommitdiffstats
path: root/src/inode2filename/inode.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/inode2filename/inode.h')
-rw-r--r--src/inode2filename/inode.h89
1 files changed, 87 insertions, 2 deletions
diff --git a/src/inode2filename/inode.h b/src/inode2filename/inode.h
index 2dd5611..f336a14 100644
--- a/src/inode2filename/inode.h
+++ b/src/inode2filename/inode.h
@@ -23,22 +23,97 @@
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);
- bool operator==(const Inode& rhs) const {
+ constexpr bool operator==(const Inode& rhs) const {
return device_major == rhs.device_major &&
device_minor == rhs.device_minor &&
inode == rhs.inode;
}
- bool operator!=(const Inode& rhs) const {
+ 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) {
@@ -62,4 +137,14 @@ namespace std {
};
} // 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_