|
|
bd1529 |
From 29c5b8dd6228c4401f034ca0aa85f99ac42cf8dd Mon Sep 17 00:00:00 2001
|
|
|
bd1529 |
From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= <msekleta@redhat.com>
|
|
|
bd1529 |
Date: Thu, 5 Nov 2020 17:55:25 +0100
|
|
|
bd1529 |
Subject: [PATCH] basic/stat-util: make mtime check stricter and use entire
|
|
|
bd1529 |
timestamp
|
|
|
bd1529 |
|
|
|
bd1529 |
Note that st_mtime member of struct stat is defined as follows,
|
|
|
bd1529 |
|
|
|
bd1529 |
#define st_mtime st_mtim.tv_sec
|
|
|
bd1529 |
|
|
|
bd1529 |
Hence we omitted checking nanosecond part of the timestamp (struct
|
|
|
bd1529 |
timespec) and possibly would miss modifications that happened within the
|
|
|
bd1529 |
same second.
|
|
|
bd1529 |
|
|
|
bd1529 |
(cherry picked from commit a59b0a9f768f6e27b25f4f1bab6de08842e78d74)
|
|
|
bd1529 |
|
|
|
bd1529 |
Related: #1642728
|
|
|
bd1529 |
---
|
|
|
bd1529 |
src/basic/stat-util.c | 22 ++++++++++++++++++++++
|
|
|
bd1529 |
src/basic/stat-util.h | 2 ++
|
|
|
bd1529 |
2 files changed, 24 insertions(+)
|
|
|
bd1529 |
|
|
|
bd1529 |
diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c
|
|
|
bd1529 |
index 26aee9bad6..c61c4c0517 100644
|
|
|
bd1529 |
--- a/src/basic/stat-util.c
|
|
|
bd1529 |
+++ b/src/basic/stat-util.c
|
|
|
bd1529 |
@@ -287,3 +287,25 @@ int fd_verify_regular(int fd) {
|
|
|
bd1529 |
|
|
|
bd1529 |
return stat_verify_regular(&st);
|
|
|
bd1529 |
}
|
|
|
bd1529 |
+
|
|
|
bd1529 |
+bool stat_inode_unmodified(const struct stat *a, const struct stat *b) {
|
|
|
bd1529 |
+
|
|
|
bd1529 |
+ /* Returns if the specified stat structures reference the same, unmodified inode. This check tries to
|
|
|
bd1529 |
+ * be reasonably careful when detecting changes: we check both inode and mtime, to cater for file
|
|
|
bd1529 |
+ * systems where mtimes are fixed to 0 (think: ostree/nixos type installations). We also check file
|
|
|
bd1529 |
+ * size, backing device, inode type and if this refers to a device not the major/minor.
|
|
|
bd1529 |
+ *
|
|
|
bd1529 |
+ * Note that we don't care if file attributes such as ownership or access mode change, this here is
|
|
|
bd1529 |
+ * about contents of the file. The purpose here is to detect file contents changes, and nothing
|
|
|
bd1529 |
+ * else. */
|
|
|
bd1529 |
+
|
|
|
bd1529 |
+ return a && b &&
|
|
|
bd1529 |
+ (a->st_mode & S_IFMT) != 0 && /* We use the check for .st_mode if the structure was ever initialized */
|
|
|
bd1529 |
+ ((a->st_mode ^ b->st_mode) & S_IFMT) == 0 && /* same inode type */
|
|
|
bd1529 |
+ a->st_mtim.tv_sec == b->st_mtim.tv_sec &&
|
|
|
bd1529 |
+ a->st_mtim.tv_nsec == b->st_mtim.tv_nsec &&
|
|
|
bd1529 |
+ (!S_ISREG(a->st_mode) || a->st_size == b->st_size) && /* if regular file, compare file size */
|
|
|
bd1529 |
+ a->st_dev == b->st_dev &&
|
|
|
bd1529 |
+ a->st_ino == b->st_ino &&
|
|
|
bd1529 |
+ (!(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 */
|
|
|
bd1529 |
+}
|
|
|
bd1529 |
\ No newline at end of file
|
|
|
bd1529 |
diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h
|
|
|
bd1529 |
index f8014ed30b..9e1a2b70da 100644
|
|
|
bd1529 |
--- a/src/basic/stat-util.h
|
|
|
bd1529 |
+++ b/src/basic/stat-util.h
|
|
|
bd1529 |
@@ -58,3 +58,5 @@ int path_is_temporary_fs(const char *path);
|
|
|
bd1529 |
|
|
|
bd1529 |
int stat_verify_regular(const struct stat *st);
|
|
|
bd1529 |
int fd_verify_regular(int fd);
|
|
|
bd1529 |
+
|
|
|
bd1529 |
+bool stat_inode_unmodified(const struct stat *a, const struct stat *b);
|