From: Lennart Poettering Date: Mon, 14 Feb 2022 16:18:32 +0000 (+0100) Subject: stat-util: add helper stat_inode_same() for comparing stat's st_dev/st_ino in one X-Git-Tag: v251-rc1~294^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=38db6211b5aa6e2fb65883ae3353914e82f5bef1;p=thirdparty%2Fsystemd.git stat-util: add helper stat_inode_same() for comparing stat's st_dev/st_ino in one We do this all over the place, hence let's add a simple helper that does this and particularly carefully and thoroughly. --- diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index c2269844f81..298f46440fa 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -417,6 +417,18 @@ int proc_mounted(void) { return r; } +bool stat_inode_same(const struct stat *a, const struct stat *b) { + + /* Returns if the specified stat structure references the same (though possibly modified) inode. Does + * a thorough check, comparing inode nr, backing device and if the inode is still of the same type. */ + + return a && b && + (a->st_mode & S_IFMT) != 0 && /* We use the check for .st_mode if the structure was ever initialized */ + ((a->st_mode ^ b->st_mode) & S_IFMT) == 0 && /* same inode type */ + a->st_dev == b->st_dev && + a->st_ino == b->st_ino; +} + bool stat_inode_unmodified(const struct stat *a, const struct stat *b) { /* Returns if the specified stat structures reference the same, unmodified inode. This check tries to @@ -428,14 +440,10 @@ bool stat_inode_unmodified(const struct stat *a, const struct stat *b) { * about contents of the file. The purpose here is to detect file contents changes, and nothing * else. */ - return a && b && - (a->st_mode & S_IFMT) != 0 && /* We use the check for .st_mode if the structure was ever initialized */ - ((a->st_mode ^ b->st_mode) & S_IFMT) == 0 && /* same inode type */ + return stat_inode_same(a, b) && a->st_mtim.tv_sec == b->st_mtim.tv_sec && a->st_mtim.tv_nsec == b->st_mtim.tv_nsec && (!S_ISREG(a->st_mode) || a->st_size == b->st_size) && /* if regular file, compare file size */ - a->st_dev == b->st_dev && - a->st_ino == b->st_ino && (!(S_ISCHR(a->st_mode) || S_ISBLK(a->st_mode)) || a->st_rdev == b->st_rdev); /* if device node, also compare major/minor, because we can */ } diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h index f7d2f12aa9d..5f4741cf647 100644 --- a/src/basic/stat-util.h +++ b/src/basic/stat-util.h @@ -92,6 +92,7 @@ int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret int proc_mounted(void); +bool stat_inode_same(const struct stat *a, const struct stat *b); bool stat_inode_unmodified(const struct stat *a, const struct stat *b); int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct statx *sx);