]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
stat-util: add explicit helpers for checking if stat/statx is initialized
authorLennart Poettering <lennart@poettering.net>
Tue, 12 Mar 2024 09:23:34 +0000 (10:23 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 12 Mar 2024 09:25:48 +0000 (10:25 +0100)
This is a follow-up for 945a8210c770801c8492eda03b6e9af3ec5d03a3 and
makes the st_dev check generic, so that we can reuse it some other
places. It also incorporates the non-NULL check now, to be a
comprehensive one-stop solution.

The helper is static inline so that compilers can optimize the redundant
checks away in case it is combined with other checks.

src/basic/stat-util.c
src/basic/stat-util.h
src/resolve/resolved-etc-hosts.c

index 70d5b7422416612a7e9e24270e07a784646fb5c6..6d09f8676678323ce0a7cfa8f8dd47a9f5e63312 100644 (file)
@@ -364,8 +364,7 @@ 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_dev != 0 && /* is the structure ever initialized? */
+        return stat_is_set(a) && stat_is_set(b) &&
                 ((a->st_mode ^ b->st_mode) & S_IFMT) == 0 &&  /* same inode type */
                 a->st_dev == b->st_dev &&
                 a->st_ino == b->st_ino;
@@ -393,7 +392,7 @@ bool statx_inode_same(const struct statx *a, const struct statx *b) {
 
         /* Same as stat_inode_same() but for struct statx */
 
-        return a && b &&
+        return statx_is_set(a) && statx_is_set(b) &&
                 FLAGS_SET(a->stx_mask, STATX_TYPE|STATX_INO) && FLAGS_SET(b->stx_mask, STATX_TYPE|STATX_INO) &&
                 ((a->stx_mode ^ b->stx_mode) & S_IFMT) == 0 &&
                 a->stx_dev_major == b->stx_dev_major &&
@@ -402,7 +401,7 @@ bool statx_inode_same(const struct statx *a, const struct statx *b) {
 }
 
 bool statx_mount_same(const struct new_statx *a, const struct new_statx *b) {
-        if (!a || !b)
+        if (!new_statx_is_set(a) || !new_statx_is_set(b))
                 return false;
 
         /* if we have the mount ID, that's all we need */
index c5dfd2db16a3f425eb3c44e621c8badc90b4a0cb..06bd9fdd97b7840c41328d1aeb0a05e6c367a5be 100644 (file)
@@ -9,6 +9,7 @@
 #include <sys/types.h>
 #include <sys/vfs.h>
 
+#include "fs-util.h"
 #include "macro.h"
 #include "missing_stat.h"
 #include "siphash24.h"
@@ -126,3 +127,18 @@ extern const struct hash_ops inode_hash_ops;
 
 const char* inode_type_to_string(mode_t m);
 mode_t inode_type_from_string(const char *s);
+
+/* Macros that check whether the stat/statx structures have been initialized already. For "struct stat" we
+ * use a check for .st_dev being non-zero, since the kernel unconditionally fills that in, mapping the file
+ * to its originating superblock, regardless if the fs is block based or virtual (we also check for .st_mode
+ * being MODE_INVALID, since we use that as an invalid marker for separate mode_t fields). For "struct statx"
+ * we use the .stx_mask field, which must be non-zero if any of the fields have already been initialized. */
+static inline bool stat_is_set(const struct stat *st) {
+        return st && st->st_dev != 0 && st->st_mode != MODE_INVALID;
+}
+static inline bool statx_is_set(const struct statx *sx) {
+        return sx && sx->stx_mask != 0;
+}
+static inline bool new_statx_is_set(const struct new_statx *sx) {
+        return sx && sx->stx_mask != 0;
+}
index 2d334d38ddf280a52c79022b2654e5e83456acfe..7b053862139f1ef2d4478558bea5d0219de497f0 100644 (file)
@@ -342,7 +342,7 @@ static int manager_etc_hosts_read(Manager *m) {
 
         m->etc_hosts_last = ts;
 
-        if (m->etc_hosts_stat.st_mode != 0) {
+        if (stat_is_set(&m->etc_hosts_stat)) {
                 if (stat("/etc/hosts", &st) < 0) {
                         if (errno != ENOENT)
                                 return log_error_errno(errno, "Failed to stat /etc/hosts: %m");