DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(inode_hash_ops, struct stat, inode_hash_func, inode_compare_func, free);
+void inode_unmodified_hash_func(const struct stat *q, struct siphash *state) {
+ inode_hash_func(q, state);
+
+ siphash24_compress_typesafe(q->st_mtim.tv_sec, state);
+ siphash24_compress_typesafe(q->st_mtim.tv_nsec, state);
+
+ if (S_ISREG(q->st_mode))
+ siphash24_compress_typesafe(q->st_size, state);
+ else {
+ uint64_t invalid = UINT64_MAX;
+ siphash24_compress_typesafe(invalid, state);
+ }
+
+ if (S_ISCHR(q->st_mode) || S_ISBLK(q->st_mode))
+ siphash24_compress_typesafe(q->st_rdev, state);
+ else {
+ dev_t invalid = (dev_t) -1;
+ siphash24_compress_typesafe(invalid, state);
+ }
+}
+
+int inode_unmodified_compare_func(const struct stat *a, const struct stat *b) {
+ int r;
+
+ r = inode_compare_func(a, b);
+ if (r != 0)
+ return r;
+
+ r = CMP(a->st_mtim.tv_sec, b->st_mtim.tv_sec);
+ if (r != 0)
+ return r;
+
+ r = CMP(a->st_mtim.tv_nsec, b->st_mtim.tv_nsec);
+ if (r != 0)
+ return r;
+
+ if (S_ISREG(a->st_mode)) {
+ r = CMP(a->st_size, b->st_size);
+ if (r != 0)
+ return r;
+ }
+
+ if (S_ISCHR(a->st_mode) || S_ISBLK(a->st_mode)) {
+ r = CMP(a->st_rdev, b->st_rdev);
+ if (r != 0)
+ return r;
+ }
+
+ return 0;
+}
+
+DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(inode_unmodified_hash_ops, struct stat, inode_unmodified_hash_func, inode_unmodified_compare_func, free);
+
const char* inode_type_to_string(mode_t m) {
/* Returns a short string for the inode type. We use the same name as the underlying macros for each
int inode_compare_func(const struct stat *a, const struct stat *b);
extern const struct hash_ops inode_hash_ops;
+/* This is a more thorough version of the above, and also checks the mtimes, the size, and the rdev. It does
+ * not check "external" attributes such as access mode or ownership. */
+void inode_unmodified_hash_func(const struct stat *q, struct siphash *state);
+int inode_unmodified_compare_func(const struct stat *a, const struct stat *b);
+extern const struct hash_ops inode_unmodified_hash_ops;
+
DECLARE_STRING_TABLE_LOOKUP(inode_type, mode_t);
/* Macros that check whether the stat/statx structures have been initialized already. For "struct stat" we