]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
stat-util: add stat_inode_unmodified() helper that checks if an inode was modified
authorLennart Poettering <lennart@poettering.net>
Tue, 28 Apr 2020 16:16:25 +0000 (18:16 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 13 May 2020 14:57:44 +0000 (16:57 +0200)
src/basic/stat-util.c
src/basic/stat-util.h

index 1f3de56cf926781ba94da9682c98d3d516150710..e4e4d8f0762108bedb3e8f863acb1d8887d33e7f 100644 (file)
@@ -388,3 +388,24 @@ int proc_mounted(void) {
 
         return r;
 }
+
+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
+         * be reasonably careful when detecting changes: we check both inode and mtime, to cater for file
+         * systems where mtimes are fixed to 0 (think: ostree/nixos type installations). We also check file
+         * size, backing device, inode type and if this refers to a device not the major/minor.
+         *
+         * Note that we don't care if file attributes such as ownership or access mode change, this here is
+         * 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 */
+                a->st_mtime == b->st_mtime &&
+                (!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 */
+}
index 81607483121d66839bd93346d88a6fc05f203c5a..59aedcb7c4d727bfa1ecce990e6148c3c6cb21be 100644 (file)
@@ -89,3 +89,5 @@ int device_path_make_canonical(mode_t mode, dev_t devno, char **ret);
 int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devno);
 
 int proc_mounted(void);
+
+bool stat_inode_unmodified(const struct stat *a, const struct stat *b);